Merge
authorduke
Wed, 05 Jul 2017 20:00:59 +0200
changeset 26541 f82a4d6bc8c7
parent 26540 34aa137c3d5f (current diff)
parent 26525 071d5cb91855 (diff)
child 26542 9d0e6639a4d7
Merge
hotspot/test/compiler/intrinsics/mathexact/sanity/Verifier.java
jdk/src/java.base/share/conf/security/sunpkcs11-solaris.cfg
nashorn/test/script/basic/JDK-8048079_1.js
nashorn/test/script/basic/JDK-8048079_1.js.EXPECTED
nashorn/test/script/basic/JDK-8048079_2.js
nashorn/test/script/basic/JDK-8048079_2.js.EXPECTED
--- a/.hgtags-top-repo	Thu Sep 11 14:29:01 2014 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 20:00:59 2017 +0200
@@ -272,3 +272,4 @@
 ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27
 ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28
 9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29
+36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30
--- a/Makefile	Thu Sep 11 14:29:01 2014 -0700
+++ b/Makefile	Wed Jul 05 20:00:59 2017 +0200
@@ -108,12 +108,23 @@
       $(shell $(MKDIR) -p $(SJAVAC_SERVER_DIR) && $(RM) -rf $(SJAVAC_SERVER_DIR)/*)
     endif
 
+    # Split out the targets requiring sequential execution. Run these targets separately
+    # from the rest so that the rest may still enjoy full parallel execution.
+    SEQUENTIAL_TARGETS := $(filter dist-clean clean% reconfigure, $(MAIN_TARGETS))
+    PARALLEL_TARGETS := $(filter-out $(SEQUENTIAL_TARGETS), $(MAIN_TARGETS))
+
     main-wrapper:
-	@$(if $(findstring clean, $(MAIN_TARGETS)), , $(call AtMakeStart))
-	(cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \
-	    $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(MAIN_TARGETS) \
-	    $(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC)))
-	@$(if $(findstring clean, $(MAIN_TARGETS)), , $(call AtMakeEnd))
+        ifneq ($(SEQUENTIAL_TARGETS), )
+	  (cd $(root_dir)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \
+	      $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(SEQUENTIAL_TARGETS))
+        endif
+        ifneq ($(PARALLEL_TARGETS), )
+	  @$(call AtMakeStart)
+	  (cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \
+	      $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(PARALLEL_TARGETS) \
+	      $(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC)))
+	  @$(call AtMakeEnd)
+        endif
 
      .PHONY: main-wrapper
 
@@ -138,10 +149,9 @@
 	$(info .  make profiles          # Create complete j2re compact profile images)
 	$(info .  make bootcycle-images  # Build images twice, second time with newly built JDK)
 	$(info .  make install           # Install the generated images locally)
+	$(info .  make reconfigure       # Rerun configure with the same arguments as last time)
 	$(info .  make clean             # Remove all files generated by make, but not those)
-	$(info .                         # generated by configure. Do not run clean and other)
-	$(info .                         # targets together as that might behave in an)
-	$(info .                         # unexpected way.)
+	$(info .                         # generated by configure)
 	$(info .  make dist-clean        # Remove all files, including configuration)
 	$(info .  make help              # Give some help on using make)
 	$(info .  make test              # Run tests, default is all tests (see TEST below))
--- a/common/autoconf/configure.ac	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/configure.ac	Wed Jul 05 20:00:59 2017 +0200
@@ -54,6 +54,7 @@
 
 AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK])
 AC_DEFUN_ONCE([CUSTOM_LATE_HOOK])
+AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK])
 
 # This line needs to be here, verbatim, after all includes and the dummy hook
 # definitions. It is replaced with custom functionality when building
@@ -273,3 +274,4 @@
 
 # Finally output some useful information to the user
 HELP_PRINT_SUMMARY_AND_WARNINGS
+CUSTOM_SUMMARY_AND_WARNINGS_HOOK
--- a/common/autoconf/generated-configure.sh	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 20:00:59 2017 +0200
@@ -753,6 +753,7 @@
 GNM
 NM
 STRIP
+MSBUILD
 DUMPBIN
 RC
 MT
@@ -1088,6 +1089,7 @@
 with_freetype
 with_freetype_include
 with_freetype_lib
+with_freetype_src
 enable_freetype_bundling
 with_alsa
 with_alsa_include
@@ -1942,6 +1944,9 @@
                           headers under PATH/include)
   --with-freetype-include specify directory for the freetype include files
   --with-freetype-lib     specify directory for the freetype library
+  --with-freetype-src     specify directory with freetype sources to
+                          automatically build the library (experimental,
+                          Windows-only)
   --with-alsa             specify prefix directory for the alsa package
                           (expecting the libraries under PATH/lib and the
                           headers under PATH/include)
@@ -3882,20 +3887,18 @@
       HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'."
       ;;
     freetype)
-      if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then
-        HELP_MSG="To install freetype, run:
-wget \"http://gnuwin32.sourceforge.net/downlinks/freetype.php\" -O /tmp/freetype-setup.exe
-chmod +x /tmp/freetype-setup.exe
-/tmp/freetype-setup.exe
-Follow GUI prompts, and install to default directory \"C:\Program Files (x86)\GnuWin32\".
-After installation, locate lib/libfreetype.dll.a and make a copy with the name freetype.dll."
-      else
-        HELP_MSG="You need to build a 64-bit version of freetype.
-This is not readily available.
-You can find source code and build instructions on
-http://www.freetype.org/
-If you put the resulting build in \"C:\Program Files\GnuWin32\", it will be found automatically."
-      fi
+      HELP_MSG="
+The freetype library can now be build during the configure process.
+Download the freetype sources and unpack them into an arbitrary directory:
+
+wget http://download.savannah.gnu.org/releases/freetype/freetype-2.5.3.tar.gz
+tar -xzf freetype-2.5.3.tar.gz
+
+Then run configure with '--with-freetype-src=<freetype_src>'. This will
+automatically build the freetype library into '<freetype_src>/lib64' for 64-bit
+builds or into '<freetype_src>/lib32' for 32-bit builds.
+Afterwards you can always use '--with-freetype-include=<freetype_src>/include'
+and '--with-freetype-lib=<freetype_src>/lib32|64' for other builds."
       ;;
   esac
 }
@@ -4061,6 +4064,8 @@
 
 
 
+
+
 #
 # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4315,13 +4320,14 @@
 
 
 
+
 # This line needs to be here, verbatim, after all includes and the dummy hook
 # definitions. It is replaced with custom functionality when building
 # custom sources.
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1409311712
+DATE_WHEN_GENERATED=1410377275
 
 ###############################################################################
 #
@@ -26881,6 +26887,10 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
@@ -26922,6 +26932,10 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
@@ -26952,6 +26966,10 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
@@ -26981,6 +26999,10 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
@@ -27009,6 +27031,10 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5
 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;}
@@ -27051,6 +27077,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5
 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;}
@@ -27093,6 +27123,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5
 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;}
@@ -27135,6 +27169,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5
 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;}
@@ -27176,6 +27214,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5
 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;}
@@ -27216,6 +27258,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5
 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;}
@@ -35112,6 +35158,50 @@
 $as_echo "$as_me: Rewriting DUMPBIN to \"$new_complete\"" >&6;}
   fi
 
+    # We need to check for 'msbuild.exe' because at the place where we expect to
+    # find 'msbuild.exe' there's also a directory called 'msbuild' and configure
+    # won't find the 'msbuild.exe' executable in that case (and the
+    # 'ac_executable_extensions' is unusable due to performance reasons).
+    # Notice that we intentionally don't fix up the path to MSBUILD because we
+    # will call it in a DOS shell during freetype detection on Windows (see
+    # 'LIB_SETUP_FREETYPE' in "libraries.m4"
+    # Extract the first word of "msbuild.exe", so it can be a program name with args.
+set dummy msbuild.exe; 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_MSBUILD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MSBUILD"; then
+  ac_cv_prog_MSBUILD="$MSBUILD" # 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_MSBUILD="msbuild.exe"
+    $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
+MSBUILD=$ac_cv_prog_MSBUILD
+if test -n "$MSBUILD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSBUILD" >&5
+$as_echo "$MSBUILD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
   fi
 
   if test "x$OPENJDK_TARGET_OS" = xsolaris; then
@@ -44318,6 +44408,12 @@
   withval=$with_freetype_lib;
 fi
 
+
+# Check whether --with-freetype-src was given.
+if test "${with_freetype_src+set}" = set; then :
+  withval=$with_freetype_src;
+fi
+
   # Check whether --enable-freetype-bundling was given.
 if test "${enable_freetype_bundling+set}" = set; then :
   enableval=$enable_freetype_bundling;
@@ -44329,7 +44425,7 @@
   FREETYPE_BUNDLE_LIB_PATH=
 
   if test "x$FREETYPE_NOT_NEEDED" = xyes; then
-    if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then
+    if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: freetype not used, so --with-freetype is ignored" >&5
 $as_echo "$as_me: WARNING: freetype not used, so --with-freetype is ignored" >&2;}
     fi
@@ -44342,6 +44438,429 @@
 
     BUNDLE_FREETYPE="$enable_freetype_bundling"
 
+    if  test "x$with_freetype_src" != x; then
+      if test "x$OPENJDK_TARGET_OS" = xwindows; then
+        # Try to build freetype if --with-freetype-src was given on Windows
+
+  FREETYPE_SRC_PATH="$with_freetype_src"
+  BUILD_FREETYPE=yes
+
+  # Check if the freetype sources are acessible..
+  if ! test -d $FREETYPE_SRC_PATH; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-freetype-src specified, but can't find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: --with-freetype-src specified, but can't find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&2;}
+    BUILD_FREETYPE=no
+  fi
+  # ..and contain a vc2010 project file
+  vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj"
+  if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&2;}
+    BUILD_FREETYPE=no
+  fi
+  # Now check if configure found a version of 'msbuild.exe'
+  if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&2;}
+    BUILD_FREETYPE=no
+  fi
+
+  # Ready to go..
+  if test "x$BUILD_FREETYPE" = xyes; then
+
+    # msbuild requires trailing slashes for output directories
+    freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/"
+    freetype_lib_path_unix="$freetype_lib_path"
+    freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/"
+
+  unix_path="$vcxproj_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    windows_path=`$CYGPATH -m "$unix_path"`
+    vcxproj_path="$windows_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    windows_path=`cmd //c echo $unix_path`
+    vcxproj_path="$windows_path"
+  fi
+
+
+  unix_path="$freetype_lib_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    windows_path=`$CYGPATH -m "$unix_path"`
+    freetype_lib_path="$windows_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    windows_path=`cmd //c echo $unix_path`
+    freetype_lib_path="$windows_path"
+  fi
+
+
+  unix_path="$freetype_obj_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    windows_path=`$CYGPATH -m "$unix_path"`
+    freetype_obj_path="$windows_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    windows_path=`cmd //c echo $unix_path`
+    freetype_obj_path="$windows_path"
+  fi
+
+    if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+      freetype_platform=x64
+    else
+      freetype_platform=win32
+    fi
+
+    # The original freetype project file is for VS 2010 (i.e. 'v100'),
+    # so we have to adapt the toolset if building with any other toolsed (i.e. SDK).
+    # Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/
+    # 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&5
+$as_echo "$as_me: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&6;}
+
+    # First we try to build the freetype.dll
+    $ECHO -e "@echo off\n"\
+	     "$MSBUILD $vcxproj_path "\
+		       "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+		       "/p:Configuration=\"Release Multithreaded\" "\
+		       "/p:Platform=$freetype_platform "\
+		       "/p:ConfigurationType=DynamicLibrary "\
+		       "/p:TargetName=freetype "\
+		       "/p:OutDir=\"$freetype_lib_path\" "\
+		       "/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat
+    cmd /c freetype.bat
+
+    if test -s "$freetype_lib_path_unix/freetype.dll"; then
+      # If that succeeds we also build freetype.lib
+      $ECHO -e "@echo off\n"\
+	       "$MSBUILD $vcxproj_path "\
+			 "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+			 "/p:Configuration=\"Release Multithreaded\" "\
+			 "/p:Platform=$freetype_platform "\
+			 "/p:ConfigurationType=StaticLibrary "\
+			 "/p:TargetName=freetype "\
+			 "/p:OutDir=\"$freetype_lib_path\" "\
+			 "/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat
+      cmd /c freetype.bat
+
+      if test -s "$freetype_lib_path_unix/freetype.lib"; then
+	# Once we build both, lib and dll, set freetype lib and include path appropriately
+	POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include"
+	POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix"
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: Compiling freetype sources succeeded! (see freetype.log for build results)" >&5
+$as_echo "$as_me: Compiling freetype sources succeeded! (see freetype.log for build results)" >&6;}
+      else
+	BUILD_FREETYPE=no
+      fi
+    else
+      BUILD_FREETYPE=no
+    fi
+  fi
+
+        if test "x$BUILD_FREETYPE" = xyes; then
+          # Okay, we built it. Check that it works.
+
+  POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+  METHOD="--with-freetype-src"
+
+  # First check if the files exists.
+  if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+    # We found an arbitrary include file. That's a good sign.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+    FOUND_FREETYPE=yes
+
+    FREETYPE_LIB_NAME="${LIBRARY_PREFIX}freetype${SHARED_LIBRARY_SUFFIX}"
+    if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+      FOUND_FREETYPE=no
+    else
+      if test "x$OPENJDK_TARGET_OS" = xwindows; then
+        # On Windows, we will need both .lib and .dll file.
+        if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/freetype.lib"; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;}
+          FOUND_FREETYPE=no
+        fi
+      elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+          && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+        # Found lib in isa dir, use that instead.
+        POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+      fi
+    fi
+  fi
+
+  if test "x$FOUND_FREETYPE" = xyes; then
+
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-stile (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+  else
+    # We're on a posix platform. Hooray! :)
+    path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+    has_space=`$ECHO "$path" | $GREP " "`
+    if test "x$has_space" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+    fi
+
+    # Use eval to expand a potential ~
+    eval path="$path"
+    if test ! -f "$path" && test ! -d "$path"; then
+      as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+    fi
+
+    POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-stile (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+  else
+    # We're on a posix platform. Hooray! :)
+    path="$POTENTIAL_FREETYPE_LIB_PATH"
+    has_space=`$ECHO "$path" | $GREP " "`
+    if test "x$has_space" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+    fi
+
+    # Use eval to expand a potential ~
+    eval path="$path"
+    if test ! -f "$path" && test ! -d "$path"; then
+      as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+    fi
+
+    POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+
+    FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+    FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+  fi
+
+          if test "x$FOUND_FREETYPE" != xyes; then
+            as_fn_error $? "Can not use the built freetype at location given by --with-freetype-src" "$LINENO" 5
+          fi
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)" >&5
+$as_echo "$as_me: User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)" >&6;}
+          as_fn_error $? "Consider building freetype manually and using --with-freetype instead." "$LINENO" 5
+        fi
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-freetype-src is currently only supported on Windows - ignoring" >&5
+$as_echo "$as_me: WARNING: --with-freetype-src is currently only supported on Windows - ignoring" >&2;}
+      fi
+    fi
+
     if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then
       # User has specified settings
 
@@ -51828,3 +52347,4 @@
     printf "\n"
   fi
 
+
--- a/common/autoconf/help.m4	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/help.m4	Wed Jul 05 20:00:59 2017 +0200
@@ -75,20 +75,18 @@
       HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'."
       ;;
     freetype)
-      if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then
-        HELP_MSG="To install freetype, run:
-wget \"http://gnuwin32.sourceforge.net/downlinks/freetype.php\" -O /tmp/freetype-setup.exe
-chmod +x /tmp/freetype-setup.exe
-/tmp/freetype-setup.exe
-Follow GUI prompts, and install to default directory \"C:\Program Files (x86)\GnuWin32\".
-After installation, locate lib/libfreetype.dll.a and make a copy with the name freetype.dll."
-      else
-        HELP_MSG="You need to build a 64-bit version of freetype.
-This is not readily available.
-You can find source code and build instructions on
-http://www.freetype.org/
-If you put the resulting build in \"C:\Program Files\GnuWin32\", it will be found automatically."
-      fi
+      HELP_MSG="
+The freetype library can now be build during the configure process.
+Download the freetype sources and unpack them into an arbitrary directory:
+
+wget http://download.savannah.gnu.org/releases/freetype/freetype-2.5.3.tar.gz
+tar -xzf freetype-2.5.3.tar.gz
+
+Then run configure with '--with-freetype-src=<freetype_src>'. This will
+automatically build the freetype library into '<freetype_src>/lib64' for 64-bit
+builds or into '<freetype_src>/lib32' for 32-bit builds.
+Afterwards you can always use '--with-freetype-include=<freetype_src>/include'
+and '--with-freetype-lib=<freetype_src>/lib[32|64]' for other builds."
       ;;
   esac
 }
--- a/common/autoconf/libraries.m4	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/libraries.m4	Wed Jul 05 20:00:59 2017 +0200
@@ -247,12 +247,95 @@
 
 ])
 
+AC_DEFUN([LIB_BUILD_FREETYPE],
+[
+  FREETYPE_SRC_PATH="$1"
+  BUILD_FREETYPE=yes
+
+  # Check if the freetype sources are acessible..
+  if ! test -d $FREETYPE_SRC_PATH; then
+    AC_MSG_WARN([--with-freetype-src specified, but can't find path "$FREETYPE_SRC_PATH" - ignoring --with-freetype-src])
+    BUILD_FREETYPE=no
+  fi
+  # ..and contain a vc2010 project file
+  vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj"
+  if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then
+    AC_MSG_WARN([Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src])
+    BUILD_FREETYPE=no
+  fi
+  # Now check if configure found a version of 'msbuild.exe'
+  if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then
+    AC_MSG_WARN([Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src])
+    BUILD_FREETYPE=no
+  fi
+
+  # Ready to go..
+  if test "x$BUILD_FREETYPE" = xyes; then
+
+    # msbuild requires trailing slashes for output directories
+    freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/"
+    freetype_lib_path_unix="$freetype_lib_path"
+    freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/"
+    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(vcxproj_path)
+    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_lib_path)
+    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_obj_path)
+    if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+      freetype_platform=x64
+    else
+      freetype_platform=win32
+    fi
+
+    # The original freetype project file is for VS 2010 (i.e. 'v100'),
+    # so we have to adapt the toolset if building with any other toolsed (i.e. SDK).
+    # Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/
+    # 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4
+    AC_MSG_NOTICE([Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ...])
+
+    # First we try to build the freetype.dll
+    $ECHO -e "@echo off\n"\
+	     "$MSBUILD $vcxproj_path "\
+		       "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+		       "/p:Configuration=\"Release Multithreaded\" "\
+		       "/p:Platform=$freetype_platform "\
+		       "/p:ConfigurationType=DynamicLibrary "\
+		       "/p:TargetName=freetype "\
+		       "/p:OutDir=\"$freetype_lib_path\" "\
+		       "/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat
+    cmd /c freetype.bat
+
+    if test -s "$freetype_lib_path_unix/freetype.dll"; then
+      # If that succeeds we also build freetype.lib
+      $ECHO -e "@echo off\n"\
+	       "$MSBUILD $vcxproj_path "\
+			 "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+			 "/p:Configuration=\"Release Multithreaded\" "\
+			 "/p:Platform=$freetype_platform "\
+			 "/p:ConfigurationType=StaticLibrary "\
+			 "/p:TargetName=freetype "\
+			 "/p:OutDir=\"$freetype_lib_path\" "\
+			 "/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat
+      cmd /c freetype.bat
+
+      if test -s "$freetype_lib_path_unix/freetype.lib"; then
+	# Once we build both, lib and dll, set freetype lib and include path appropriately
+	POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include"
+	POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix"
+	AC_MSG_NOTICE([Compiling freetype sources succeeded! (see freetype.log for build results)])
+      else
+	BUILD_FREETYPE=no
+      fi
+    else
+      BUILD_FREETYPE=no
+    fi
+  fi
+])
+
 AC_DEFUN([LIB_CHECK_POTENTIAL_FREETYPE],
 [
   POTENTIAL_FREETYPE_INCLUDE_PATH="$1"
   POTENTIAL_FREETYPE_LIB_PATH="$2"
   METHOD="$3"
-  
+
   # First check if the files exists.
   if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
     # We found an arbitrary include file. That's a good sign.
@@ -305,6 +388,8 @@
       [specify directory for the freetype include files])])
   AC_ARG_WITH(freetype-lib, [AS_HELP_STRING([--with-freetype-lib],
       [specify directory for the freetype library])])
+  AC_ARG_WITH(freetype-src, [AS_HELP_STRING([--with-freetype-src],
+      [specify directory with freetype sources to automatically build the library (experimental, Windows-only)])])
   AC_ARG_ENABLE(freetype-bundling, [AS_HELP_STRING([--disable-freetype-bundling],
       [disable bundling of the freetype library with the build result @<:@enabled on Windows or when using --with-freetype, disabled otherwise@:>@])])
 
@@ -313,7 +398,7 @@
   FREETYPE_BUNDLE_LIB_PATH=
 
   if test "x$FREETYPE_NOT_NEEDED" = xyes; then
-    if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then
+    if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then
       AC_MSG_WARN([freetype not used, so --with-freetype is ignored])
     fi
     if test "x$enable_freetype_bundling" != x; then
@@ -324,6 +409,25 @@
 
     BUNDLE_FREETYPE="$enable_freetype_bundling"
 
+    if  test "x$with_freetype_src" != x; then
+      if test "x$OPENJDK_TARGET_OS" = xwindows; then
+        # Try to build freetype if --with-freetype-src was given on Windows
+        LIB_BUILD_FREETYPE([$with_freetype_src])
+        if test "x$BUILD_FREETYPE" = xyes; then
+          # Okay, we built it. Check that it works.
+          LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH, $POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype-src])
+          if test "x$FOUND_FREETYPE" != xyes; then
+            AC_MSG_ERROR([Can not use the built freetype at location given by --with-freetype-src])
+          fi
+        else
+          AC_MSG_NOTICE([User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)])
+          AC_MSG_ERROR([Consider building freetype manually and using --with-freetype instead.])
+        fi
+      else
+        AC_MSG_WARN([--with-freetype-src is currently only supported on Windows - ignoring])
+      fi
+    fi
+
     if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then
       # User has specified settings
 
@@ -331,12 +435,12 @@
         # If not specified, default is to bundle freetype
         BUNDLE_FREETYPE=yes
       fi
-      
+
       if test "x$with_freetype" != x; then
         POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype/include"
         POTENTIAL_FREETYPE_LIB_PATH="$with_freetype/lib"
       fi
-      
+
       # Allow --with-freetype-lib and --with-freetype-include to override
       if test "x$with_freetype_include" != x; then
         POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype_include"
@@ -468,7 +572,7 @@
         FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH"
       fi
     fi
-    
+
     if test "x$FREETYPE_LIBS" = x; then
       BASIC_FIXUP_PATH(FREETYPE_LIB_PATH)
       if test "x$OPENJDK_TARGET_OS" = xwindows; then
@@ -484,7 +588,7 @@
     PREV_CXXCFLAGS="$CXXFLAGS"
     PREV_LIBS="$LIBS"
     PREV_CXX="$CXX"
-    CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS" 
+    CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS"
     LIBS="$LIBS $FREETYPE_LIBS"
     CXX="$FIXPATH $CXX"
     AC_LINK_IFELSE([AC_LANG_SOURCE([[
@@ -502,9 +606,9 @@
           AC_MSG_RESULT([no])
           AC_MSG_NOTICE([Could not compile and link with freetype. This might be a 32/64-bit mismatch.])
           AC_MSG_NOTICE([Using FREETYPE_CFLAGS=$FREETYPE_CFLAGS and FREETYPE_LIBS=$FREETYPE_LIBS])
-          
+
           HELP_MSG_MISSING_DEPENDENCY([freetype])
-          
+
           AC_MSG_ERROR([Can not continue without freetype. $HELP_MSG])
         ]
     )
--- a/common/autoconf/toolchain.m4	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 20:00:59 2017 +0200
@@ -557,6 +557,14 @@
     BASIC_FIXUP_EXECUTABLE(RC)
     AC_CHECK_PROG([DUMPBIN], [dumpbin], [dumpbin],,,)
     BASIC_FIXUP_EXECUTABLE(DUMPBIN)
+    # We need to check for 'msbuild.exe' because at the place where we expect to
+    # find 'msbuild.exe' there's also a directory called 'msbuild' and configure
+    # won't find the 'msbuild.exe' executable in that case (and the
+    # 'ac_executable_extensions' is unusable due to performance reasons).
+    # Notice that we intentionally don't fix up the path to MSBUILD because we
+    # will call it in a DOS shell during freetype detection on Windows (see
+    # 'LIB_SETUP_FREETYPE' in "libraries.m4"
+    AC_CHECK_PROG([MSBUILD], [msbuild.exe], [msbuild.exe],,,)
   fi
 
   if test "x$OPENJDK_TARGET_OS" = xsolaris; then
--- a/common/autoconf/toolchain_windows.m4	Thu Sep 11 14:29:01 2014 -0700
+++ b/common/autoconf/toolchain_windows.m4	Wed Jul 05 20:00:59 2017 +0200
@@ -33,6 +33,10 @@
       if test -f "$VS100BASE/$VCVARSFILE"; then
         AC_MSG_NOTICE([Found Visual Studio installation at $VS100BASE using $METHOD])
         VS_ENV_CMD="$VS100BASE/$VCVARSFILE"
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013
+        # TODO: improve detection for other versions of VS
+        PLATFORM_TOOLSET="v100"
       else
         AC_MSG_NOTICE([Found Visual Studio installation at $VS100BASE using $METHOD])
         AC_MSG_NOTICE([Warning: $VCVARSFILE is missing, this is probably Visual Studio Express. Ignoring])
@@ -61,6 +65,10 @@
         else
           VS_ENV_ARGS="/x64"
         fi
+        # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see
+        # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK
+        # TODO: improve detection for other versions of SDK
+        PLATFORM_TOOLSET="Windows7.1SDK"
       else
         AC_MSG_NOTICE([Found Windows SDK installation at $WIN_SDK_BASE using $METHOD])
         AC_MSG_NOTICE([Warning: Installation is broken, SetEnv.Cmd is missing. Ignoring])
--- a/corba/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/corba/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^webrev
 /nbproject/private/
 ^.hgtip
 .DS_Store
--- a/corba/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/corba/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -272,3 +272,4 @@
 7e06bf1dcb0907b80ddf59315426ce9ce775e56d jdk9-b27
 a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28
 163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29
+98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30
--- a/hotspot/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^webrev
 /nbproject/private/
 ^src/share/tools/hsdis/build/
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
--- a/hotspot/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -432,3 +432,4 @@
 f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27
 657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28
 deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29
+5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30
--- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c	Wed Jul 05 20:00:59 2017 +0200
@@ -64,7 +64,10 @@
 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
 
 void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
-  (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+  jclass clazz;
+  clazz = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
+  CHECK_EXCEPTION;
+  (*env)->ThrowNew(env, clazz, errMsg);
 }
 
 struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
@@ -149,11 +152,14 @@
      const char* name;
      jobject loadObject;
      jobject loadObjectList;
+     jstring str;
 
      base = get_lib_base(ph, i);
      name = get_lib_name(ph, i);
-     loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
-                                   (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
+
+     str = (*env)->NewStringUTF(env, name);
+     CHECK_EXCEPTION;
+     loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, str, (jlong)0, (jlong)base);
      CHECK_EXCEPTION;
      loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
      CHECK_EXCEPTION;
@@ -298,13 +304,18 @@
 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByAddress0
   (JNIEnv *env, jobject this_obj, jlong addr) {
   uintptr_t offset;
+  jobject obj;
+  jstring str;
   const char* sym = NULL;
 
   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
   if (sym == NULL) return 0;
-  return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
-                          (*env)->NewStringUTF(env, sym), (jlong)offset);
+  str = (*env)->NewStringUTF(env, sym);
+  CHECK_EXCEPTION_(NULL);
+  obj = (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, str, (jlong)offset);
+  CHECK_EXCEPTION_(NULL);
+  return obj;
 }
 
 /*
--- a/hotspot/agent/src/os/solaris/proc/saproc.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/agent/src/os/solaris/proc/saproc.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -90,7 +90,9 @@
 */
 
 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
-  env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+  jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
+  CHECK_EXCEPTION;
+  env->ThrowNew(clazz, errMsg);
 }
 
 // JNI ids for some fields, methods
@@ -962,6 +964,7 @@
   CHECK_EXCEPTION_(0);
   jboolean isCopy;
   jlong* ptr = env->GetLongArrayElements(res, &isCopy);
+  CHECK_EXCEPTION_(NULL);
   for (int i = 0; i < NPRGREG; i++) {
     ptr[i] = (jlong) (uintptr_t) gregs[i];
   }
@@ -1253,6 +1256,7 @@
   (JNIEnv *env, jobject this_object, jstring name) {
   jboolean isCopy;
   const char* ptr = env->GetStringUTFChars(name, &isCopy);
+  CHECK_EXCEPTION_(NULL);
   char  buf[2*SYMBOL_BUF_SIZE + 1];
   jstring res = 0;
   if (cplus_demangle((char*) ptr, buf, sizeof(buf)) != DEMANGLE_ESPACE) {
@@ -1439,7 +1443,9 @@
                             "createClosestSymbol", "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
   CHECK_EXCEPTION;
 
-  listAdd_ID = env->GetMethodID(env->FindClass("java/util/List"), "add", "(Ljava/lang/Object;)Z");
+  jclass list_clazz = env->FindClass("java/util/List");
+  CHECK_EXCEPTION;
+  listAdd_ID = env->GetMethodID(list_clazz, "add", "(Ljava/lang/Object;)Z");
   CHECK_EXCEPTION;
 
   // part of the class sharing workaround
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -49,7 +49,6 @@
     higherDimension    = new MetadataField(type.getAddressField("_higher_dimension"), 0);
     lowerDimension     = new MetadataField(type.getAddressField("_lower_dimension"), 0);
     vtableLen          = new CIntField(type.getCIntegerField("_vtable_len"), 0);
-    componentMirror    = new OopField(type.getOopField("_component_mirror"), 0);
     javaLangCloneableName = null;
     javaLangObjectName = null;
     javaIoSerializableName = null;
@@ -63,7 +62,6 @@
   private static MetadataField  higherDimension;
   private static MetadataField  lowerDimension;
   private static CIntField vtableLen;
-  private static OopField  componentMirror;
 
   public Klass getJavaSuper() {
     SystemDictionary sysDict = VM.getVM().getSystemDictionary();
@@ -74,7 +72,6 @@
   public Klass getHigherDimension() { return (Klass) higherDimension.getValue(this); }
   public Klass getLowerDimension()  { return (Klass) lowerDimension.getValue(this); }
   public long  getVtableLen()       { return         vtableLen.getValue(this); }
-  public Oop   getComponentMirror() { return         componentMirror.getValue(this); }
 
   // constant class names - javaLangCloneable, javaIoSerializable, javaLangObject
   // Initialized lazily to avoid initialization ordering dependencies between ArrayKlass and SymbolTable
@@ -144,6 +141,5 @@
     visitor.doMetadata(higherDimension, true);
     visitor.doMetadata(lowerDimension, true);
       visitor.doCInt(vtableLen, true);
-      visitor.doOop(componentMirror, true);
     }
   }
--- a/hotspot/make/Makefile	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/Makefile	Wed Jul 05 20:00:59 2017 +0200
@@ -337,7 +337,7 @@
 export_product_jdk::
 	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
 export_optimized_jdk::
-	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
 export_fastdebug_jdk::
 	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
 export_debug_jdk::
--- a/hotspot/make/aix/makefiles/mapfile-vers-debug	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/aix/makefiles/mapfile-vers-debug	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/aix/makefiles/mapfile-vers-product	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/aix/makefiles/mapfile-vers-product	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/bsd/makefiles/gcc.make	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/bsd/makefiles/gcc.make	Wed Jul 05 20:00:59 2017 +0200
@@ -325,6 +325,10 @@
   else ifeq ($(shell expr $(CC_VER_MAJOR) = 5 \& $(CC_VER_MINOR) = 1), 1)
     OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
     OPT_CFLAGS/unsafe.o += -O1
+  # Clang 6.0 
+  else ifeq ($(shell expr $(CC_VER_MAJOR) = 6 \& $(CC_VER_MINOR) = 0), 1) 
+    OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) 
+    OPT_CFLAGS/unsafe.o += -O1 
   else
     $(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
   endif
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -123,7 +123,6 @@
                 _JVM_GetClassSignature
                 _JVM_GetClassSigners
                 _JVM_GetClassTypeAnnotations
-                _JVM_GetComponentType
                 _JVM_GetDeclaredClasses
                 _JVM_GetDeclaringClass
                 _JVM_GetEnclosingMethodInfo
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -123,7 +123,6 @@
                 _JVM_GetClassSignature
                 _JVM_GetClassSigners
                 _JVM_GetClassTypeAnnotations
-                _JVM_GetComponentType
                 _JVM_GetDeclaredClasses
                 _JVM_GetDeclaringClass
                 _JVM_GetEnclosingMethodInfo
--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/bsd/makefiles/mapfile-vers-product	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-product	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/linux/makefiles/mapfile-vers-product	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -125,7 +125,6 @@
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
-                JVM_GetComponentType;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
                 JVM_GetEnclosingMethodInfo;
--- a/hotspot/make/solaris/makefiles/mapfile-vers	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/solaris/makefiles/mapfile-vers	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 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
@@ -124,7 +124,6 @@
                 JVM_GetClassNameUTF;
                 JVM_GetClassSignature;
                 JVM_GetClassSigners;
-                JVM_GetComponentType;
                 JVM_GetClassTypeAnnotations;
                 JVM_GetDeclaredClasses;
                 JVM_GetDeclaringClass;
--- a/hotspot/make/solaris/makefiles/sparcWorks.make	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 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
@@ -53,9 +53,9 @@
   VALIDATED_COMPILER_REVS   := 5.8
   VALIDATED_CC_COMPILER_REVS := 5.8
 else
-  # Validated compiler for JDK7 is SS12 update 1 + patches (5.10)
-  VALIDATED_COMPILER_REVS   := 5.10
-  VALIDATED_CC_COMPILER_REVS := 5.10
+  # Validated compiler for JDK9 is SS12.3 (5.12)
+  VALIDATED_COMPILER_REVS   := 5.12
+  VALIDATED_CC_COMPILER_REVS := 5.12
 endif
 
 # Warning messages about not using the above validated versions
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -4937,6 +4937,26 @@
   emit_arith(0x03, 0xC0, dst, src);
 }
 
+void Assembler::adcxq(Register dst, Register src) {
+  //assert(VM_Version::supports_adx(), "adx instructions not supported");
+  emit_int8((unsigned char)0x66);
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_int8(0x0F);
+  emit_int8(0x38);
+  emit_int8((unsigned char)0xF6);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::adoxq(Register dst, Register src) {
+  //assert(VM_Version::supports_adx(), "adx instructions not supported");
+  emit_int8((unsigned char)0xF3);
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_int8(0x0F);
+  emit_int8(0x38);
+  emit_int8((unsigned char)0xF6);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
 void Assembler::andq(Address dst, int32_t imm32) {
   InstructionMark im(this);
   prefixq(dst);
@@ -5444,6 +5464,26 @@
   emit_int8((unsigned char)(0xC0 | encode));
 }
 
+void Assembler::mulq(Address src) {
+  InstructionMark im(this);
+  prefixq(src);
+  emit_int8((unsigned char)0xF7);
+  emit_operand(rsp, src);
+}
+
+void Assembler::mulq(Register src) {
+  int encode = prefixq_and_encode(src->encoding());
+  emit_int8((unsigned char)0xF7);
+  emit_int8((unsigned char)(0xE0 | encode));
+}
+
+void Assembler::mulxq(Register dst1, Register dst2, Register src) {
+  assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
+  int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, true, false);
+  emit_int8((unsigned char)0xF6);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
 void Assembler::negq(Register dst) {
   int encode = prefixq_and_encode(dst->encoding());
   emit_int8((unsigned char)0xF7);
@@ -5572,6 +5612,28 @@
     emit_int8(imm8);
   }
 }
+
+void Assembler::rorq(Register dst, int imm8) {
+  assert(isShiftCount(imm8 >> 1), "illegal shift count");
+  int encode = prefixq_and_encode(dst->encoding());
+  if (imm8 == 1) {
+    emit_int8((unsigned char)0xD1);
+    emit_int8((unsigned char)(0xC8 | encode));
+  } else {
+    emit_int8((unsigned char)0xC1);
+    emit_int8((unsigned char)(0xc8 | encode));
+    emit_int8(imm8);
+  }
+}
+
+void Assembler::rorxq(Register dst, Register src, int imm8) {
+  assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
+  int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A, true, false);
+  emit_int8((unsigned char)0xF0);
+  emit_int8((unsigned char)(0xC0 | encode));
+  emit_int8(imm8);
+}
+
 void Assembler::sarq(Register dst, int imm8) {
   assert(isShiftCount(imm8 >> 1), "illegal shift count");
   int encode = prefixq_and_encode(dst->encoding());
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -888,6 +888,14 @@
   void addq(Register dst, Address src);
   void addq(Register dst, Register src);
 
+#ifdef _LP64
+ //Add Unsigned Integers with Carry Flag
+  void adcxq(Register dst, Register src);
+
+ //Add Unsigned Integers with Overflow Flag
+  void adoxq(Register dst, Register src);
+#endif
+
   void addr_nop_4();
   void addr_nop_5();
   void addr_nop_7();
@@ -1204,19 +1212,20 @@
   void idivl(Register src);
   void divl(Register src); // Unsigned division
 
+#ifdef _LP64
   void idivq(Register src);
+#endif
 
   void imull(Register dst, Register src);
   void imull(Register dst, Register src, int value);
   void imull(Register dst, Address src);
 
+#ifdef _LP64
   void imulq(Register dst, Register src);
   void imulq(Register dst, Register src, int value);
-#ifdef _LP64
   void imulq(Register dst, Address src);
 #endif
 
-
   // jcc is the generic conditional branch generator to run-
   // time routines, jcc is used for branches to labels. jcc
   // takes a branch opcode (cc) and a label (L) and generates
@@ -1408,9 +1417,16 @@
   void movzwq(Register dst, Register src);
 #endif
 
+  // Unsigned multiply with RAX destination register
   void mull(Address src);
   void mull(Register src);
 
+#ifdef _LP64
+  void mulq(Address src);
+  void mulq(Register src);
+  void mulxq(Register dst1, Register dst2, Register src);
+#endif
+
   // Multiply Scalar Double-Precision Floating-Point Values
   void mulsd(XMMRegister dst, Address src);
   void mulsd(XMMRegister dst, XMMRegister src);
@@ -1541,6 +1557,11 @@
 
   void ret(int imm16);
 
+#ifdef _LP64
+  void rorq(Register dst, int imm8);
+  void rorxq(Register dst, Register src, int imm8);
+#endif
+
   void sahf();
 
   void sarl(Register dst, int imm8);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -176,6 +176,8 @@
           "Use count trailing zeros instruction")                           \
                                                                             \
   product(bool, UseBMI1Instructions, false,                                 \
-          "Use BMI instructions")
-
+          "Use BMI1 instructions")                                          \
+                                                                            \
+  product(bool, UseBMI2Instructions, false,                                 \
+          "Use BMI2 instructions")
 #endif // CPU_X86_VM_GLOBALS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -7293,6 +7293,467 @@
   bind(L_done);
 }
 
+#ifdef _LP64
+/**
+ * Helper for multiply_to_len().
+ */
+void MacroAssembler::add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2) {
+  addq(dest_lo, src1);
+  adcq(dest_hi, 0);
+  addq(dest_lo, src2);
+  adcq(dest_hi, 0);
+}
+
+/**
+ * Multiply 64 bit by 64 bit first loop.
+ */
+void MacroAssembler::multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
+                                           Register y, Register y_idx, Register z,
+                                           Register carry, Register product,
+                                           Register idx, Register kdx) {
+  //
+  //  jlong carry, x[], y[], z[];
+  //  for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx-, kdx--) {
+  //    huge_128 product = y[idx] * x[xstart] + carry;
+  //    z[kdx] = (jlong)product;
+  //    carry  = (jlong)(product >>> 64);
+  //  }
+  //  z[xstart] = carry;
+  //
+
+  Label L_first_loop, L_first_loop_exit;
+  Label L_one_x, L_one_y, L_multiply;
+
+  decrementl(xstart);
+  jcc(Assembler::negative, L_one_x);
+
+  movq(x_xstart, Address(x, xstart, Address::times_4,  0));
+  rorq(x_xstart, 32); // convert big-endian to little-endian
+
+  bind(L_first_loop);
+  decrementl(idx);
+  jcc(Assembler::negative, L_first_loop_exit);
+  decrementl(idx);
+  jcc(Assembler::negative, L_one_y);
+  movq(y_idx, Address(y, idx, Address::times_4,  0));
+  rorq(y_idx, 32); // convert big-endian to little-endian
+  bind(L_multiply);
+  movq(product, x_xstart);
+  mulq(y_idx); // product(rax) * y_idx -> rdx:rax
+  addq(product, carry);
+  adcq(rdx, 0);
+  subl(kdx, 2);
+  movl(Address(z, kdx, Address::times_4,  4), product);
+  shrq(product, 32);
+  movl(Address(z, kdx, Address::times_4,  0), product);
+  movq(carry, rdx);
+  jmp(L_first_loop);
+
+  bind(L_one_y);
+  movl(y_idx, Address(y,  0));
+  jmp(L_multiply);
+
+  bind(L_one_x);
+  movl(x_xstart, Address(x,  0));
+  jmp(L_first_loop);
+
+  bind(L_first_loop_exit);
+}
+
+/**
+ * Multiply 64 bit by 64 bit and add 128 bit.
+ */
+void MacroAssembler::multiply_add_128_x_128(Register x_xstart, Register y, Register z,
+                                            Register yz_idx, Register idx,
+                                            Register carry, Register product, int offset) {
+  //     huge_128 product = (y[idx] * x_xstart) + z[kdx] + carry;
+  //     z[kdx] = (jlong)product;
+
+  movq(yz_idx, Address(y, idx, Address::times_4,  offset));
+  rorq(yz_idx, 32); // convert big-endian to little-endian
+  movq(product, x_xstart);
+  mulq(yz_idx);     // product(rax) * yz_idx -> rdx:product(rax)
+  movq(yz_idx, Address(z, idx, Address::times_4,  offset));
+  rorq(yz_idx, 32); // convert big-endian to little-endian
+
+  add2_with_carry(rdx, product, carry, yz_idx);
+
+  movl(Address(z, idx, Address::times_4,  offset+4), product);
+  shrq(product, 32);
+  movl(Address(z, idx, Address::times_4,  offset), product);
+
+}
+
+/**
+ * Multiply 128 bit by 128 bit. Unrolled inner loop.
+ */
+void MacroAssembler::multiply_128_x_128_loop(Register x_xstart, Register y, Register z,
+                                             Register yz_idx, Register idx, Register jdx,
+                                             Register carry, Register product,
+                                             Register carry2) {
+  //   jlong carry, x[], y[], z[];
+  //   int kdx = ystart+1;
+  //   for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop
+  //     huge_128 product = (y[idx+1] * x_xstart) + z[kdx+idx+1] + carry;
+  //     z[kdx+idx+1] = (jlong)product;
+  //     jlong carry2  = (jlong)(product >>> 64);
+  //     product = (y[idx] * x_xstart) + z[kdx+idx] + carry2;
+  //     z[kdx+idx] = (jlong)product;
+  //     carry  = (jlong)(product >>> 64);
+  //   }
+  //   idx += 2;
+  //   if (idx > 0) {
+  //     product = (y[idx] * x_xstart) + z[kdx+idx] + carry;
+  //     z[kdx+idx] = (jlong)product;
+  //     carry  = (jlong)(product >>> 64);
+  //   }
+  //
+
+  Label L_third_loop, L_third_loop_exit, L_post_third_loop_done;
+
+  movl(jdx, idx);
+  andl(jdx, 0xFFFFFFFC);
+  shrl(jdx, 2);
+
+  bind(L_third_loop);
+  subl(jdx, 1);
+  jcc(Assembler::negative, L_third_loop_exit);
+  subl(idx, 4);
+
+  multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product, 8);
+  movq(carry2, rdx);
+
+  multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry2, product, 0);
+  movq(carry, rdx);
+  jmp(L_third_loop);
+
+  bind (L_third_loop_exit);
+
+  andl (idx, 0x3);
+  jcc(Assembler::zero, L_post_third_loop_done);
+
+  Label L_check_1;
+  subl(idx, 2);
+  jcc(Assembler::negative, L_check_1);
+
+  multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product, 0);
+  movq(carry, rdx);
+
+  bind (L_check_1);
+  addl (idx, 0x2);
+  andl (idx, 0x1);
+  subl(idx, 1);
+  jcc(Assembler::negative, L_post_third_loop_done);
+
+  movl(yz_idx, Address(y, idx, Address::times_4,  0));
+  movq(product, x_xstart);
+  mulq(yz_idx); // product(rax) * yz_idx -> rdx:product(rax)
+  movl(yz_idx, Address(z, idx, Address::times_4,  0));
+
+  add2_with_carry(rdx, product, yz_idx, carry);
+
+  movl(Address(z, idx, Address::times_4,  0), product);
+  shrq(product, 32);
+
+  shlq(rdx, 32);
+  orq(product, rdx);
+  movq(carry, product);
+
+  bind(L_post_third_loop_done);
+}
+
+/**
+ * Multiply 128 bit by 128 bit using BMI2. Unrolled inner loop.
+ *
+ */
+void MacroAssembler::multiply_128_x_128_bmi2_loop(Register y, Register z,
+                                                  Register carry, Register carry2,
+                                                  Register idx, Register jdx,
+                                                  Register yz_idx1, Register yz_idx2,
+                                                  Register tmp, Register tmp3, Register tmp4) {
+  assert(UseBMI2Instructions, "should be used only when BMI2 is available");
+
+  //   jlong carry, x[], y[], z[];
+  //   int kdx = ystart+1;
+  //   for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop
+  //     huge_128 tmp3 = (y[idx+1] * rdx) + z[kdx+idx+1] + carry;
+  //     jlong carry2  = (jlong)(tmp3 >>> 64);
+  //     huge_128 tmp4 = (y[idx]   * rdx) + z[kdx+idx] + carry2;
+  //     carry  = (jlong)(tmp4 >>> 64);
+  //     z[kdx+idx+1] = (jlong)tmp3;
+  //     z[kdx+idx] = (jlong)tmp4;
+  //   }
+  //   idx += 2;
+  //   if (idx > 0) {
+  //     yz_idx1 = (y[idx] * rdx) + z[kdx+idx] + carry;
+  //     z[kdx+idx] = (jlong)yz_idx1;
+  //     carry  = (jlong)(yz_idx1 >>> 64);
+  //   }
+  //
+
+  Label L_third_loop, L_third_loop_exit, L_post_third_loop_done;
+
+  movl(jdx, idx);
+  andl(jdx, 0xFFFFFFFC);
+  shrl(jdx, 2);
+
+  bind(L_third_loop);
+  subl(jdx, 1);
+  jcc(Assembler::negative, L_third_loop_exit);
+  subl(idx, 4);
+
+  movq(yz_idx1,  Address(y, idx, Address::times_4,  8));
+  rorxq(yz_idx1, yz_idx1, 32); // convert big-endian to little-endian
+  movq(yz_idx2, Address(y, idx, Address::times_4,  0));
+  rorxq(yz_idx2, yz_idx2, 32);
+
+  mulxq(tmp4, tmp3, yz_idx1);  //  yz_idx1 * rdx -> tmp4:tmp3
+  mulxq(carry2, tmp, yz_idx2); //  yz_idx2 * rdx -> carry2:tmp
+
+  movq(yz_idx1,  Address(z, idx, Address::times_4,  8));
+  rorxq(yz_idx1, yz_idx1, 32);
+  movq(yz_idx2, Address(z, idx, Address::times_4,  0));
+  rorxq(yz_idx2, yz_idx2, 32);
+
+  if (VM_Version::supports_adx()) {
+    adcxq(tmp3, carry);
+    adoxq(tmp3, yz_idx1);
+
+    adcxq(tmp4, tmp);
+    adoxq(tmp4, yz_idx2);
+
+    movl(carry, 0); // does not affect flags
+    adcxq(carry2, carry);
+    adoxq(carry2, carry);
+  } else {
+    add2_with_carry(tmp4, tmp3, carry, yz_idx1);
+    add2_with_carry(carry2, tmp4, tmp, yz_idx2);
+  }
+  movq(carry, carry2);
+
+  movl(Address(z, idx, Address::times_4, 12), tmp3);
+  shrq(tmp3, 32);
+  movl(Address(z, idx, Address::times_4,  8), tmp3);
+
+  movl(Address(z, idx, Address::times_4,  4), tmp4);
+  shrq(tmp4, 32);
+  movl(Address(z, idx, Address::times_4,  0), tmp4);
+
+  jmp(L_third_loop);
+
+  bind (L_third_loop_exit);
+
+  andl (idx, 0x3);
+  jcc(Assembler::zero, L_post_third_loop_done);
+
+  Label L_check_1;
+  subl(idx, 2);
+  jcc(Assembler::negative, L_check_1);
+
+  movq(yz_idx1, Address(y, idx, Address::times_4,  0));
+  rorxq(yz_idx1, yz_idx1, 32);
+  mulxq(tmp4, tmp3, yz_idx1); //  yz_idx1 * rdx -> tmp4:tmp3
+  movq(yz_idx2, Address(z, idx, Address::times_4,  0));
+  rorxq(yz_idx2, yz_idx2, 32);
+
+  add2_with_carry(tmp4, tmp3, carry, yz_idx2);
+
+  movl(Address(z, idx, Address::times_4,  4), tmp3);
+  shrq(tmp3, 32);
+  movl(Address(z, idx, Address::times_4,  0), tmp3);
+  movq(carry, tmp4);
+
+  bind (L_check_1);
+  addl (idx, 0x2);
+  andl (idx, 0x1);
+  subl(idx, 1);
+  jcc(Assembler::negative, L_post_third_loop_done);
+  movl(tmp4, Address(y, idx, Address::times_4,  0));
+  mulxq(carry2, tmp3, tmp4);  //  tmp4 * rdx -> carry2:tmp3
+  movl(tmp4, Address(z, idx, Address::times_4,  0));
+
+  add2_with_carry(carry2, tmp3, tmp4, carry);
+
+  movl(Address(z, idx, Address::times_4,  0), tmp3);
+  shrq(tmp3, 32);
+
+  shlq(carry2, 32);
+  orq(tmp3, carry2);
+  movq(carry, tmp3);
+
+  bind(L_post_third_loop_done);
+}
+
+/**
+ * Code for BigInteger::multiplyToLen() instrinsic.
+ *
+ * rdi: x
+ * rax: xlen
+ * rsi: y
+ * rcx: ylen
+ * r8:  z
+ * r11: zlen
+ * r12: tmp1
+ * r13: tmp2
+ * r14: tmp3
+ * r15: tmp4
+ * rbx: tmp5
+ *
+ */
+void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
+                                     Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) {
+  ShortBranchVerifier sbv(this);
+  assert_different_registers(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx);
+
+  push(tmp1);
+  push(tmp2);
+  push(tmp3);
+  push(tmp4);
+  push(tmp5);
+
+  push(xlen);
+  push(zlen);
+
+  const Register idx = tmp1;
+  const Register kdx = tmp2;
+  const Register xstart = tmp3;
+
+  const Register y_idx = tmp4;
+  const Register carry = tmp5;
+  const Register product  = xlen;
+  const Register x_xstart = zlen;  // reuse register
+
+  // First Loop.
+  //
+  //  final static long LONG_MASK = 0xffffffffL;
+  //  int xstart = xlen - 1;
+  //  int ystart = ylen - 1;
+  //  long carry = 0;
+  //  for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx-, kdx--) {
+  //    long product = (y[idx] & LONG_MASK) * (x[xstart] & LONG_MASK) + carry;
+  //    z[kdx] = (int)product;
+  //    carry = product >>> 32;
+  //  }
+  //  z[xstart] = (int)carry;
+  //
+
+  movl(idx, ylen);      // idx = ylen;
+  movl(kdx, zlen);      // kdx = xlen+ylen;
+  xorq(carry, carry);   // carry = 0;
+
+  Label L_done;
+
+  movl(xstart, xlen);
+  decrementl(xstart);
+  jcc(Assembler::negative, L_done);
+
+  multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
+
+  Label L_second_loop;
+  testl(kdx, kdx);
+  jcc(Assembler::zero, L_second_loop);
+
+  Label L_carry;
+  subl(kdx, 1);
+  jcc(Assembler::zero, L_carry);
+
+  movl(Address(z, kdx, Address::times_4,  0), carry);
+  shrq(carry, 32);
+  subl(kdx, 1);
+
+  bind(L_carry);
+  movl(Address(z, kdx, Address::times_4,  0), carry);
+
+  // Second and third (nested) loops.
+  //
+  // for (int i = xstart-1; i >= 0; i--) { // Second loop
+  //   carry = 0;
+  //   for (int jdx=ystart, k=ystart+1+i; jdx >= 0; jdx--, k--) { // Third loop
+  //     long product = (y[jdx] & LONG_MASK) * (x[i] & LONG_MASK) +
+  //                    (z[k] & LONG_MASK) + carry;
+  //     z[k] = (int)product;
+  //     carry = product >>> 32;
+  //   }
+  //   z[i] = (int)carry;
+  // }
+  //
+  // i = xlen, j = tmp1, k = tmp2, carry = tmp5, x[i] = rdx
+
+  const Register jdx = tmp1;
+
+  bind(L_second_loop);
+  xorl(carry, carry);    // carry = 0;
+  movl(jdx, ylen);       // j = ystart+1
+
+  subl(xstart, 1);       // i = xstart-1;
+  jcc(Assembler::negative, L_done);
+
+  push (z);
+
+  Label L_last_x;
+  lea(z, Address(z, xstart, Address::times_4, 4)); // z = z + k - j
+  subl(xstart, 1);       // i = xstart-1;
+  jcc(Assembler::negative, L_last_x);
+
+  if (UseBMI2Instructions) {
+    movq(rdx,  Address(x, xstart, Address::times_4,  0));
+    rorxq(rdx, rdx, 32); // convert big-endian to little-endian
+  } else {
+    movq(x_xstart, Address(x, xstart, Address::times_4,  0));
+    rorq(x_xstart, 32);  // convert big-endian to little-endian
+  }
+
+  Label L_third_loop_prologue;
+  bind(L_third_loop_prologue);
+
+  push (x);
+  push (xstart);
+  push (ylen);
+
+
+  if (UseBMI2Instructions) {
+    multiply_128_x_128_bmi2_loop(y, z, carry, x, jdx, ylen, product, tmp2, x_xstart, tmp3, tmp4);
+  } else { // !UseBMI2Instructions
+    multiply_128_x_128_loop(x_xstart, y, z, y_idx, jdx, ylen, carry, product, x);
+  }
+
+  pop(ylen);
+  pop(xlen);
+  pop(x);
+  pop(z);
+
+  movl(tmp3, xlen);
+  addl(tmp3, 1);
+  movl(Address(z, tmp3, Address::times_4,  0), carry);
+  subl(tmp3, 1);
+  jccb(Assembler::negative, L_done);
+
+  shrq(carry, 32);
+  movl(Address(z, tmp3, Address::times_4,  0), carry);
+  jmp(L_second_loop);
+
+  // Next infrequent code is moved outside loops.
+  bind(L_last_x);
+  if (UseBMI2Instructions) {
+    movl(rdx, Address(x,  0));
+  } else {
+    movl(x_xstart, Address(x,  0));
+  }
+  jmp(L_third_loop_prologue);
+
+  bind(L_done);
+
+  pop(zlen);
+  pop(xlen);
+
+  pop(tmp5);
+  pop(tmp4);
+  pop(tmp3);
+  pop(tmp2);
+  pop(tmp1);
+}
+#endif
+
 /**
  * Emits code to update CRC-32 with a byte value according to constants in table
  *
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1221,6 +1221,28 @@
                         XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3,
                         XMMRegister tmp4, Register tmp5, Register result);
 
+#ifdef _LP64
+  void add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2);
+  void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
+                             Register y, Register y_idx, Register z,
+                             Register carry, Register product,
+                             Register idx, Register kdx);
+  void multiply_add_128_x_128(Register x_xstart, Register y, Register z,
+                              Register yz_idx, Register idx,
+                              Register carry, Register product, int offset);
+  void multiply_128_x_128_bmi2_loop(Register y, Register z,
+                                    Register carry, Register carry2,
+                                    Register idx, Register jdx,
+                                    Register yz_idx1, Register yz_idx2,
+                                    Register tmp, Register tmp3, Register tmp4);
+  void multiply_128_x_128_loop(Register x_xstart, Register y, Register z,
+                               Register yz_idx, Register idx, Register jdx,
+                               Register carry, Register product,
+                               Register carry2);
+  void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
+                       Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
+#endif
+
   // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
   void update_byte_crc32(Register crc, Register val, Register table);
   void kernel_crc32(Register crc, Register buf, Register len, Register table, Register tmp);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -3677,6 +3677,70 @@
     return start;
   }
 
+
+  /**
+   *  Arguments:
+   *
+   *  Input:
+   *    c_rarg0   - x address
+   *    c_rarg1   - x length
+   *    c_rarg2   - y address
+   *    c_rarg3   - y lenth
+   * not Win64
+   *    c_rarg4   - z address
+   *    c_rarg5   - z length
+   * Win64
+   *    rsp+40    - z address
+   *    rsp+48    - z length
+   */
+  address generate_multiplyToLen() {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "multiplyToLen");
+
+    address start = __ pc();
+    // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
+    // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
+    const Register x     = rdi;
+    const Register xlen  = rax;
+    const Register y     = rsi;
+    const Register ylen  = rcx;
+    const Register z     = r8;
+    const Register zlen  = r11;
+
+    // Next registers will be saved on stack in multiply_to_len().
+    const Register tmp1  = r12;
+    const Register tmp2  = r13;
+    const Register tmp3  = r14;
+    const Register tmp4  = r15;
+    const Register tmp5  = rbx;
+
+    BLOCK_COMMENT("Entry:");
+    __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+#ifndef _WIN64
+    __ movptr(zlen, r9); // Save r9 in r11 - zlen
+#endif
+    setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
+                       // ylen => rcx, z => r8, zlen => r11
+                       // r9 and r10 may be used to save non-volatile registers
+#ifdef _WIN64
+    // last 2 arguments (#4, #5) are on stack on Win64
+    __ movptr(z, Address(rsp, 6 * wordSize));
+    __ movptr(zlen, Address(rsp, 7 * wordSize));
+#endif
+
+    __ movptr(xlen, rsi);
+    __ movptr(y,    rdx);
+    __ multiply_to_len(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5);
+
+    restore_arg_regs();
+
+    __ leave(); // required for proper stackwalking of RuntimeStub frame
+    __ ret(0);
+
+    return start;
+  }
+
 #undef __
 #define __ masm->
 
@@ -3917,6 +3981,11 @@
     generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
                                                        &StubRoutines::_safefetchN_fault_pc,
                                                        &StubRoutines::_safefetchN_continuation_pc);
+#ifdef COMPILER2
+    if (UseMultiplyToLenIntrinsic) {
+      StubRoutines::_multiplyToLen = generate_multiplyToLen();
+    }
+#endif
   }
 
  public:
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -485,7 +485,7 @@
   }
 
   char buf[256];
-  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                cores_per_cpu(), threads_per_core(),
                cpu_family(), _model, _stepping,
                (supports_cmov() ? ", cmov" : ""),
@@ -514,7 +514,8 @@
                (supports_tscinv_bit() ? ", tscinvbit": ""),
                (supports_tscinv() ? ", tscinv": ""),
                (supports_bmi1() ? ", bmi1" : ""),
-               (supports_bmi2() ? ", bmi2" : ""));
+               (supports_bmi2() ? ", bmi2" : ""),
+               (supports_adx() ? ", adx" : ""));
   _features_str = os::strdup(buf);
 
   // UseSSE is set to the smaller of what hardware supports and what
@@ -566,7 +567,7 @@
     }
   } else if (UseCRC32Intrinsics) {
     if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics))
-      warning("CRC32 Intrinsics requires AVX and CLMUL instructions (not available on this CPU)");
+      warning("CRC32 Intrinsics requires CLMUL instructions (not available on this CPU)");
     FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
   }
 
@@ -689,7 +690,20 @@
     }
 #endif
   }
+
+#ifdef _LP64
+  if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
+    UseMultiplyToLenIntrinsic = true;
+  }
+#else
+  if (UseMultiplyToLenIntrinsic) {
+    if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
+      warning("multiplyToLen intrinsic is not available in 32-bit VM");
+    }
+    FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
+  }
 #endif
+#endif // COMPILER2
 
   // On new cpus instructions which update whole XMM register should be used
   // to prevent partial register stall due to dependencies on high half.
@@ -832,6 +846,9 @@
         }
       }
     }
+    if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
+      AllocatePrefetchInstr = 3;
+    }
   }
 
   // Use count leading zeros count instruction if available.
@@ -844,23 +861,35 @@
     FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false);
   }
 
+  // Use count trailing zeros instruction if available
   if (supports_bmi1()) {
+    // tzcnt does not require VEX prefix
+    if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
+      UseCountTrailingZerosInstruction = true;
+    }
+  } else if (UseCountTrailingZerosInstruction) {
+    warning("tzcnt instruction is not available on this CPU");
+    FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
+  }
+
+  // BMI instructions use an encoding with VEX prefix.
+  // VEX prefix is generated only when AVX > 0.
+  if (supports_bmi1() && supports_avx()) {
     if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
       UseBMI1Instructions = true;
     }
   } else if (UseBMI1Instructions) {
-    warning("BMI1 instructions are not available on this CPU");
+    warning("BMI1 instructions are not available on this CPU (AVX is also required)");
     FLAG_SET_DEFAULT(UseBMI1Instructions, false);
   }
 
-  // Use count trailing zeros instruction if available
-  if (supports_bmi1()) {
-    if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
-      UseCountTrailingZerosInstruction = UseBMI1Instructions;
+  if (supports_bmi2() && supports_avx()) {
+    if (FLAG_IS_DEFAULT(UseBMI2Instructions)) {
+      UseBMI2Instructions = true;
     }
-  } else if (UseCountTrailingZerosInstruction) {
-    warning("tzcnt instruction is not available on this CPU");
-    FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
+  } else if (UseBMI2Instructions) {
+    warning("BMI2 instructions are not available on this CPU (AVX is also required)");
+    FLAG_SET_DEFAULT(UseBMI2Instructions, false);
   }
 
   // Use population count instruction if available.
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -209,7 +209,9 @@
                    erms : 1,
                         : 1,
                    rtm  : 1,
-                        : 20;
+                        : 7,
+                   adx  : 1,
+                        : 12;
     } bits;
   };
 
@@ -260,7 +262,8 @@
     CPU_CLMUL  = (1 << 21), // carryless multiply for CRC
     CPU_BMI1   = (1 << 22),
     CPU_BMI2   = (1 << 23),
-    CPU_RTM    = (1 << 24)  // Restricted Transactional Memory instructions
+    CPU_RTM    = (1 << 24),  // Restricted Transactional Memory instructions
+    CPU_ADX    = (1 << 25)
   } cpuFeatureFlags;
 
   enum {
@@ -465,10 +468,16 @@
     }
     // Intel features.
     if(is_intel()) {
+      if(_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
+         result |= CPU_ADX;
       if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
         result |= CPU_BMI2;
       if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
         result |= CPU_LZCNT;
+      // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw
+      if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) {
+        result |= CPU_3DNOW_PREFETCH;
+      }
     }
 
     return result;
@@ -625,6 +634,7 @@
   static bool supports_rtm()      { return (_cpuFeatures & CPU_RTM) != 0; }
   static bool supports_bmi1()     { return (_cpuFeatures & CPU_BMI1) != 0; }
   static bool supports_bmi2()     { return (_cpuFeatures & CPU_BMI2) != 0; }
+  static bool supports_adx()     { return (_cpuFeatures & CPU_ADX) != 0; }
   // Intel features
   static bool is_intel_family_core() { return is_intel() &&
                                        extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1678,14 +1678,9 @@
 
   dlclose(handle);
 #elif defined(__APPLE__)
-  uint32_t count;
-  uint32_t i;
-
-  count = _dyld_image_count();
-  for (i = 1; i < count; i++) {
-    const char *name = _dyld_get_image_name(i);
-    intptr_t slide = _dyld_get_image_vmaddr_slide(i);
-    st->print_cr(PTR_FORMAT " \t%s", slide, name);
+  for (uint32_t i = 1; i < _dyld_image_count(); i++) {
+    st->print_cr(PTR_FORMAT " \t%s", _dyld_get_image_header(i),
+        _dyld_get_image_name(i));
   }
 #else
   st->print_cr("Error: Cannot print dynamic libraries.");
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -134,6 +134,10 @@
   // free any overflow storage
   delete _overflow_arena;
 
+  // Claim is that stack allocation ensures resources are cleaned up.
+  // This is resource clean up, let's hope that all were properly copied out.
+  free_strings();
+
 #ifdef ASSERT
   // Save allocation type to execute assert in ~ResourceObj()
   // which is called after this destructor.
@@ -705,7 +709,7 @@
   relocate_code_to(&dest);
 
   // transfer strings and comments from buffer to blob
-  dest_blob->set_strings(_strings);
+  dest_blob->set_strings(_code_strings);
 
   // Done moving code bytes; were they the right size?
   assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
@@ -1005,11 +1009,11 @@
 
 
 void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
-  _strings.add_comment(offset, comment);
+  _code_strings.add_comment(offset, comment);
 }
 
 const char* CodeBuffer::code_string(const char* str) {
-  return _strings.add_string(str);
+  return _code_strings.add_string(str);
 }
 
 class CodeString: public CHeapObj<mtCode> {
@@ -1075,6 +1079,7 @@
 }
 
 void CodeStrings::add_comment(intptr_t offset, const char * comment) {
+  check_valid();
   CodeString* c      = new CodeString(comment, offset);
   CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
 
@@ -1090,11 +1095,32 @@
 }
 
 void CodeStrings::assign(CodeStrings& other) {
+  other.check_valid();
+  // Cannot do following because CodeStrings constructor is not alway run!
+  assert(is_null(), "Cannot assign onto non-empty CodeStrings");
   _strings = other._strings;
+  other.set_null_and_invalidate();
+}
+
+// Deep copy of CodeStrings for consistent memory management.
+// Only used for actual disassembly so this is cheaper than reference counting
+// for the "normal" fastdebug case.
+void CodeStrings::copy(CodeStrings& other) {
+  other.check_valid();
+  check_valid();
+  assert(is_null(), "Cannot copy onto non-empty CodeStrings");
+  CodeString* n = other._strings;
+  CodeString** ps = &_strings;
+  while (n != NULL) {
+    *ps = new CodeString(n->string(),n->offset());
+    ps = &((*ps)->_next);
+    n = n->next();
+  }
 }
 
 void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
-  if (_strings != NULL) {
+    check_valid();
+    if (_strings != NULL) {
     CodeString* c = find(offset);
     while (c && c->offset() == offset) {
       stream->bol();
@@ -1105,7 +1131,7 @@
   }
 }
 
-
+// Also sets isNull()
 void CodeStrings::free() {
   CodeString* n = _strings;
   while (n) {
@@ -1115,10 +1141,11 @@
     delete n;
     n = p;
   }
-  _strings = NULL;
+  set_null_and_invalidate();
 }
 
 const char* CodeStrings::add_string(const char * string) {
+  check_valid();
   CodeString* s = new CodeString(string);
   s->set_next(_strings);
   _strings = s;
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -27,6 +27,7 @@
 
 #include "code/oopRecorder.hpp"
 #include "code/relocInfo.hpp"
+#include "utilities/debug.hpp"
 
 class CodeStrings;
 class PhaseCFG;
@@ -245,15 +246,39 @@
 private:
 #ifndef PRODUCT
   CodeString* _strings;
+#ifdef ASSERT
+  // Becomes true after copy-out, forbids further use.
+  bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
+#endif
 #endif
 
   CodeString* find(intptr_t offset) const;
   CodeString* find_last(intptr_t offset) const;
 
+  void set_null_and_invalidate() {
+#ifndef PRODUCT
+    _strings = NULL;
+#ifdef ASSERT
+    _defunct = true;
+#endif
+#endif
+  }
+
 public:
   CodeStrings() {
 #ifndef PRODUCT
     _strings = NULL;
+#ifdef ASSERT
+    _defunct = false;
+#endif
+#endif
+  }
+
+  bool is_null() {
+#ifdef ASSERT
+    return _strings == NULL;
+#else
+    return true;
 #endif
   }
 
@@ -261,8 +286,17 @@
 
   void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
   void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
+  // MOVE strings from other to this; invalidate other.
   void assign(CodeStrings& other)  PRODUCT_RETURN;
+  // COPY strings from other to this; leave other valid.
+  void copy(CodeStrings& other)  PRODUCT_RETURN;
   void free() PRODUCT_RETURN;
+  // Guarantee that _strings are used at most once; assign invalidates a buffer.
+  inline void check_valid() const {
+#ifdef ASSERT
+    assert(!_defunct, "Use of invalid CodeStrings");
+#endif
+  }
 };
 
 // A CodeBuffer describes a memory space into which assembly
@@ -330,7 +364,7 @@
   csize_t      _total_size;     // size in bytes of combined memory buffer
 
   OopRecorder* _oop_recorder;
-  CodeStrings  _strings;
+  CodeStrings  _code_strings;
   OopRecorder  _default_oop_recorder;  // override with initialize_oop_recorder
   Arena*       _overflow_arena;
 
@@ -531,7 +565,13 @@
   void initialize_oop_recorder(OopRecorder* r);
 
   OopRecorder* oop_recorder() const   { return _oop_recorder; }
-  CodeStrings& strings()              { return _strings; }
+  CodeStrings& strings()              { return _code_strings; }
+
+  void free_strings() {
+    if (!_code_strings.is_null()) {
+      _code_strings.free(); // sets _strings Null as a side-effect.
+    }
+  }
 
   // Code generation
   void relocate(address at, RelocationHolder const& rspec, int format = 0) {
--- a/hotspot/src/share/vm/asm/register.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/asm/register.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -275,4 +275,101 @@
   );
 }
 
+inline void assert_different_registers(
+  AbstractRegister a,
+  AbstractRegister b,
+  AbstractRegister c,
+  AbstractRegister d,
+  AbstractRegister e,
+  AbstractRegister f,
+  AbstractRegister g,
+  AbstractRegister h,
+  AbstractRegister i,
+  AbstractRegister j
+) {
+  assert(
+    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j
+           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j
+                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j
+                               && d != e && d != f && d != g && d != h && d != i && d != j
+                                         && e != f && e != g && e != h && e != i && e != j
+                                                   && f != g && f != h && f != i && f != j
+                                                             && g != h && g != i && g != j
+                                                                       && h != i && h != j
+                                                                                 && i != j,
+    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT "",
+                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j))
+  );
+}
+
+inline void assert_different_registers(
+  AbstractRegister a,
+  AbstractRegister b,
+  AbstractRegister c,
+  AbstractRegister d,
+  AbstractRegister e,
+  AbstractRegister f,
+  AbstractRegister g,
+  AbstractRegister h,
+  AbstractRegister i,
+  AbstractRegister j,
+  AbstractRegister k
+) {
+  assert(
+    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k
+           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k
+                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k
+                               && d != e && d != f && d != g && d != h && d != i && d != j && d !=k
+                                         && e != f && e != g && e != h && e != i && e != j && e !=k
+                                                   && f != g && f != h && f != i && f != j && f !=k
+                                                             && g != h && g != i && g != j && g !=k
+                                                                       && h != i && h != j && h !=k
+                                                                                 && i != j && i !=k
+                                                                                           && j !=k,
+    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT "",
+                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k))
+  );
+}
+
+inline void assert_different_registers(
+  AbstractRegister a,
+  AbstractRegister b,
+  AbstractRegister c,
+  AbstractRegister d,
+  AbstractRegister e,
+  AbstractRegister f,
+  AbstractRegister g,
+  AbstractRegister h,
+  AbstractRegister i,
+  AbstractRegister j,
+  AbstractRegister k,
+  AbstractRegister l
+) {
+  assert(
+    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k && a !=l
+           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k && b !=l
+                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k && c !=l
+                               && d != e && d != f && d != g && d != h && d != i && d != j && d !=k && d !=l
+                                         && e != f && e != g && e != h && e != i && e != j && e !=k && e !=l
+                                                   && f != g && f != h && f != i && f != j && f !=k && f !=l
+                                                             && g != h && g != i && g != j && g !=k && g !=l
+                                                                       && h != i && h != j && h !=k && h !=l
+                                                                                 && i != j && i !=k && i !=l
+                                                                                           && j !=k && j !=l
+                                                                                                    && k !=l,
+    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT
+                ", l=" INTPTR_FORMAT "",
+                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k), p2i(l))
+  );
+}
+
 #endif // SHARE_VM_ASM_REGISTER_HPP
--- a/hotspot/src/share/vm/ci/ciArrayKlass.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciArrayKlass.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -52,11 +52,6 @@
   ciType* base_element_type();  // JLS calls this the "element type"
   bool is_leaf_type();          // No subtypes of this array type.
 
-  ciInstance* component_mirror() {
-    // This is a real field in ArrayKlass, but we derive it from element_type.
-    return element_type()->java_mirror();
-  }
-
   // What kind of vmObject is this?
   bool is_array_klass() const { return true; }
   bool is_java_klass() const  { return true; }
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1102,6 +1102,22 @@
 }
 
 // ------------------------------------------------------------------
+// ciMethod::has_option_value
+//
+template<typename T>
+bool ciMethod::has_option_value(const char* option, T& value) {
+  check_is_loaded();
+  VM_ENTRY_MARK;
+  methodHandle mh(THREAD, get_Method());
+  return CompilerOracle::has_option_value(mh, option, value);
+}
+// Explicit instantiation for all OptionTypes supported.
+template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
+template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
+template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
+template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
+
+// ------------------------------------------------------------------
 // ciMethod::can_be_compiled
 //
 // Have previous compilations of this method succeeded?
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -269,6 +269,8 @@
   bool should_print_assembly();
   bool break_at_execute();
   bool has_option(const char *option);
+  template<typename T>
+  bool has_option_value(const char* option, T& value);
   bool can_be_compiled();
   bool can_be_osr_compiled(int entry_bci);
   void set_not_compilable(const char* reason = NULL);
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -81,19 +81,38 @@
 void ciMethodData::load_extra_data() {
   MethodData* mdo = get_MethodData();
 
+  MutexLocker(mdo->extra_data_lock());
+
   // speculative trap entries also hold a pointer to a Method so need to be translated
   DataLayout* dp_src  = mdo->extra_data_base();
-  DataLayout* end_src = mdo->extra_data_limit();
+  DataLayout* end_src = mdo->args_data_limit();
   DataLayout* dp_dst  = extra_data_base();
   for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) {
     assert(dp_src < end_src, "moved past end of extra data");
-    // New traps in the MDO can be added as we translate the copy so
-    // look at the entries in the copy.
-    switch(dp_dst->tag()) {
+    assert(((intptr_t)dp_dst) - ((intptr_t)extra_data_base()) == ((intptr_t)dp_src) - ((intptr_t)mdo->extra_data_base()), "source and destination don't match");
+
+    // New traps in the MDO may have been added since we copied the
+    // data (concurrent deoptimizations before we acquired
+    // extra_data_lock above) or can be removed (a safepoint may occur
+    // in the translate_from call below) as we translate the copy:
+    // update the copy as we go.
+    int tag = dp_src->tag();
+    if (tag != DataLayout::arg_info_data_tag) {
+      memcpy(dp_dst, dp_src, ((intptr_t)MethodData::next_extra(dp_src)) - ((intptr_t)dp_src));
+    }
+
+    switch(tag) {
     case DataLayout::speculative_trap_data_tag: {
       ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst);
       SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src);
+
       data_dst->translate_from(data_src);
+
+#ifdef ASSERT
+      SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src);
+      assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating");
+#endif
+
       break;
     }
     case DataLayout::bit_data_tag:
@@ -244,8 +263,8 @@
 }
 
 ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
-  DataLayout* dp  = data_layout_at(data_size());
-  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = args_data_limit();
   two_free_slots = false;
   for (;dp < end; dp = MethodData::next_extra(dp)) {
     switch(dp->tag()) {
@@ -492,8 +511,8 @@
 
 ciArgInfoData *ciMethodData::arg_info() const {
   // Should be last, have to skip all traps.
-  DataLayout* dp  = data_layout_at(data_size());
-  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = args_data_limit();
   for (; dp < end; dp = MethodData::next_extra(dp)) {
     if (dp->tag() == DataLayout::arg_info_data_tag)
       return new ciArgInfoData(dp);
@@ -535,8 +554,8 @@
 }
 
 void ciMethodData::dump_replay_data_extra_data_helper(outputStream* out, int round, int& count) {
-  DataLayout* dp  = data_layout_at(data_size());
-  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = args_data_limit();
 
   for (;dp < end; dp = MethodData::next_extra(dp)) {
     switch(dp->tag()) {
@@ -653,8 +672,8 @@
     data->print_data_on(st);
   }
   st->print_cr("--- Extra data:");
-  DataLayout* dp  = data_layout_at(data_size());
-  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = args_data_limit();
   for (;; dp = MethodData::next_extra(dp)) {
     assert(dp < end, "moved past end of extra data");
     switch (dp->tag()) {
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -410,6 +410,9 @@
   // Area dedicated to parameters. NULL if no parameter profiling for
   // this method.
   DataLayout* _parameters;
+  int parameters_size() const {
+    return _parameters == NULL ? 0 : parameters_type_data()->size_in_bytes();
+  }
 
   ciMethodData(MethodData* md);
   ciMethodData();
@@ -461,9 +464,6 @@
   address data_base() const {
     return (address) _data;
   }
-  DataLayout* limit_data_position() const {
-    return (DataLayout*)((address)data_base() + _data_size);
-  }
 
   void load_extra_data();
   ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots);
@@ -524,7 +524,9 @@
   ciProfileData* next_data(ciProfileData* current);
   bool is_valid(ciProfileData* current) { return current != NULL; }
 
-  DataLayout* extra_data_base() const { return limit_data_position(); }
+  DataLayout* extra_data_base() const  { return data_layout_at(data_size()); }
+  DataLayout* args_data_limit() const  { return data_layout_at(data_size() + extra_data_size() -
+                                                               parameters_size()); }
 
   // Get the data at an arbitrary bci, or NULL if there is none. If m
   // is not NULL look for a SpeculativeTrapData if any first.
--- a/hotspot/src/share/vm/classfile/classFileStream.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classFileStream.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -30,7 +30,7 @@
   THROW_MSG(vmSymbols::java_lang_ClassFormatError(), "Truncated class file");
 }
 
-ClassFileStream::ClassFileStream(u1* buffer, int length, char* source) {
+ClassFileStream::ClassFileStream(u1* buffer, int length, const char* source) {
   _buffer_start = buffer;
   _buffer_end   = buffer + length;
   _current      = buffer;
--- a/hotspot/src/share/vm/classfile/classFileStream.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classFileStream.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -39,20 +39,20 @@
   u1*   _buffer_start; // Buffer bottom
   u1*   _buffer_end;   // Buffer top (one past last element)
   u1*   _current;      // Current buffer position
-  char* _source;       // Source of stream (directory name, ZIP/JAR archive name)
+  const char* _source; // Source of stream (directory name, ZIP/JAR archive name)
   bool  _need_verify;  // True if verification is on for the class file
 
   void truncated_file_error(TRAPS);
  public:
   // Constructor
-  ClassFileStream(u1* buffer, int length, char* source);
+  ClassFileStream(u1* buffer, int length, const char* source);
 
   // Buffer access
   u1* buffer() const           { return _buffer_start; }
   int length() const           { return _buffer_end - _buffer_start; }
   u1* current() const          { return _current; }
   void set_current(u1* pos)    { _current = pos; }
-  char* source() const         { return _source; }
+  const char* source() const   { return _source; }
   void set_verify(bool flag)   { _need_verify = flag; }
 
   void check_truncated_file(bool b, TRAPS) {
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -189,9 +189,10 @@
   return false;
 }
 
-ClassPathDirEntry::ClassPathDirEntry(char* dir) : ClassPathEntry() {
-  _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
-  strcpy(_dir, dir);
+ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
+  char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
+  strcpy(copy, dir);
+  _dir = copy;
 }
 
 
@@ -235,8 +236,9 @@
 
 ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
   _zip = zip;
-  _zip_name = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
-  strcpy(_zip_name, zip_name);
+  char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
+  strcpy(copy, zip_name);
+  _zip_name = copy;
 }
 
 ClassPathZipEntry::~ClassPathZipEntry() {
@@ -304,7 +306,7 @@
   }
 }
 
-LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() {
+LazyClassPathEntry::LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() {
   _path = os::strdup_check_oom(path);
   _st = *st;
   _meta_index = NULL;
@@ -314,7 +316,7 @@
 }
 
 LazyClassPathEntry::~LazyClassPathEntry() {
-  os::free(_path);
+  os::free((void*)_path);
 }
 
 bool LazyClassPathEntry::is_jar_file() {
@@ -563,17 +565,19 @@
 
 void ClassLoader::setup_bootstrap_search_path() {
   assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
-  char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath());
-  if (!PrintSharedArchiveAndExit) {
+  const char* sys_class_path = Arguments::get_sysclasspath();
+  if (PrintSharedArchiveAndExit) {
+    // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily
+    // the same as the bootcp of the shared archive.
+  } else {
     trace_class_path("[Bootstrap loader class path=", sys_class_path);
   }
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
-    _shared_paths_misc_info->add_boot_classpath(Arguments::get_sysclasspath());
+    _shared_paths_misc_info->add_boot_classpath(sys_class_path);
   }
 #endif
   setup_search_path(sys_class_path);
-  os::free(sys_class_path);
 }
 
 #if INCLUDE_CDS
@@ -593,7 +597,7 @@
 }
 #endif
 
-void ClassLoader::setup_search_path(char *class_path) {
+void ClassLoader::setup_search_path(const char *class_path) {
   int offset = 0;
   int len = (int)strlen(class_path);
   int end = 0;
@@ -620,7 +624,7 @@
   }
 }
 
-ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st,
+ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
                                                      bool lazy, bool throw_exception, TRAPS) {
   JavaThread* thread = JavaThread::current();
   if (lazy) {
@@ -687,11 +691,8 @@
   struct stat st;
   if (os::stat(path, &st) == 0) {
     if ((st.st_mode & S_IFREG) == S_IFREG) {
-      char orig_path[JVM_MAXPATHLEN];
       char canonical_path[JVM_MAXPATHLEN];
-
-      strcpy(orig_path, path);
-      if (get_canonical_path(orig_path, canonical_path, JVM_MAXPATHLEN)) {
+      if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
         char* error_msg = NULL;
         jzfile* zip;
         {
@@ -737,7 +738,7 @@
 }
 
 // Returns true IFF the file/dir exists and the entry was successfully created.
-bool ClassLoader::update_class_path_entry_list(char *path,
+bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
                                                bool throw_exception) {
   struct stat st;
@@ -762,8 +763,8 @@
     if (DumpSharedSpaces) {
       _shared_paths_misc_info->add_nonexist_path(path);
     }
+#endif
     return false;
-#endif
   }
 }
 
@@ -1269,11 +1270,17 @@
 }
 
 
-bool ClassLoader::get_canonical_path(char* orig, char* out, int len) {
+bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
   assert(orig != NULL && out != NULL && len > 0, "bad arguments");
   if (CanonicalizeEntry != NULL) {
-    JNIEnv* env = JavaThread::current()->jni_environment();
-    if ((CanonicalizeEntry)(env, os::native_path(orig), out, len) < 0) {
+    JavaThread* THREAD = JavaThread::current();
+    JNIEnv* env = THREAD->jni_environment();
+    ResourceMark rm(THREAD);
+
+    // os::native_path writes into orig_copy
+    char* orig_copy = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(orig)+1);
+    strcpy(orig_copy, orig);
+    if ((CanonicalizeEntry)(env, os::native_path(orig_copy), out, len) < 0) {
       return false;
     }
   } else {
--- a/hotspot/src/share/vm/classfile/classLoader.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -72,11 +72,11 @@
 
 class ClassPathDirEntry: public ClassPathEntry {
  private:
-  char* _dir;           // Name of directory
+  const char* _dir;           // Name of directory
  public:
   bool is_jar_file()  { return false;  }
   const char* name()  { return _dir; }
-  ClassPathDirEntry(char* dir);
+  ClassPathDirEntry(const char* dir);
   ClassFileStream* open_stream(const char* name, TRAPS);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
@@ -100,8 +100,8 @@
 
 class ClassPathZipEntry: public ClassPathEntry {
  private:
-  jzfile* _zip;        // The zip archive
-  char*   _zip_name;   // Name of zip archive
+  jzfile* _zip;              // The zip archive
+  const char*   _zip_name;   // Name of zip archive
  public:
   bool is_jar_file()  { return true;  }
   const char* name()  { return _zip_name; }
@@ -119,7 +119,7 @@
 // For lazier loading of boot class path entries
 class LazyClassPathEntry: public ClassPathEntry {
  private:
-  char* _path; // dir or file
+  const char* _path; // dir or file
   struct stat _st;
   MetaIndex* _meta_index;
   bool _has_error;
@@ -129,7 +129,7 @@
  public:
   bool is_jar_file();
   const char* name()  { return _path; }
-  LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception);
+  LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception);
   virtual ~LazyClassPathEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
 
@@ -216,17 +216,17 @@
   static void setup_meta_index(const char* meta_index_path, const char* meta_index_dir,
                                int start_index);
   static void setup_bootstrap_search_path();
-  static void setup_search_path(char *class_path);
+  static void setup_search_path(const char *class_path);
 
   static void load_zip_library();
-  static ClassPathEntry* create_class_path_entry(char *path, const struct stat* st,
+  static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                  bool lazy, bool throw_exception, TRAPS);
 
   // Canonicalizes path names, so strcmp will work properly. This is mainly
   // to avoid confusing the zip library
-  static bool get_canonical_path(char* orig, char* out, int len);
+  static bool get_canonical_path(const char* orig, char* out, int len);
  public:
-  static bool update_class_path_entry_list(char *path,
+  static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
                                            bool throw_exception=true);
   static void print_bootclasspath();
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -332,27 +332,6 @@
   }
 }
 
-#ifdef ASSERT
-class AllAliveClosure : public OopClosure {
-  BoolObjectClosure* _is_alive_closure;
-  bool _found_dead;
- public:
-  AllAliveClosure(BoolObjectClosure* is_alive_closure) : _is_alive_closure(is_alive_closure), _found_dead(false) {}
-  template <typename T> void do_oop_work(T* p) {
-    T heap_oop = oopDesc::load_heap_oop(p);
-    if (!oopDesc::is_null(heap_oop)) {
-      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-      if (!_is_alive_closure->do_object_b(obj)) {
-        _found_dead = true;
-      }
-    }
-  }
-  void do_oop(oop* p)       { do_oop_work<oop>(p); }
-  void do_oop(narrowOop* p) { do_oop_work<narrowOop>(p); }
-  bool found_dead()         { return _found_dead; }
-};
-#endif
-
 oop ClassLoaderData::keep_alive_object() const {
   assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
   return is_anonymous() ? _klasses->java_mirror() : class_loader();
@@ -362,15 +341,6 @@
   bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
       || is_alive_closure->do_object_b(keep_alive_object());
 
-#ifdef ASSERT
-  if (alive) {
-    AllAliveClosure all_alive_closure(is_alive_closure);
-    KlassToOopClosure klass_closure(&all_alive_closure);
-    const_cast<ClassLoaderData*>(this)->oops_do(&all_alive_closure, &klass_closure, false);
-    assert(!all_alive_closure.found_dead(), err_msg("Found dead oop in alive cld: " PTR_FORMAT, p2i(this)));
-  }
-#endif
-
   return alive;
 }
 
--- a/hotspot/src/share/vm/classfile/classLoaderExt.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -59,8 +59,8 @@
   };
 
 
-  static void add_class_path_entry(char* path, bool check_for_duplicates,
-                            ClassPathEntry* new_entry) {
+  static void add_class_path_entry(const char* path, bool check_for_duplicates,
+                                   ClassPathEntry* new_entry) {
     ClassLoader::add_to_list(new_entry);
   }
   static void setup_search_paths() {}
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -620,7 +620,6 @@
       // Two-way link between the array klass and its component mirror:
       // (array_klass) k -> mirror -> component_mirror -> array_klass -> k
       set_component_mirror(mirror(), comp_mirror());
-      ArrayKlass::cast(k())->set_component_mirror(comp_mirror());
       set_array_klass(comp_mirror(), k());
     } else {
       assert(k->oop_is_instance(), "Must be");
@@ -682,10 +681,9 @@
 }
 
 void java_lang_Class::set_component_mirror(oop java_class, oop comp_mirror) {
-  if (_component_mirror_offset != 0) {
+  assert(_component_mirror_offset != 0, "must be set");
     java_class->obj_field_put(_component_mirror_offset, comp_mirror);
   }
-}
 oop java_lang_Class::component_mirror(oop java_class) {
   assert(_component_mirror_offset != 0, "must be set");
   return java_class->obj_field(_component_mirror_offset);
@@ -875,22 +873,27 @@
   assert(!offsets_computed, "offsets should be initialized only once");
   offsets_computed = true;
 
-  Klass* klass_oop = SystemDictionary::Class_klass();
+  Klass* k = SystemDictionary::Class_klass();
   // The classRedefinedCount field is only present starting in 1.5,
   // so don't go fatal.
   compute_optional_offset(classRedefinedCount_offset,
-                          klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
+                          k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
 
   // Needs to be optional because the old build runs Queens during bootstrapping
   // and jdk8-9 doesn't have coordinated pushes yet.
   compute_optional_offset(_class_loader_offset,
-                 klass_oop, vmSymbols::classLoader_name(),
+                 k, vmSymbols::classLoader_name(),
                  vmSymbols::classloader_signature());
 
-  compute_optional_offset(_component_mirror_offset,
-                 klass_oop, vmSymbols::componentType_name(),
+  compute_offset(_component_mirror_offset,
+                 k, vmSymbols::componentType_name(),
                  vmSymbols::class_signature());
 
+  // Init lock is a C union with component_mirror.  Only instanceKlass mirrors have
+  // init_lock and only ArrayKlass mirrors have component_mirror.  Since both are oops
+  // GC treats them the same.
+  _init_lock_offset = _component_mirror_offset;
+
   CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
 }
 
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -222,7 +222,6 @@
   macro(java_lang_Class, oop_size,               int_signature,     false) \
   macro(java_lang_Class, static_oop_field_count, int_signature,     false) \
   macro(java_lang_Class, protection_domain,      object_signature,  false) \
-  macro(java_lang_Class, init_lock,              object_signature,  false) \
   macro(java_lang_Class, signers,                object_signature,  false)
 
 class java_lang_Class : AllStatic {
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -139,7 +139,7 @@
         if (timestamp != st.st_mtime) {
           return fail("Timestamp mismatch");
         }
-        if (filesize  != st.st_size) {
+        if (filesize != st.st_size) {
           return fail("File size mismatch");
         }
       }
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -165,7 +165,7 @@
       out->print("Expecting that %s does not exist", path);
       break;
     case REQUIRED:
-      out->print("Expecting that file %s must exist and not altered", path);
+      out->print("Expecting that file %s must exist and is not altered", path);
       break;
     default:
       ShouldNotReachHere();
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -109,7 +109,7 @@
     }
   }
   // If the bucket size is too deep check if this hash code is insufficient.
-  if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
+  if (count >= rehash_count && !needs_rehashing()) {
     _needs_rehashing = check_rehash_table(count);
   }
   return NULL;
--- a/hotspot/src/share/vm/classfile/stringTable.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -28,7 +28,7 @@
 #include "memory/allocation.inline.hpp"
 #include "utilities/hashtable.hpp"
 
-class StringTable : public Hashtable<oop, mtSymbol> {
+class StringTable : public RehashableHashtable<oop, mtSymbol> {
   friend class VMStructs;
   friend class Symbol;
 
@@ -55,11 +55,11 @@
   // in the range [start_idx, end_idx).
   static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
 
-  StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
+  StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
                               sizeof (HashtableEntry<oop, mtSymbol>)) {}
 
   StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
-    : Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
+    : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
                      number_of_entries) {}
 public:
   // The string table
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -201,7 +201,7 @@
     }
   }
   // If the bucket size is too deep check if this hash code is insufficient.
-  if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
+  if (count >= rehash_count && !needs_rehashing()) {
     _needs_rehashing = check_rehash_table(count);
   }
   return NULL;
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -73,7 +73,7 @@
   operator Symbol*()                             { return _temp; }
 };
 
-class SymbolTable : public Hashtable<Symbol*, mtSymbol> {
+class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
   friend class VMStructs;
   friend class ClassFileParser;
 
@@ -109,10 +109,10 @@
   Symbol* lookup(int index, const char* name, int len, unsigned int hash);
 
   SymbolTable()
-    : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
+    : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
 
   SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
-    : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
+    : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
                 number_of_entries) {}
 
   // Arena for permanent symbols (null class loader) that are never unloaded
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1243,7 +1243,6 @@
       tty->print_cr("]");
     }
 
-#if INCLUDE_CDS
     if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
       // Only dump the classes that can be stored into CDS archive
       if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
@@ -1252,7 +1251,6 @@
         classlist_file->flush();
       }
     }
-#endif
 
     // notify a class loaded from shared object
     ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()),
@@ -1260,7 +1258,7 @@
   }
   return ik;
 }
-#endif
+#endif // INCLUDE_CDS
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -399,7 +399,6 @@
   template(oop_size_name,                             "oop_size")                                 \
   template(static_oop_field_count_name,               "static_oop_field_count")                   \
   template(protection_domain_name,                    "protection_domain")                        \
-  template(init_lock_name,                            "init_lock")                                \
   template(signers_name,                              "signers_name")                             \
   template(loader_data_name,                          "loader_data")                              \
   template(dependencies_name,                         "dependencies")                             \
@@ -747,8 +746,6 @@
    do_name(     isPrimitive_name,                                "isPrimitive")                                         \
   do_intrinsic(_getSuperclass,            java_lang_Class,        getSuperclass_name, void_class_signature,      F_RN)  \
    do_name(     getSuperclass_name,                              "getSuperclass")                                       \
-  do_intrinsic(_getComponentType,         java_lang_Class,        getComponentType_name, void_class_signature,   F_RN)  \
-   do_name(     getComponentType_name,                           "getComponentType")                                    \
                                                                                                                         \
   do_intrinsic(_getClassAccessFlags,      sun_reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN)  \
    do_name(     getClassAccessFlags_name,                        "getClassAccessFlags")                                 \
@@ -788,6 +785,11 @@
    do_name(     encodeISOArray_name,                             "encodeISOArray")                                      \
    do_signature(encodeISOArray_signature,                        "([CI[BII)I")                                          \
                                                                                                                         \
+  do_class(java_math_BigInteger,                      "java/math/BigInteger")                                           \
+  do_intrinsic(_multiplyToLen,      java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_R)             \
+   do_name(     multiplyToLen_name,                             "multiplyToLen")                                        \
+   do_signature(multiplyToLen_signature,                        "([II[II[I)[I")                                         \
+                                                                                                                        \
   /* java/lang/ref/Reference */                                                                                         \
   do_intrinsic(_Reference_get,            java_lang_ref_Reference, get_name,    void_object_signature, F_R)             \
                                                                                                                         \
--- a/hotspot/src/share/vm/code/codeBlob.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -238,6 +238,7 @@
 
 void BufferBlob::free( BufferBlob *blob ) {
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
+  blob->flush();
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::free((CodeBlob*)blob);
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -168,48 +168,134 @@
   }
 }
 
+enum OptionType {
+  IntxType,
+  UintxType,
+  BoolType,
+  CcstrType,
+  UnknownType
+};
 
-class MethodOptionMatcher: public MethodMatcher {
-  const char * option;
- public:
-  MethodOptionMatcher(Symbol* class_name, Mode class_mode,
-                             Symbol* method_name, Mode method_mode,
-                             Symbol* signature, const char * opt, MethodMatcher* next):
-    MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) {
-    option = os::strdup_check_oom(opt);
+/* Methods to map real type names to OptionType */
+template<typename T>
+static OptionType get_type_for() {
+  return UnknownType;
+};
+
+template<> OptionType get_type_for<intx>() {
+  return IntxType;
+}
+
+template<> OptionType get_type_for<uintx>() {
+  return UintxType;
+}
+
+template<> OptionType get_type_for<bool>() {
+  return BoolType;
+}
+
+template<> OptionType get_type_for<ccstr>() {
+  return CcstrType;
+}
+
+template<typename T>
+static const T copy_value(const T value) {
+  return value;
+}
+
+template<> const ccstr copy_value<ccstr>(const ccstr value) {
+  return (const ccstr)os::strdup_check_oom(value);
+}
+
+template <typename T>
+class TypedMethodOptionMatcher : public MethodMatcher {
+  const char* _option;
+  OptionType _type;
+  const T _value;
+
+public:
+  TypedMethodOptionMatcher(Symbol* class_name, Mode class_mode,
+                           Symbol* method_name, Mode method_mode,
+                           Symbol* signature, const char* opt,
+                           const T value,  MethodMatcher* next) :
+    MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
+                  _type(get_type_for<T>()), _value(copy_value<T>(value)) {
+    _option = os::strdup_check_oom(opt);
   }
 
-  virtual ~MethodOptionMatcher() {
-    os::free((void*)option);
+  ~TypedMethodOptionMatcher() {
+    os::free((void*)_option);
   }
 
-  bool match(methodHandle method, const char* opt) {
-    MethodOptionMatcher* current = this;
+  TypedMethodOptionMatcher* match(methodHandle method, const char* opt) {
+    TypedMethodOptionMatcher* current = this;
     while (current != NULL) {
-      current = (MethodOptionMatcher*)current->find(method);
+      current = (TypedMethodOptionMatcher*)current->find(method);
       if (current == NULL) {
-        return false;
+        return NULL;
       }
-      if (strcmp(current->option, opt) == 0) {
-        return true;
+      if (strcmp(current->_option, opt) == 0) {
+        return current;
       }
       current = current->next();
     }
-    return false;
+    return NULL;
+  }
+
+  TypedMethodOptionMatcher* next() {
+    return (TypedMethodOptionMatcher*)_next;
   }
 
-  MethodOptionMatcher* next() {
-    return (MethodOptionMatcher*)_next;
-  }
+  OptionType get_type(void) {
+      return _type;
+  };
+
+  T value() { return _value; }
 
-  virtual void print() {
+  void print() {
+    ttyLocker ttyl;
     print_base();
-    tty->print(" %s", option);
+    tty->print(" %s", _option);
+    tty->print(" <unknown option type>");
     tty->cr();
   }
 };
 
+template<>
+void TypedMethodOptionMatcher<intx>::print() {
+  ttyLocker ttyl;
+  print_base();
+  tty->print(" intx %s", _option);
+  tty->print(" = " INTX_FORMAT, _value);
+  tty->cr();
+};
 
+template<>
+void TypedMethodOptionMatcher<uintx>::print() {
+  ttyLocker ttyl;
+  print_base();
+  tty->print(" uintx %s", _option);
+  tty->print(" = " UINTX_FORMAT, _value);
+  tty->cr();
+};
+
+template<>
+void TypedMethodOptionMatcher<bool>::print() {
+  ttyLocker ttyl;
+  print_base();
+  tty->print(" bool %s", _option);
+  tty->print(" = %s", _value ? "true" : "false");
+  tty->cr();
+};
+
+template<>
+void TypedMethodOptionMatcher<ccstr>::print() {
+  ttyLocker ttyl;
+  print_base();
+  tty->print(" const char* %s", _option);
+  tty->print(" = '%s'", _value);
+  tty->cr();
+};
 
 // this must parallel the command_names below
 enum OracleCommand {
@@ -264,23 +350,46 @@
   return lists[command];
 }
 
-
-
+template<typename T>
 static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode,
                                         Symbol* method_name, MethodMatcher::Mode m_mode,
                                         Symbol* signature,
-                                        const char* option) {
-  lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode,
-                                                 signature, option, lists[OptionCommand]);
+                                        const char* option,
+                                        T value) {
+  lists[OptionCommand] = new TypedMethodOptionMatcher<T>(class_name, c_mode, method_name, m_mode,
+                                                         signature, option, value, lists[OptionCommand]);
   return lists[OptionCommand];
 }
 
+template<typename T>
+static bool get_option_value(methodHandle method, const char* option, T& value) {
+   TypedMethodOptionMatcher<T>* m;
+   if (lists[OptionCommand] != NULL
+       && (m = ((TypedMethodOptionMatcher<T>*)lists[OptionCommand])->match(method, option)) != NULL
+       && m->get_type() == get_type_for<T>()) {
+       value = m->value();
+       return true;
+   } else {
+     return false;
+   }
+}
 
 bool CompilerOracle::has_option_string(methodHandle method, const char* option) {
-  return lists[OptionCommand] != NULL &&
-    ((MethodOptionMatcher*)lists[OptionCommand])->match(method, option);
+  bool value = false;
+  get_option_value(method, option, value);
+  return value;
 }
 
+template<typename T>
+bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) {
+  return ::get_option_value(method, option, value);
+}
+
+// Explicit instantiation for all OptionTypes supported.
+template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
+template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
+template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value);
+template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value);
 
 bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
   quietly = true;
@@ -422,6 +531,94 @@
 
 
 
+// Scan next flag and value in line, return MethodMatcher object on success, NULL on failure.
+// On failure, error_msg contains description for the first error.
+// For future extensions: set error_msg on first error.
+static MethodMatcher* scan_flag_and_value(const char* type, const char* line, int& total_bytes_read,
+                                          Symbol* c_name, MethodMatcher::Mode c_match,
+                                          Symbol* m_name, MethodMatcher::Mode m_match,
+                                          Symbol* signature,
+                                          char* errorbuf, const int buf_size) {
+  total_bytes_read = 0;
+  int bytes_read = 0;
+  char flag[256];
+
+  // Read flag name.
+  if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", flag, &bytes_read) == 1) {
+    line += bytes_read;
+    total_bytes_read += bytes_read;
+
+    // Read value.
+    if (strcmp(type, "intx") == 0) {
+      intx value;
+      if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
+        total_bytes_read += bytes_read;
+        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
+      } else {
+        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s ", flag, type);
+      }
+    } else if (strcmp(type, "uintx") == 0) {
+      uintx value;
+      if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
+        total_bytes_read += bytes_read;
+        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
+      } else {
+        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
+      }
+    } else if (strcmp(type, "ccstr") == 0) {
+      ResourceMark rm;
+      char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
+      if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
+        total_bytes_read += bytes_read;
+        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
+      } else {
+        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
+      }
+    } else if (strcmp(type, "ccstrlist") == 0) {
+      // Accumulates several strings into one. The internal type is ccstr.
+      ResourceMark rm;
+      char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
+      char* next_value = value;
+      if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
+        total_bytes_read += bytes_read;
+        line += bytes_read;
+        next_value += bytes_read;
+        char* end_value = next_value-1;
+        while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
+          total_bytes_read += bytes_read;
+          line += bytes_read;
+          *end_value = ' '; // override '\0'
+          next_value += bytes_read;
+          end_value = next_value-1;
+        }
+        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
+      } else {
+        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
+      }
+    } else if (strcmp(type, "bool") == 0) {
+      char value[256];
+      if (sscanf(line, "%*[ \t]%255[a-zA-Z]%n", value, &bytes_read) == 1) {
+        if (strcmp(value, "true") == 0) {
+          total_bytes_read += bytes_read;
+          return add_option_string(c_name, c_match, m_name, m_match, signature, flag, true);
+        } else if (strcmp(value, "false") == 0) {
+          total_bytes_read += bytes_read;
+          return add_option_string(c_name, c_match, m_name, m_match, signature, flag, false);
+        } else {
+          jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
+        }
+      } else {
+        jio_snprintf(errorbuf, sizeof(errorbuf), "  Value cannot be read for flag %s of type %s", flag, type);
+      }
+    } else {
+      jio_snprintf(errorbuf, sizeof(errorbuf), "  Type %s not supported ", type);
+    }
+  } else {
+    jio_snprintf(errorbuf, sizeof(errorbuf), "  Flag name for type %s should be alphanumeric ", type);
+  }
+  return NULL;
+}
+
 void CompilerOracle::parse_from_line(char* line) {
   if (line[0] == '\0') return;
   if (line[0] == '#')  return;
@@ -451,8 +648,10 @@
   int bytes_read;
   OracleCommand command = parse_command_name(line, &bytes_read);
   line += bytes_read;
+  ResourceMark rm;
 
   if (command == UnknownCommand) {
+    ttyLocker ttyl;
     tty->print_cr("CompilerOracle: unrecognized line");
     tty->print_cr("  \"%s\"", original_line);
     return;
@@ -474,7 +673,7 @@
   char method_name[256];
   char sig[1024];
   char errorbuf[1024];
-  const char* error_msg = NULL;
+  const char* error_msg = NULL; // description of first error that appears
   MethodMatcher* match = NULL;
 
   if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) {
@@ -493,43 +692,77 @@
     }
 
     if (command == OptionCommand) {
-      // Look for trailing options to support
-      // ciMethod::has_option("string") to control features in the
-      // compiler.  Multiple options may follow the method name.
-      char option[256];
+      // Look for trailing options.
+      //
+      // Two types of trailing options are
+      // supported:
+      //
+      // (1) CompileCommand=option,Klass::method,flag
+      // (2) CompileCommand=option,Klass::method,type,flag,value
+      //
+      // Type (1) is used to support ciMethod::has_option("someflag")
+      // (i.e., to check if a flag "someflag" is enabled for a method).
+      //
+      // Type (2) is used to support options with a value. Values can have the
+      // the following types: intx, uintx, bool, ccstr, and ccstrlist.
+      //
+      // For future extensions: extend scan_flag_and_value()
+      char option[256]; // stores flag for Type (1) and type of Type (2)
       while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
         if (match != NULL && !_quiet) {
           // Print out the last match added
+          ttyLocker ttyl;
           tty->print("CompilerOracle: %s ", command_names[command]);
           match->print();
         }
-        match = add_option_string(c_name, c_match, m_name, m_match, signature, option);
         line += bytes_read;
-      }
+
+        if (strcmp(option, "intx") == 0
+            || strcmp(option, "uintx") == 0
+            || strcmp(option, "bool") == 0
+            || strcmp(option, "ccstr") == 0
+            || strcmp(option, "ccstrlist") == 0
+            ) {
+
+          // Type (2) option: parse flag name and value.
+          match = scan_flag_and_value(option, line, bytes_read,
+                                      c_name, c_match, m_name, m_match, signature,
+                                      errorbuf, sizeof(errorbuf));
+          if (match == NULL) {
+            error_msg = errorbuf;
+            break;
+          }
+          line += bytes_read;
+        } else {
+          // Type (1) option
+          match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true);
+        }
+      } // while(
     } else {
-      bytes_read = 0;
-      sscanf(line, "%*[ \t]%n", &bytes_read);
-      if (line[bytes_read] != '\0') {
-        jio_snprintf(errorbuf, sizeof(errorbuf), "  Unrecognized text after command: %s", line);
-        error_msg = errorbuf;
-      } else {
-        match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
-      }
+      match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
     }
   }
 
-  if (match != NULL) {
-    if (!_quiet) {
-      ResourceMark rm;
-      tty->print("CompilerOracle: %s ", command_names[command]);
-      match->print();
-    }
-  } else {
+  ttyLocker ttyl;
+  if (error_msg != NULL) {
+    // an error has happened
     tty->print_cr("CompilerOracle: unrecognized line");
     tty->print_cr("  \"%s\"", original_line);
     if (error_msg != NULL) {
       tty->print_cr("%s", error_msg);
     }
+  } else {
+    // check for remaining characters
+    bytes_read = 0;
+    sscanf(line, "%*[ \t]%n", &bytes_read);
+    if (line[bytes_read] != '\0') {
+      tty->print_cr("CompilerOracle: unrecognized line");
+      tty->print_cr("  \"%s\"", original_line);
+      tty->print_cr("  Unrecognized text %s after command ", line);
+    } else if (match != NULL && !_quiet) {
+      tty->print("CompilerOracle: %s ", command_names[command]);
+      match->print();
+    }
   }
 }
 
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -64,6 +64,11 @@
   // Check to see if this method has option set for it
   static bool has_option_string(methodHandle method, const char * option);
 
+  // Check if method has option and value set. If yes, overwrite value and return true,
+  // otherwise leave value unchanged and return false.
+  template<typename T>
+  static bool has_option_value(methodHandle method, const char* option, T& value);
+
   // Reads from string instead of file
   static void parse_from_string(const char* command_string, void (*parser)(char*));
 
--- a/hotspot/src/share/vm/compiler/disassembler.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -246,12 +246,12 @@
 };
 
 decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) {
-  memset(this, 0, sizeof(*this));
+  memset(this, 0, sizeof(*this)); // Beware, this zeroes bits of fields.
   _output = output ? output : tty;
   _code = code;
   if (code != NULL && code->is_nmethod())
     _nm = (nmethod*) code;
-  _strings.assign(c);
+  _strings.copy(c);
 
   // by default, output pc but not bytes:
   _print_pc       = true;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -22,372 +22,375 @@
  *
  */
 
-
 #include "precompiled.hpp"
+#include "code/codeCache.hpp"
 #include "code/nmethod.hpp"
 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
+#include "memory/heap.hpp"
 #include "memory/iterator.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/hashtable.inline.hpp"
+#include "utilities/stack.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
-G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
-  _top = bottom();
+class CodeRootSetTable : public Hashtable<nmethod*, mtGC> {
+  friend class G1CodeRootSetTest;
+  typedef HashtableEntry<nmethod*, mtGC> Entry;
+
+  static CodeRootSetTable* volatile _purge_list;
+
+  CodeRootSetTable* _purge_next;
+
+  unsigned int compute_hash(nmethod* nm) {
+    uintptr_t hash = (uintptr_t)nm;
+    return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
+  }
+
+  Entry* new_entry(nmethod* nm);
+
+ public:
+  CodeRootSetTable(int size) : Hashtable<nmethod*, mtGC>(size, sizeof(Entry)), _purge_next(NULL) {}
+  ~CodeRootSetTable();
+
+  // Needs to be protected locks
+  bool add(nmethod* nm);
+  bool remove(nmethod* nm);
+
+  // Can be called without locking
+  bool contains(nmethod* nm);
+
+  int entry_size() const { return BasicHashtable<mtGC>::entry_size(); }
+
+  void copy_to(CodeRootSetTable* new_table);
+  void nmethods_do(CodeBlobClosure* blk);
+
+  template<typename CB>
+  void remove_if(CB& should_remove);
+
+  static void purge_list_append(CodeRootSetTable* tbl);
+  static void purge();
+
+  static size_t static_mem_size() {
+    return sizeof(_purge_list);
+  }
+};
+
+CodeRootSetTable* volatile CodeRootSetTable::_purge_list = NULL;
+
+CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) {
+  unsigned int hash = compute_hash(nm);
+  Entry* entry = (Entry*) new_entry_free_list();
+  if (entry == NULL) {
+    entry = (Entry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtGC, CURRENT_PC);
+  }
+  entry->set_next(NULL);
+  entry->set_hash(hash);
+  entry->set_literal(nm);
+  return entry;
 }
 
-void G1CodeRootChunk::reset() {
-  _next = _prev = NULL;
-  _free = NULL;
-  _top = bottom();
-}
-
-void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
-  NmethodOrLink* cur = bottom();
-  while (cur != _top) {
-    if (is_nmethod(cur)) {
-      cl->do_code_blob(cur->_nmethod);
+CodeRootSetTable::~CodeRootSetTable() {
+  for (int index = 0; index < table_size(); ++index) {
+    for (Entry* e = bucket(index); e != NULL; ) {
+      Entry* to_remove = e;
+      // read next before freeing.
+      e = e->next();
+      unlink_entry(to_remove);
+      FREE_C_HEAP_ARRAY(char, to_remove, mtGC);
     }
-    cur++;
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  free_buckets();
+  for (BasicHashtableEntry<mtGC>* e = new_entry_free_list(); e != NULL; e = new_entry_free_list()) {
+    FREE_C_HEAP_ARRAY(char, e, mtGC);
   }
 }
 
-bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
-  NmethodOrLink* cur = bottom();
-
-  for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
-    if (cur->_nmethod == method) {
-      bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
+bool CodeRootSetTable::add(nmethod* nm) {
+  if (!contains(nm)) {
+    Entry* e = new_entry(nm);
+    int index = hash_to_index(e->hash());
+    add_entry(index, e);
+    return true;
+  }
+  return false;
+}
 
-      if (!result) {
-        // Someone else cleared out this entry.
-        return false;
-      }
+bool CodeRootSetTable::contains(nmethod* nm) {
+  int index = hash_to_index(compute_hash(nm));
+  for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+    if (e->literal() == nm) {
+      return true;
+    }
+  }
+  return false;
+}
 
-      // The method was cleared. Time to link it into the free list.
-      NmethodOrLink* prev_free;
-      do {
-        prev_free = (NmethodOrLink*)_free;
-        cur->_link = prev_free;
-      } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
-
+bool CodeRootSetTable::remove(nmethod* nm) {
+  int index = hash_to_index(compute_hash(nm));
+  Entry* previous = NULL;
+  for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
+    if (e->literal() == nm) {
+      if (previous != NULL) {
+        previous->set_next(e->next());
+      } else {
+        set_entry(index, e->next());
+      }
+      free_entry(e);
       return true;
     }
   }
-
   return false;
 }
 
-G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
-  _free_list.initialize();
-  _free_list.set_size(G1CodeRootChunk::word_size());
+void CodeRootSetTable::copy_to(CodeRootSetTable* new_table) {
+  for (int index = 0; index < table_size(); ++index) {
+    for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+      new_table->add(e->literal());
+    }
+  }
+  new_table->copy_freelist(this);
 }
 
-size_t G1CodeRootChunkManager::fl_mem_size() {
-  return _free_list.count() * _free_list.size();
-}
-
-void G1CodeRootChunkManager::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
-  _num_chunks_handed_out -= list->count();
-  _free_list.prepend(list);
+void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {
+  for (int index = 0; index < table_size(); ++index) {
+    for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+      blk->do_code_blob(e->literal());
+    }
+  }
 }
 
-void G1CodeRootChunkManager::free_chunk(G1CodeRootChunk* chunk) {
-  _free_list.return_chunk_at_head(chunk);
-  _num_chunks_handed_out--;
+template<typename CB>
+void CodeRootSetTable::remove_if(CB& should_remove) {
+  for (int index = 0; index < table_size(); ++index) {
+    Entry* previous = NULL;
+    Entry* e = bucket(index);
+    while (e != NULL) {
+      Entry* next = e->next();
+      if (should_remove(e->literal())) {
+        if (previous != NULL) {
+          previous->set_next(next);
+        } else {
+          set_entry(index, next);
+        }
+        free_entry(e);
+      } else {
+        previous = e;
+      }
+      e = next;
+    }
+  }
+}
+
+G1CodeRootSet::~G1CodeRootSet() {
+  delete _table;
 }
 
-void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
-  size_t keep = _num_chunks_handed_out * keep_ratio / 100;
-  if (keep >= (size_t)_free_list.count()) {
-    return;
-  }
+CodeRootSetTable* G1CodeRootSet::load_acquire_table() {
+  return (CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table);
+}
+
+void G1CodeRootSet::allocate_small_table() {
+  _table = new CodeRootSetTable(SmallSize);
+}
 
-  FreeList<G1CodeRootChunk> temp;
-  temp.initialize();
-  temp.set_size(G1CodeRootChunk::word_size());
+void CodeRootSetTable::purge_list_append(CodeRootSetTable* table) {
+  for (;;) {
+    table->_purge_next = _purge_list;
+    CodeRootSetTable* old = (CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next);
+    if (old == table->_purge_next) {
+      break;
+    }
+  }
+}
 
-  _free_list.getFirstNChunksFromList((size_t)_free_list.count() - keep, &temp);
-
-  G1CodeRootChunk* cur = temp.get_chunk_at_head();
-  while (cur != NULL) {
-    delete cur;
-    cur = temp.get_chunk_at_head();
+void CodeRootSetTable::purge() {
+  CodeRootSetTable* table = _purge_list;
+  _purge_list = NULL;
+  while (table != NULL) {
+    CodeRootSetTable* to_purge = table;
+    table = table->_purge_next;
+    delete to_purge;
   }
 }
 
-size_t G1CodeRootChunkManager::static_mem_size() {
-  return sizeof(G1CodeRootChunkManager);
+void G1CodeRootSet::move_to_large() {
+  CodeRootSetTable* temp = new CodeRootSetTable(LargeSize);
+
+  _table->copy_to(temp);
+
+  CodeRootSetTable::purge_list_append(_table);
+
+  OrderAccess::release_store_ptr(&_table, temp);
 }
 
 
-G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
-  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
-  if (result == NULL) {
-    result = new G1CodeRootChunk();
+void G1CodeRootSet::purge() {
+  CodeRootSetTable::purge();
+}
+
+size_t G1CodeRootSet::static_mem_size() {
+  return CodeRootSetTable::static_mem_size();
+}
+
+void G1CodeRootSet::add(nmethod* method) {
+  bool added = false;
+  if (is_empty()) {
+    allocate_small_table();
+  }
+  added = _table->add(method);
+  if (_length == Threshold) {
+    move_to_large();
+  }
+  if (added) {
+    ++_length;
+  }
+}
+
+bool G1CodeRootSet::remove(nmethod* method) {
+  bool removed = false;
+  if (_table != NULL) {
+    removed = _table->remove(method);
+  }
+  if (removed) {
+    _length--;
+    if (_length == 0) {
+      clear();
+    }
+  }
+  return removed;
+}
+
+bool G1CodeRootSet::contains(nmethod* method) {
+  CodeRootSetTable* table = load_acquire_table();
+  if (table != NULL) {
+    return table->contains(method);
   }
-  _num_chunks_handed_out++;
-  result->reset();
-  return result;
+  return false;
+}
+
+void G1CodeRootSet::clear() {
+  delete _table;
+  _table = NULL;
+  _length = 0;
+}
+
+size_t G1CodeRootSet::mem_size() {
+  return sizeof(*this) +
+      (_table != NULL ? sizeof(CodeRootSetTable) + _table->entry_size() * _length : 0);
+}
+
+void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
+  if (_table != NULL) {
+    _table->nmethods_do(blk);
+  }
+}
+
+class CleanCallback : public StackObj {
+  class PointsIntoHRDetectionClosure : public OopClosure {
+    HeapRegion* _hr;
+   public:
+    bool _points_into;
+    PointsIntoHRDetectionClosure(HeapRegion* hr) : _hr(hr), _points_into(false) {}
+
+    void do_oop(narrowOop* o) {
+      do_oop_work(o);
+    }
+
+    void do_oop(oop* o) {
+      do_oop_work(o);
+    }
+
+    template <typename T>
+    void do_oop_work(T* p) {
+      if (_hr->is_in(oopDesc::load_decode_heap_oop(p))) {
+        _points_into = true;
+      }
+    }
+  };
+
+  PointsIntoHRDetectionClosure _detector;
+  CodeBlobToOopClosure _blobs;
+
+ public:
+  CleanCallback(HeapRegion* hr) : _detector(hr), _blobs(&_detector, !CodeBlobToOopClosure::FixRelocations) {}
+
+  bool operator() (nmethod* nm) {
+    _detector._points_into = false;
+    _blobs.do_code_blob(nm);
+    return _detector._points_into;
+  }
+};
+
+void G1CodeRootSet::clean(HeapRegion* owner) {
+  CleanCallback should_clean(owner);
+  if (_table != NULL) {
+    _table->remove_if(should_clean);
+  }
 }
 
 #ifndef PRODUCT
 
-size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
-  return _num_chunks_handed_out;
-}
+class G1CodeRootSetTest {
+ public:
+  static void test() {
+    {
+      G1CodeRootSet set1;
+      assert(set1.is_empty(), "Code root set must be initially empty but is not.");
+
+      assert(G1CodeRootSet::static_mem_size() == sizeof(void*),
+          err_msg("The code root set's static memory usage is incorrect, "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
+
+      set1.add((nmethod*)1);
+      assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
+          SIZE_FORMAT" elements", set1.length()));
+
+      const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1;
+
+      for (size_t i = 1; i <= num_to_add; i++) {
+        set1.add((nmethod*)1);
+      }
+      assert(set1.length() == 1,
+          err_msg("Duplicate detection should not have increased the set size but "
+              "is "SIZE_FORMAT, set1.length()));
 
-size_t G1CodeRootChunkManager::num_free_chunks() const {
-  return (size_t)_free_list.count();
+      for (size_t i = 2; i <= num_to_add; i++) {
+        set1.add((nmethod*)(uintptr_t)(i));
+      }
+      assert(set1.length() == num_to_add,
+          err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
+              "need to be in the set, but there are only "SIZE_FORMAT,
+              num_to_add, set1.length()));
+
+      assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
+
+      size_t num_popped = 0;
+      for (size_t i = 1; i <= num_to_add; i++) {
+        bool removed = set1.remove((nmethod*)i);
+        if (removed) {
+          num_popped += 1;
+        } else {
+          break;
+        }
+      }
+      assert(num_popped == num_to_add,
+          err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
+              "were added", num_popped, num_to_add));
+      assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
+
+      G1CodeRootSet::purge();
+
+      assert(CodeRootSetTable::_purge_list == NULL, "should have purged old small tables");
+
+    }
+
+  }
+};
+
+void TestCodeCacheRemSet_test() {
+  G1CodeRootSetTest::test();
 }
 
 #endif
-
-G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
-
-void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
-  _default_chunk_manager.purge_chunks(keep_ratio);
-}
-
-size_t G1CodeRootSet::free_chunks_static_mem_size() {
-  return _default_chunk_manager.static_mem_size();
-}
-
-size_t G1CodeRootSet::free_chunks_mem_size() {
-  return _default_chunk_manager.fl_mem_size();
-}
-
-G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
-  if (_manager == NULL) {
-    _manager = &_default_chunk_manager;
-  }
-  _list.initialize();
-  _list.set_size(G1CodeRootChunk::word_size());
-}
-
-G1CodeRootSet::~G1CodeRootSet() {
-  clear();
-}
-
-void G1CodeRootSet::add(nmethod* method) {
-  if (!contains(method)) {
-    // Find the first chunk that isn't full.
-    G1CodeRootChunk* cur = _list.head();
-    while (cur != NULL) {
-      if (!cur->is_full()) {
-        break;
-      }
-      cur = cur->next();
-    }
-
-    // All chunks are full, get a new chunk.
-    if (cur == NULL) {
-      cur = new_chunk();
-      _list.return_chunk_at_head(cur);
-    }
-
-    // Add the nmethod.
-    bool result = cur->add(method);
-
-    guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
-
-    _length++;
-  }
-}
-
-void G1CodeRootSet::remove_lock_free(nmethod* method) {
-  G1CodeRootChunk* found = find(method);
-  if (found != NULL) {
-    bool result = found->remove_lock_free(method);
-    if (result) {
-      Atomic::dec_ptr((volatile intptr_t*)&_length);
-    }
-  }
-  assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
-}
-
-nmethod* G1CodeRootSet::pop() {
-  while (true) {
-    G1CodeRootChunk* cur = _list.head();
-    if (cur == NULL) {
-      assert(_length == 0, "when there are no chunks, there should be no elements");
-      return NULL;
-    }
-    nmethod* result = cur->pop();
-    if (result != NULL) {
-      _length--;
-      return result;
-    } else {
-      free(_list.get_chunk_at_head());
-    }
-  }
-}
-
-G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
-  G1CodeRootChunk* cur = _list.head();
-  while (cur != NULL) {
-    if (cur->contains(method)) {
-      return cur;
-    }
-    cur = (G1CodeRootChunk*)cur->next();
-  }
-  return NULL;
-}
-
-void G1CodeRootSet::free(G1CodeRootChunk* chunk) {
-  free_chunk(chunk);
-}
-
-bool G1CodeRootSet::contains(nmethod* method) {
-  return find(method) != NULL;
-}
-
-void G1CodeRootSet::clear() {
-  free_all_chunks(&_list);
-  _length = 0;
-}
-
-void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
-  G1CodeRootChunk* cur = _list.head();
-  while (cur != NULL) {
-    cur->nmethods_do(blk);
-    cur = (G1CodeRootChunk*)cur->next();
-  }
-}
-
-size_t G1CodeRootSet::static_mem_size() {
-  return sizeof(G1CodeRootSet);
-}
-
-size_t G1CodeRootSet::mem_size() {
-  return G1CodeRootSet::static_mem_size() + _list.count() * _list.size();
-}
-
-#ifndef PRODUCT
-
-void G1CodeRootSet::test() {
-  G1CodeRootChunkManager mgr;
-
-  assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
-
-  assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*),
-         err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size()));
-
-  // The number of chunks that we allocate for purge testing.
-  size_t const num_chunks = 10;
-
-  {
-    G1CodeRootSet set1(&mgr);
-    assert(set1.is_empty(), "Code root set must be initially empty but is not.");
-
-    assert(G1CodeRootSet::static_mem_size() > sizeof(void*),
-           err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
-
-    set1.add((nmethod*)1);
-    assert(mgr.num_chunks_handed_out() == 1,
-           err_msg("Must have allocated and handed out one chunk, but handed out "
-                   SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
-    assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
-                                       SIZE_FORMAT" elements", set1.length()));
-
-    // G1CodeRootChunk::word_size() is larger than G1CodeRootChunk::num_entries which
-    // we cannot access.
-    for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
-      set1.add((nmethod*)1);
-    }
-    assert(mgr.num_chunks_handed_out() == 1,
-           err_msg("Duplicate detection must have prevented allocation of further "
-                   "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
-    assert(set1.length() == 1,
-           err_msg("Duplicate detection should not have increased the set size but "
-                   "is "SIZE_FORMAT, set1.length()));
-
-    size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;
-    for (size_t i = 0; i < num_total_after_add - 1; i++) {
-      set1.add((nmethod*)(uintptr_t)(2 + i));
-    }
-    assert(mgr.num_chunks_handed_out() > 1,
-           "After adding more code roots, more than one additional chunk should have been handed out");
-    assert(set1.length() == num_total_after_add,
-           err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
-                   "need to be in the set, but there are only "SIZE_FORMAT,
-                   num_total_after_add, set1.length()));
-
-    size_t num_popped = 0;
-    while (set1.pop() != NULL) {
-      num_popped++;
-    }
-    assert(num_popped == num_total_after_add,
-           err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
-                   "were added", num_popped, num_total_after_add));
-    assert(mgr.num_chunks_handed_out() == 0,
-           err_msg("After popping all elements, all chunks must have been returned "
-                   "but there are still "SIZE_FORMAT" additional", mgr.num_chunks_handed_out()));
-
-    mgr.purge_chunks(0);
-    assert(mgr.num_free_chunks() == 0,
-           err_msg("After purging everything, the free list must be empty but still "
-                   "contains "SIZE_FORMAT" chunks", mgr.num_free_chunks()));
-
-    // Add some more handed out chunks.
-    size_t i = 0;
-    while (mgr.num_chunks_handed_out() < num_chunks) {
-      set1.add((nmethod*)i);
-      i++;
-    }
-
-    {
-      // Generate chunks on the free list.
-      G1CodeRootSet set2(&mgr);
-      size_t i = 0;
-      while (mgr.num_chunks_handed_out() < (num_chunks * 2)) {
-        set2.add((nmethod*)i);
-        i++;
-      }
-      // Exit of the scope of the set2 object will call the destructor that generates
-      // num_chunks elements on the free list.
-    }
-
-    assert(mgr.num_chunks_handed_out() == num_chunks,
-           err_msg("Deletion of the second set must have resulted in giving back "
-                   "those, but there are still "SIZE_FORMAT" additional handed out, expecting "
-                   SIZE_FORMAT, mgr.num_chunks_handed_out(), num_chunks));
-    assert(mgr.num_free_chunks() == num_chunks,
-           err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                   "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
-
-    size_t const test_percentage = 50;
-    mgr.purge_chunks(test_percentage);
-    assert(mgr.num_chunks_handed_out() == num_chunks,
-           err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT,
-                   mgr.num_chunks_handed_out()));
-    assert(mgr.num_free_chunks() == (size_t)(mgr.num_chunks_handed_out() * test_percentage / 100),
-           err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks"
-                   "but there are "SIZE_FORMAT, test_percentage, num_chunks,
-                   mgr.num_free_chunks()));
-    // Purge the remainder of the chunks on the free list.
-    mgr.purge_chunks(0);
-    assert(mgr.num_free_chunks() == 0, "Free List must be empty");
-    assert(mgr.num_chunks_handed_out() == num_chunks,
-           err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set "
-                   "but there are "SIZE_FORMAT, num_chunks, mgr.num_chunks_handed_out()));
-
-    // Exit of the scope of the set1 object will call the destructor that generates
-    // num_chunks additional elements on the free list.
-   }
-
-  assert(mgr.num_chunks_handed_out() == 0,
-         err_msg("Deletion of the only set must have resulted in no chunks handed "
-                 "out, but there is still "SIZE_FORMAT" handed out", mgr.num_chunks_handed_out()));
-  assert(mgr.num_free_chunks() == num_chunks,
-         err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                 "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
-
-  // Restore initial state.
-  mgr.purge_chunks(0);
-  assert(mgr.num_free_chunks() == 0, "Free List must be empty");
-  assert(mgr.num_chunks_handed_out() == 0, "No additional elements must have been handed out yet");
-}
-
-void TestCodeCacheRemSet_test() {
-  G1CodeRootSet::test();
-}
-#endif
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -26,222 +26,64 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/freeList.hpp"
-#include "runtime/globals.hpp"
 
 class CodeBlobClosure;
-
-// The elements of the G1CodeRootChunk is either:
-//  1) nmethod pointers
-//  2) nodes in an internally chained free list
-typedef union {
-  nmethod* _nmethod;
-  void*    _link;
-} NmethodOrLink;
-
-class G1CodeRootChunk : public CHeapObj<mtGC> {
- private:
-  static const int NUM_ENTRIES = 32;
- public:
-  G1CodeRootChunk*     _next;
-  G1CodeRootChunk*     _prev;
-
-  NmethodOrLink*          _top;
-  // First free position within the chunk.
-  volatile NmethodOrLink* _free;
-
-  NmethodOrLink _data[NUM_ENTRIES];
-
-  NmethodOrLink* bottom() const {
-    return (NmethodOrLink*) &(_data[0]);
-  }
-
-  NmethodOrLink* end() const {
-    return (NmethodOrLink*) &(_data[NUM_ENTRIES]);
-  }
-
-  bool is_link(NmethodOrLink* nmethod_or_link) {
-    return nmethod_or_link->_link == NULL ||
-        (bottom() <= nmethod_or_link->_link
-        && nmethod_or_link->_link < end());
-  }
-
-  bool is_nmethod(NmethodOrLink* nmethod_or_link) {
-    return !is_link(nmethod_or_link);
-  }
-
- public:
-  G1CodeRootChunk();
-  ~G1CodeRootChunk() {}
-
-  static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); }
-
-  // FreeList "interface" methods
-
-  G1CodeRootChunk* next() const         { return _next; }
-  G1CodeRootChunk* prev() const         { return _prev; }
-  void set_next(G1CodeRootChunk* v)     { _next = v; assert(v != this, "Boom");}
-  void set_prev(G1CodeRootChunk* v)     { _prev = v; assert(v != this, "Boom");}
-  void clear_next()       { set_next(NULL); }
-  void clear_prev()       { set_prev(NULL); }
-
-  size_t size() const { return word_size(); }
-
-  void link_next(G1CodeRootChunk* ptr)  { set_next(ptr); }
-  void link_prev(G1CodeRootChunk* ptr)  { set_prev(ptr); }
-  void link_after(G1CodeRootChunk* ptr) {
-    link_next(ptr);
-    if (ptr != NULL) ptr->link_prev((G1CodeRootChunk*)this);
-  }
-
-  bool is_free()                 { return true; }
-
-  // New G1CodeRootChunk routines
-
-  void reset();
-
-  bool is_empty() const {
-    return _top == bottom();
-  }
-
-  bool is_full() const {
-    return _top == end() && _free == NULL;
-  }
-
-  bool contains(nmethod* method) {
-    NmethodOrLink* cur = bottom();
-    while (cur != _top) {
-      if (cur->_nmethod == method) return true;
-      cur++;
-    }
-    return false;
-  }
-
-  bool add(nmethod* method) {
-    if (is_full()) {
-      return false;
-    }
-
-    if (_free != NULL) {
-      // Take from internally chained free list
-      NmethodOrLink* first_free = (NmethodOrLink*)_free;
-      _free = (NmethodOrLink*)_free->_link;
-      first_free->_nmethod = method;
-    } else {
-      // Take from top.
-      _top->_nmethod = method;
-      _top++;
-    }
-
-    return true;
-  }
-
-  bool remove_lock_free(nmethod* method);
-
-  void nmethods_do(CodeBlobClosure* blk);
-
-  nmethod* pop() {
-    if (_free != NULL) {
-      // Kill the free list.
-      _free = NULL;
-    }
-
-    while (!is_empty()) {
-      _top--;
-      if (is_nmethod(_top)) {
-        return _top->_nmethod;
-      }
-    }
-
-    return NULL;
-  }
-};
-
-// Manages free chunks.
-class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC {
- private:
-  // Global free chunk list management
-  FreeList<G1CodeRootChunk> _free_list;
-  // Total number of chunks handed out
-  size_t _num_chunks_handed_out;
-
- public:
-  G1CodeRootChunkManager();
-
-  G1CodeRootChunk* new_chunk();
-  void free_chunk(G1CodeRootChunk* chunk);
-  // Free all elements of the given list.
-  void free_all_chunks(FreeList<G1CodeRootChunk>* list);
-
-  void initialize();
-  void purge_chunks(size_t keep_ratio);
-
-  static size_t static_mem_size();
-  size_t fl_mem_size();
-
-#ifndef PRODUCT
-  size_t num_chunks_handed_out() const;
-  size_t num_free_chunks() const;
-#endif
-};
+class CodeRootSetTable;
+class HeapRegion;
+class nmethod;
 
 // Implements storage for a set of code roots.
 // All methods that modify the set are not thread-safe except if otherwise noted.
 class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
+  friend class G1CodeRootSetTest;
  private:
-  // Global default free chunk manager instance.
-  static G1CodeRootChunkManager _default_chunk_manager;
 
-  G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); }
-  void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); }
-  // Free all elements of the given list.
-  void free_all_chunks(FreeList<G1CodeRootChunk>* list) { _manager->free_all_chunks(list); }
+  const static size_t SmallSize = 32;
+  const static size_t Threshold = 24;
+  const static size_t LargeSize = 512;
 
-  // Return the chunk that contains the given nmethod, NULL otherwise.
-  // Scans the list of chunks backwards, as this method is used to add new
-  // entries, which are typically added in bulk for a single nmethod.
-  G1CodeRootChunk* find(nmethod* method);
-  void free(G1CodeRootChunk* chunk);
+  CodeRootSetTable* _table;
+  CodeRootSetTable* load_acquire_table();
 
   size_t _length;
-  FreeList<G1CodeRootChunk> _list;
-  G1CodeRootChunkManager* _manager;
+
+  void move_to_large();
+  void allocate_small_table();
 
  public:
-  // If an instance is initialized with a chunk manager of NULL, use the global
-  // default one.
-  G1CodeRootSet(G1CodeRootChunkManager* manager = NULL);
+  G1CodeRootSet() : _table(NULL), _length(0) {}
   ~G1CodeRootSet();
 
-  static void purge_chunks(size_t keep_ratio);
+  static void purge();
 
-  static size_t free_chunks_static_mem_size();
-  static size_t free_chunks_mem_size();
+  static size_t static_mem_size();
 
-  // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
-  // method is likely to be repeatedly called with the same nmethod.
   void add(nmethod* method);
 
-  void remove_lock_free(nmethod* method);
-  nmethod* pop();
+  bool remove(nmethod* method);
 
+  // Safe to call without synchronization, but may return false negatives.
   bool contains(nmethod* method);
 
   void clear();
 
   void nmethods_do(CodeBlobClosure* blk) const;
 
-  bool is_empty() { return length() == 0; }
+  // Remove all nmethods which no longer contain pointers into our "owner" region
+  void clean(HeapRegion* owner);
+
+  bool is_empty() {
+    bool empty = length() == 0;
+    assert(empty == (_table == NULL), "is empty only if table is deallocated");
+    return empty;
+  }
 
   // Length in elements
   size_t length() const { return _length; }
 
-  // Static data memory size in bytes of this set.
-  static size_t static_mem_size();
   // Memory size in bytes taken by this set.
   size_t mem_size();
 
-  static void test() PRODUCT_RETURN;
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -4670,6 +4670,56 @@
   }
 };
 
+class G1CodeBlobClosure : public CodeBlobClosure {
+  class HeapRegionGatheringOopClosure : public OopClosure {
+    G1CollectedHeap* _g1h;
+    OopClosure* _work;
+    nmethod* _nm;
+
+    template <typename T>
+    void do_oop_work(T* p) {
+      _work->do_oop(p);
+      T oop_or_narrowoop = oopDesc::load_heap_oop(p);
+      if (!oopDesc::is_null(oop_or_narrowoop)) {
+        oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
+        HeapRegion* hr = _g1h->heap_region_containing_raw(o);
+        assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
+        hr->add_strong_code_root(_nm);
+      }
+    }
+
+  public:
+    HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
+
+    void do_oop(oop* o) {
+      do_oop_work(o);
+    }
+
+    void do_oop(narrowOop* o) {
+      do_oop_work(o);
+    }
+
+    void set_nm(nmethod* nm) {
+      _nm = nm;
+    }
+  };
+
+  HeapRegionGatheringOopClosure _oc;
+public:
+  G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
+
+  void do_code_blob(CodeBlob* cb) {
+    nmethod* nm = cb->as_nmethod_or_null();
+    if (nm != NULL) {
+      if (!nm->test_set_oops_do_mark()) {
+        _oc.set_nm(nm);
+        nm->oops_do(&_oc);
+        nm->fix_oop_relocations();
+      }
+    }
+  }
+};
+
 class G1ParTask : public AbstractGangTask {
 protected:
   G1CollectedHeap*       _g1h;
@@ -4738,22 +4788,6 @@
     }
   };
 
-  class G1CodeBlobClosure: public CodeBlobClosure {
-    OopClosure* _f;
-
-   public:
-    G1CodeBlobClosure(OopClosure* f) : _f(f) {}
-    void do_code_blob(CodeBlob* blob) {
-      nmethod* that = blob->as_nmethod_or_null();
-      if (that != NULL) {
-        if (!that->test_set_oops_do_mark()) {
-          that->oops_do(_f);
-          that->fix_oop_relocations();
-        }
-      }
-    }
-  };
-
   void work(uint worker_id) {
     if (worker_id >= _n_workers) return;  // no work needed this round
 
@@ -4944,7 +4978,7 @@
   g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
 
   // Now scan the complement of the collection set.
-  MarkingCodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots, CodeBlobToOopClosure::FixRelocations);
+  G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
 
   g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
 
@@ -5991,12 +6025,6 @@
   hot_card_cache->reset_hot_cache();
   hot_card_cache->set_use_cache(true);
 
-  // Migrate the strong code roots attached to each region in
-  // the collection set. Ideally we would like to do this
-  // after we have finished the scanning/evacuation of the
-  // strong code roots for a particular heap region.
-  migrate_strong_code_roots();
-
   purge_code_root_memory();
 
   if (g1_policy()->during_initial_mark_pause()) {
@@ -7049,13 +7077,8 @@
                      " starting at "HR_FORMAT,
                      _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
 
-      // HeapRegion::add_strong_code_root() avoids adding duplicate
-      // entries but having duplicates is  OK since we "mark" nmethods
-      // as visited when we scan the strong code root lists during the GC.
-      hr->add_strong_code_root(_nm);
-      assert(hr->rem_set()->strong_code_roots_list_contains(_nm),
-             err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT,
-                     _nm, HR_FORMAT_PARAMS(hr)));
+      // HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries.
+      hr->add_strong_code_root_locked(_nm);
     }
   }
 
@@ -7082,9 +7105,6 @@
                      _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
 
       hr->remove_strong_code_root(_nm);
-      assert(!hr->rem_set()->strong_code_roots_list_contains(_nm),
-             err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT,
-                     _nm, HR_FORMAT_PARAMS(hr)));
     }
   }
 
@@ -7112,28 +7132,9 @@
   nm->oops_do(&reg_cl, true);
 }
 
-class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure {
-public:
-  bool doHeapRegion(HeapRegion *hr) {
-    assert(!hr->isHumongous(),
-           err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
-                   HR_FORMAT_PARAMS(hr)));
-    hr->migrate_strong_code_roots();
-    return false;
-  }
-};
-
-void G1CollectedHeap::migrate_strong_code_roots() {
-  MigrateCodeRootsHeapRegionClosure cl;
-  double migrate_start = os::elapsedTime();
-  collection_set_iterate(&cl);
-  double migration_time_ms = (os::elapsedTime() - migrate_start) * 1000.0;
-  g1_policy()->phase_times()->record_strong_code_root_migration_time(migration_time_ms);
-}
-
 void G1CollectedHeap::purge_code_root_memory() {
   double purge_start = os::elapsedTime();
-  G1CodeRootSet::purge_chunks(G1CodeRootsChunkCacheKeepPercent);
+  G1CodeRootSet::purge();
   double purge_time_ms = (os::elapsedTime() - purge_start) * 1000.0;
   g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms);
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1662,12 +1662,6 @@
   // Unregister the given nmethod from the G1 heap.
   virtual void unregister_nmethod(nmethod* nm);
 
-  // Migrate the nmethods in the code root lists of the regions
-  // in the collection set to regions in to-space. In the event
-  // of an evacuation failure, nmethods that reference objects
-  // that were not successfully evacuated are not migrated.
-  void migrate_strong_code_roots();
-
   // Free up superfluous code root memory.
   void purge_code_root_memory();
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -217,6 +217,8 @@
         _update_rset_cl->set_region(hr);
         hr->object_iterate(&rspc);
 
+        hr->rem_set()->clean_strong_code_roots(hr);
+
         hr->note_self_forwarding_removal_end(during_initial_mark,
                                              during_conc_mark,
                                              rspc.marked_bytes());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -275,9 +275,6 @@
     // Now subtract the time taken to fix up roots in generated code
     misc_time_ms += _cur_collection_code_root_fixup_time_ms;
 
-    // Strong code root migration time
-    misc_time_ms += _cur_strong_code_root_migration_time_ms;
-
     // Strong code root purge time
     misc_time_ms += _cur_strong_code_root_purge_time_ms;
 
@@ -328,7 +325,6 @@
     _last_obj_copy_times_ms.print(1, "Object Copy (ms)");
   }
   print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
-  print_stats(1, "Code Root Migration", _cur_strong_code_root_migration_time_ms);
   print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms);
   if (G1StringDedup::is_enabled()) {
     print_stats(1, "String Dedup Fixup", _cur_string_dedup_fixup_time_ms, _active_gc_threads);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -129,7 +129,6 @@
 
   double _cur_collection_par_time_ms;
   double _cur_collection_code_root_fixup_time_ms;
-  double _cur_strong_code_root_migration_time_ms;
   double _cur_strong_code_root_purge_time_ms;
 
   double _cur_evac_fail_recalc_used;
@@ -233,10 +232,6 @@
     _cur_collection_code_root_fixup_time_ms = ms;
   }
 
-  void record_strong_code_root_migration_time(double ms) {
-    _cur_strong_code_root_migration_time_ms = ms;
-  }
-
   void record_strong_code_root_purge_time(double ms) {
     _cur_strong_code_root_purge_time_ms = ms;
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -110,7 +110,7 @@
   G1CollectedHeap* _g1h;
 
   OopsInHeapRegionClosure* _oc;
-  CodeBlobToOopClosure* _code_root_cl;
+  CodeBlobClosure* _code_root_cl;
 
   G1BlockOffsetSharedArray* _bot_shared;
   G1SATBCardTableModRefBS *_ct_bs;
@@ -122,7 +122,7 @@
 
 public:
   ScanRSClosure(OopsInHeapRegionClosure* oc,
-                CodeBlobToOopClosure* code_root_cl,
+                CodeBlobClosure* code_root_cl,
                 uint worker_i) :
     _oc(oc),
     _code_root_cl(code_root_cl),
@@ -242,7 +242,7 @@
 };
 
 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
-                      CodeBlobToOopClosure* code_root_cl,
+                      CodeBlobClosure* code_root_cl,
                       uint worker_i) {
   double rs_time_start = os::elapsedTime();
   HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
@@ -321,7 +321,7 @@
 }
 
 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
-                                           CodeBlobToOopClosure* code_root_cl,
+                                           CodeBlobClosure* code_root_cl,
                                            uint worker_i) {
 #if CARD_REPEAT_HISTO
   ct_freq_update_histo_and_reset();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -96,7 +96,7 @@
   // the "i" passed to the calling thread's work(i) function.
   // In the sequential case this param will be ignored.
   void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
-                                   CodeBlobToOopClosure* code_root_cl,
+                                   CodeBlobClosure* code_root_cl,
                                    uint worker_i);
 
   // Prepare for and cleanup after an oops_into_collection_set_do
@@ -108,7 +108,7 @@
   void cleanup_after_oops_into_collection_set_do();
 
   void scanRS(OopsInHeapRegionClosure* oc,
-              CodeBlobToOopClosure* code_root_cl,
+              CodeBlobClosure* code_root_cl,
               uint worker_i);
 
   void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -253,6 +253,7 @@
     size_t occupied_cards = hrrs->occupied();
     size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
     if (code_root_mem_sz > max_code_root_mem_sz()) {
+      _max_code_root_mem_sz = code_root_mem_sz;
       _max_code_root_mem_sz_region = r;
     }
     size_t code_root_elems = hrrs->strong_code_roots_list_length();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -277,10 +277,6 @@
   product(uintx, G1MixedGCCountTarget, 8,                                   \
           "The target number of mixed GCs after a marking cycle.")          \
                                                                             \
-  experimental(uintx, G1CodeRootsChunkCacheKeepPercent, 10,                 \
-          "The amount of code root chunks that should be kept at most "     \
-          "as percentage of already allocated.")                            \
-                                                                            \
   experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true,          \
           "Try to reclaim dead large objects at every young GC.")           \
                                                                             \
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -540,21 +540,17 @@
   hrrs->add_strong_code_root(nm);
 }
 
+void HeapRegion::add_strong_code_root_locked(nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+  HeapRegionRemSet* hrrs = rem_set();
+  hrrs->add_strong_code_root_locked(nm);
+}
+
 void HeapRegion::remove_strong_code_root(nmethod* nm) {
   HeapRegionRemSet* hrrs = rem_set();
   hrrs->remove_strong_code_root(nm);
 }
 
-void HeapRegion::migrate_strong_code_roots() {
-  assert(in_collection_set(), "only collection set regions");
-  assert(!isHumongous(),
-          err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
-                  HR_FORMAT_PARAMS(this)));
-
-  HeapRegionRemSet* hrrs = rem_set();
-  hrrs->migrate_strong_code_roots();
-}
-
 void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const {
   HeapRegionRemSet* hrrs = rem_set();
   hrrs->strong_code_roots_do(blk);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -756,14 +756,9 @@
   // Routines for managing a list of code roots (attached to the
   // this region's RSet) that point into this heap region.
   void add_strong_code_root(nmethod* nm);
+  void add_strong_code_root_locked(nmethod* nm);
   void remove_strong_code_root(nmethod* nm);
 
-  // During a collection, migrate the successfully evacuated
-  // strong code roots that referenced into this region to the
-  // new regions that they now point into. Unsuccessfully
-  // evacuated code roots are not migrated.
-  void migrate_strong_code_roots();
-
   // Applies blk->do_code_blob() to each of the entries in
   // the strong code roots list for this region
   void strong_code_roots_do(CodeBlobClosure* blk) const;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -448,10 +448,10 @@
 
   // Note that this may be a continued H region.
   HeapRegion* from_hr = _g1h->heap_region_containing_raw(from);
-  RegionIdx_t from_hrs_ind = (RegionIdx_t) from_hr->hrm_index();
+  RegionIdx_t from_hrm_ind = (RegionIdx_t) from_hr->hrm_index();
 
   // If the region is already coarsened, return.
-  if (_coarse_map.at(from_hrs_ind)) {
+  if (_coarse_map.at(from_hrm_ind)) {
     if (G1TraceHeapRegionRememberedSet) {
       gclog_or_tty->print_cr("  coarse map hit.");
     }
@@ -460,7 +460,7 @@
   }
 
   // Otherwise find a per-region table to add it to.
-  size_t ind = from_hrs_ind & _mod_max_fine_entries_mask;
+  size_t ind = from_hrm_ind & _mod_max_fine_entries_mask;
   PerRegionTable* prt = find_region_table(ind, from_hr);
   if (prt == NULL) {
     MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
@@ -475,7 +475,7 @@
       assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion,
              "Must be in range.");
       if (G1HRRSUseSparseTable &&
-          _sparse_table.add_card(from_hrs_ind, card_index)) {
+          _sparse_table.add_card(from_hrm_ind, card_index)) {
         if (G1RecordHRRSOops) {
           HeapRegionRemSet::record(hr(), from);
           if (G1TraceHeapRegionRememberedSet) {
@@ -495,7 +495,7 @@
         if (G1TraceHeapRegionRememberedSet) {
           gclog_or_tty->print_cr("   [tid %d] sparse table entry "
                         "overflow(f: %d, t: %u)",
-                        tid, from_hrs_ind, cur_hrm_ind);
+                        tid, from_hrm_ind, cur_hrm_ind);
         }
       }
 
@@ -516,7 +516,7 @@
 
       if (G1HRRSUseSparseTable) {
         // Transfer from sparse to fine-grain.
-        SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind);
+        SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrm_ind);
         assert(sprt_entry != NULL, "There should have been an entry");
         for (int i = 0; i < SparsePRTEntry::cards_num(); i++) {
           CardIdx_t c = sprt_entry->card(i);
@@ -525,7 +525,7 @@
           }
         }
         // Now we can delete the sparse entry.
-        bool res = _sparse_table.delete_entry(from_hrs_ind);
+        bool res = _sparse_table.delete_entry(from_hrm_ind);
         assert(res, "It should have been there.");
       }
     }
@@ -926,9 +926,25 @@
 }
 
 // Code roots support
+//
+// The code root set is protected by two separate locking schemes
+// When at safepoint the per-hrrs lock must be held during modifications
+// except when doing a full gc.
+// When not at safepoint the CodeCache_lock must be held during modifications.
+// When concurrent readers access the contains() function
+// (during the evacuation phase) no removals are allowed.
 
 void HeapRegionRemSet::add_strong_code_root(nmethod* nm) {
   assert(nm != NULL, "sanity");
+  // Optimistic unlocked contains-check
+  if (!_code_roots.contains(nm)) {
+    MutexLockerEx ml(&_m, Mutex::_no_safepoint_check_flag);
+    add_strong_code_root_locked(nm);
+  }
+}
+
+void HeapRegionRemSet::add_strong_code_root_locked(nmethod* nm) {
+  assert(nm != NULL, "sanity");
   _code_roots.add(nm);
 }
 
@@ -936,96 +952,19 @@
   assert(nm != NULL, "sanity");
   assert_locked_or_safepoint(CodeCache_lock);
 
-  _code_roots.remove_lock_free(nm);
+  MutexLockerEx ml(CodeCache_lock->owned_by_self() ? NULL : &_m, Mutex::_no_safepoint_check_flag);
+  _code_roots.remove(nm);
 
   // Check that there were no duplicates
   guarantee(!_code_roots.contains(nm), "duplicate entry found");
 }
 
-class NMethodMigrationOopClosure : public OopClosure {
-  G1CollectedHeap* _g1h;
-  HeapRegion* _from;
-  nmethod* _nm;
-
-  uint _num_self_forwarded;
-
-  template <class T> void do_oop_work(T* p) {
-    T heap_oop = oopDesc::load_heap_oop(p);
-    if (!oopDesc::is_null(heap_oop)) {
-      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-      if (_from->is_in(obj)) {
-        // Reference still points into the source region.
-        // Since roots are immediately evacuated this means that
-        // we must have self forwarded the object
-        assert(obj->is_forwarded(),
-               err_msg("code roots should be immediately evacuated. "
-                       "Ref: "PTR_FORMAT", "
-                       "Obj: "PTR_FORMAT", "
-                       "Region: "HR_FORMAT,
-                       p, (void*) obj, HR_FORMAT_PARAMS(_from)));
-        assert(obj->forwardee() == obj,
-               err_msg("not self forwarded? obj = "PTR_FORMAT, (void*)obj));
-
-        // The object has been self forwarded.
-        // Note, if we're during an initial mark pause, there is
-        // no need to explicitly mark object. It will be marked
-        // during the regular evacuation failure handling code.
-        _num_self_forwarded++;
-      } else {
-        // The reference points into a promotion or to-space region
-        HeapRegion* to = _g1h->heap_region_containing(obj);
-        to->rem_set()->add_strong_code_root(_nm);
-      }
-    }
-  }
-
-public:
-  NMethodMigrationOopClosure(G1CollectedHeap* g1h, HeapRegion* from, nmethod* nm):
-    _g1h(g1h), _from(from), _nm(nm), _num_self_forwarded(0) {}
-
-  void do_oop(narrowOop* p) { do_oop_work(p); }
-  void do_oop(oop* p)       { do_oop_work(p); }
-
-  uint retain() { return _num_self_forwarded > 0; }
-};
-
-void HeapRegionRemSet::migrate_strong_code_roots() {
-  assert(hr()->in_collection_set(), "only collection set regions");
-  assert(!hr()->isHumongous(),
-         err_msg("humongous region "HR_FORMAT" should not have been added to the collection set",
-                 HR_FORMAT_PARAMS(hr())));
-
-  ResourceMark rm;
-
-  // List of code blobs to retain for this region
-  GrowableArray<nmethod*> to_be_retained(10);
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-  while (!_code_roots.is_empty()) {
-    nmethod *nm = _code_roots.pop();
-    if (nm != NULL) {
-      NMethodMigrationOopClosure oop_cl(g1h, hr(), nm);
-      nm->oops_do(&oop_cl);
-      if (oop_cl.retain()) {
-        to_be_retained.push(nm);
-      }
-    }
-  }
-
-  // Now push any code roots we need to retain
-  assert(to_be_retained.is_empty() || hr()->evacuation_failed(),
-         "Retained nmethod list must be empty or "
-         "evacuation of this region failed");
-
-  while (to_be_retained.is_nonempty()) {
-    nmethod* nm = to_be_retained.pop();
-    assert(nm != NULL, "sanity");
-    add_strong_code_root(nm);
-  }
+void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
+  _code_roots.nmethods_do(blk);
 }
 
-void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
-  _code_roots.nmethods_do(blk);
+void HeapRegionRemSet::clean_strong_code_roots(HeapRegion* hr) {
+  _code_roots.clean(hr);
 }
 
 size_t HeapRegionRemSet::strong_code_roots_mem_size() {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -349,13 +349,13 @@
   // Returns the memory occupancy of all static data structures associated
   // with remembered sets.
   static size_t static_mem_size() {
-    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::free_chunks_static_mem_size();
+    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
   }
 
   // Returns the memory occupancy of all free_list data structures associated
   // with remembered sets.
   static size_t fl_mem_size() {
-    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::free_chunks_mem_size();
+    return OtherRegionsTable::fl_mem_size();
   }
 
   bool contains_reference(OopOrNarrowOopStar from) const {
@@ -365,18 +365,15 @@
   // Routines for managing the list of code roots that point into
   // the heap region that owns this RSet.
   void add_strong_code_root(nmethod* nm);
+  void add_strong_code_root_locked(nmethod* nm);
   void remove_strong_code_root(nmethod* nm);
 
-  // During a collection, migrate the successfully evacuated strong
-  // code roots that referenced into the region that owns this RSet
-  // to the RSets of the new regions that they now point into.
-  // Unsuccessfully evacuated code roots are not migrated.
-  void migrate_strong_code_roots();
-
   // Applies blk->do_code_blob() to each of the entries in
   // the strong code roots list
   void strong_code_roots_do(CodeBlobClosure* blk) const;
 
+  void clean_strong_code_roots(HeapRegion* hr);
+
   // Returns the number of elements in the strong code roots list
   size_t strong_code_roots_list_length() const {
     return _code_roots.length();
--- a/hotspot/src/share/vm/interpreter/interpreter.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreter.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -55,7 +55,9 @@
  public:
   // Initialization/finalization
   void    initialize(int size,
-                     CodeStrings& strings)       { _size = size; DEBUG_ONLY(_strings.assign(strings);) }
+                     CodeStrings& strings)       { _size = size;
+                                                   DEBUG_ONLY(::new(&_strings) CodeStrings();)
+                                                   DEBUG_ONLY(_strings.assign(strings);) }
   void    finalize()                             { ShouldNotCallThis(); }
 
   // General info/converters
--- a/hotspot/src/share/vm/memory/freeList.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/memory/freeList.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -34,7 +34,6 @@
 
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
 #endif // INCLUDE_ALL_GCS
 
 // Free list.  A FreeList is used to access a linked list of chunks
@@ -333,5 +332,4 @@
 template class FreeList<Metachunk>;
 #if INCLUDE_ALL_GCS
 template class FreeList<FreeChunk>;
-template class FreeList<G1CodeRootChunk>;
 #endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -41,7 +41,7 @@
 
 #define SET_ESTIMATED_SIZE(type, region)                              \
   Shared ##region## Size  = FLAG_IS_DEFAULT(Shared ##region## Size) ? \
-    (type ## SharedArchiveSize *  region ## RegionPercentage) : Shared ## region ## Size
+    (uintx)(type ## SharedArchiveSize *  region ## RegionPercentage) : Shared ## region ## Size
 
 class FileMapInfo;
 
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -78,7 +78,6 @@
   set_dimension(1);
   set_higher_dimension(NULL);
   set_lower_dimension(NULL);
-  set_component_mirror(NULL);
   // Arrays don't add any new methods, so their vtable is the same size as
   // the vtable of klass Object.
   int vtable_size = Universe::base_vtable_size();
@@ -160,14 +159,6 @@
   }
 }
 
-// GC support
-
-void ArrayKlass::oops_do(OopClosure* cl) {
-  Klass::oops_do(cl);
-
-  cl->do_oop(adr_component_mirror());
-}
-
 // JVM support
 
 jint ArrayKlass::compute_modifier_flags(TRAPS) const {
@@ -182,8 +173,6 @@
 
 void ArrayKlass::remove_unshareable_info() {
   Klass::remove_unshareable_info();
-  // Clear the java mirror
-  set_component_mirror(NULL);
 }
 
 void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
@@ -217,10 +206,6 @@
 
 void ArrayKlass::verify_on(outputStream* st) {
   Klass::verify_on(st);
-
-  if (component_mirror() != NULL) {
-    guarantee(component_mirror()->klass() != NULL, "should have a class");
-  }
 }
 
 void ArrayKlass::oop_verify_on(oop obj, outputStream* st) {
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -39,7 +39,6 @@
   Klass* volatile _higher_dimension;  // Refers the (n+1)'th-dimensional array (if present).
   Klass* volatile _lower_dimension;   // Refers the (n-1)'th-dimensional array (if present).
   int      _vtable_len;        // size of vtable for this klass
-  oop      _component_mirror;  // component type, as a java/lang/Class
 
  protected:
   // Constructors
@@ -70,13 +69,6 @@
   // type of elements (T_OBJECT for both oop arrays and array-arrays)
   BasicType element_type() const        { return layout_helper_element_type(layout_helper()); }
 
-  oop  component_mirror() const         { return _component_mirror; }
-  void set_component_mirror(oop m)      { klass_oop_store(&_component_mirror, m); }
-  oop* adr_component_mirror()           { return (oop*)&this->_component_mirror;}
-
-  // Compiler/Interpreter offset
-  static ByteSize component_mirror_offset() { return in_ByteSize(offset_of(ArrayKlass, _component_mirror)); }
-
   virtual Klass* java_super() const;//{ return SystemDictionary::Object_klass(); }
 
   // Allocation
@@ -122,9 +114,6 @@
   void array_klasses_do(void f(Klass* k));
   void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
 
-  // GC support
-  virtual void oops_do(OopClosure* cl);
-
   // Return a handle.
   static void     complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS);
 
--- a/hotspot/src/share/vm/oops/klass.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -565,7 +565,7 @@
   TRACE_DEFINE_KLASS_METHODS;
 
   // garbage collection support
-  virtual void oops_do(OopClosure* cl);
+  void oops_do(OopClosure* cl);
 
   // Iff the class loader (or mirror for anonymous classes) is alive the
   // Klass is considered alive.
--- a/hotspot/src/share/vm/oops/methodData.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -86,7 +86,7 @@
 
 char* ProfileData::print_data_on_helper(const MethodData* md) const {
   DataLayout* dp  = md->extra_data_base();
-  DataLayout* end = md->extra_data_limit();
+  DataLayout* end = md->args_data_limit();
   stringStream ss;
   for (;; dp = MethodData::next_extra(dp)) {
     assert(dp < end, "moved past end of extra data");
@@ -1048,14 +1048,15 @@
     stream->next();
     data->post_initialize(stream, this);
   }
-  if (_parameters_type_data_di != -1) {
+  if (_parameters_type_data_di != no_parameters) {
     parameters_type_data()->post_initialize(NULL, this);
   }
 }
 
 // Initialize the MethodData* corresponding to a given method.
 MethodData::MethodData(methodHandle method, int size, TRAPS)
-  : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {
+  : _extra_data_lock(Monitor::leaf, "MDO extra data lock"),
+    _parameters_type_data_di(parameters_uninitialized) {
   No_Safepoint_Verifier no_safepoint;  // init function atomic wrt GC
   ResourceMark rm;
   // Set the method back-pointer.
@@ -1111,7 +1112,7 @@
     DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
     dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell);
   } else {
-    _parameters_type_data_di = -1;
+    _parameters_type_data_di = no_parameters;
   }
 
   // Set an initial hint. Don't use set_hint_di() because
@@ -1236,7 +1237,7 @@
 }
 
 ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp, bool concurrent) {
-  DataLayout* end = extra_data_limit();
+  DataLayout* end = args_data_limit();
 
   for (;; dp = next_extra(dp)) {
     assert(dp < end, "moved past end of extra data");
@@ -1285,7 +1286,7 @@
          "code needs to be adjusted");
 
   DataLayout* dp  = extra_data_base();
-  DataLayout* end = extra_data_limit();
+  DataLayout* end = args_data_limit();
 
   // Allocation in the extra data space has to be atomic because not
   // all entries have the same size and non atomic concurrent
@@ -1330,7 +1331,7 @@
 
 ArgInfoData *MethodData::arg_info() {
   DataLayout* dp    = extra_data_base();
-  DataLayout* end   = extra_data_limit();
+  DataLayout* end   = args_data_limit();
   for (; dp < end; dp = next_extra(dp)) {
     if (dp->tag() == DataLayout::arg_info_data_tag)
       return new ArgInfoData(dp);
@@ -1357,7 +1358,7 @@
 void MethodData::print_data_on(outputStream* st) const {
   ResourceMark rm;
   ProfileData* data = first_data();
-  if (_parameters_type_data_di != -1) {
+  if (_parameters_type_data_di != no_parameters) {
     parameters_type_data()->print_data_on(st);
   }
   for ( ; is_valid(data); data = next_data(data)) {
@@ -1367,7 +1368,7 @@
   }
   st->print_cr("--- Extra data:");
   DataLayout* dp    = extra_data_base();
-  DataLayout* end   = extra_data_limit();
+  DataLayout* end   = args_data_limit();
   for (;; dp = next_extra(dp)) {
     assert(dp < end, "moved past end of extra data");
     // No need for "OrderAccess::load_acquire" ops,
@@ -1565,7 +1566,7 @@
 // redefined method
 void MethodData::clean_extra_data(CleanExtraDataClosure* cl) {
   DataLayout* dp  = extra_data_base();
-  DataLayout* end = extra_data_limit();
+  DataLayout* end = args_data_limit();
 
   int shift = 0;
   for (; dp < end; dp = next_extra(dp)) {
@@ -1610,7 +1611,7 @@
 void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
 #ifdef ASSERT
   DataLayout* dp  = extra_data_base();
-  DataLayout* end = extra_data_limit();
+  DataLayout* end = args_data_limit();
 
   for (; dp < end; dp = next_extra(dp)) {
     switch(dp->tag()) {
--- a/hotspot/src/share/vm/oops/methodData.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -2107,7 +2107,12 @@
 
   // data index for the area dedicated to parameters. -1 if no
   // parameter profiling.
+  enum { no_parameters = -2, parameters_uninitialized = -1 };
   int _parameters_type_data_di;
+  int parameters_size_in_bytes() const {
+    ParametersTypeData* param = parameters_type_data();
+    return param == NULL ? 0 : param->size_in_bytes();
+  }
 
   // Beginning of the data entries
   intptr_t _data[1];
@@ -2130,7 +2135,7 @@
 
   // Helper for data_at
   DataLayout* limit_data_position() const {
-    return (DataLayout*)((address)data_base() + _data_size);
+    return data_layout_at(_data_size);
   }
   bool out_of_bounds(int data_index) const {
     return data_index >= data_size();
@@ -2371,10 +2376,11 @@
   }
 
   // Add a handful of extra data records, for trap tracking.
-  DataLayout* extra_data_base() const { return limit_data_position(); }
+  DataLayout* extra_data_base() const  { return limit_data_position(); }
   DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); }
-  int extra_data_size() const { return (address)extra_data_limit()
-                               - (address)extra_data_base(); }
+  DataLayout* args_data_limit() const  { return (DataLayout*)((address)this + size_in_bytes() -
+                                                              parameters_size_in_bytes()); }
+  int extra_data_size() const          { return (address)extra_data_limit() - (address)extra_data_base(); }
   static DataLayout* next_extra(DataLayout* dp);
 
   // Return (uint)-1 for overflow.
@@ -2429,11 +2435,12 @@
 
   // Return pointer to area dedicated to parameters in MDO
   ParametersTypeData* parameters_type_data() const {
-    return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
+    assert(_parameters_type_data_di != parameters_uninitialized, "called too early");
+    return _parameters_type_data_di != no_parameters ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
   }
 
   int parameters_type_data_di() const {
-    assert(_parameters_type_data_di != -1, "no args type data");
+    assert(_parameters_type_data_di != parameters_uninitialized && _parameters_type_data_di != no_parameters, "no args type data");
     return _parameters_type_data_di;
   }
 
@@ -2480,8 +2487,8 @@
   static bool profile_return_jsr292_only();
 
   void clean_method_data(BoolObjectClosure* is_alive);
-
   void clean_weak_method_links();
+  Mutex* extra_data_lock() { return &_extra_data_lock; }
 };
 
 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -650,6 +650,9 @@
   product(bool, UseMathExactIntrinsics, true,                               \
           "Enables intrinsification of various java.lang.Math functions")   \
                                                                             \
+  product(bool, UseMultiplyToLenIntrinsic, false,                           \
+          "Enables intrinsification of BigInteger.multiplyToLen()")         \
+                                                                            \
   product(bool, UseTypeSpeculation, true,                                   \
           "Speculatively propagate types from profiles")                    \
                                                                             \
--- a/hotspot/src/share/vm/opto/callnode.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1830,8 +1830,8 @@
                                    Node* dest, Node* dest_offset,
                                    Node* length,
                                    bool alloc_tightly_coupled,
-                                   Node* src_length, Node* dest_length,
-                                   Node* src_klass, Node* dest_klass) {
+                                   Node* src_klass, Node* dest_klass,
+                                   Node* src_length, Node* dest_length) {
 
   ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled);
   Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac);
--- a/hotspot/src/share/vm/opto/callnode.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/callnode.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1138,8 +1138,8 @@
                              Node* dest,  Node* dest_offset,
                              Node* length,
                              bool alloc_tightly_coupled,
-                             Node* src_length = NULL, Node* dest_length = NULL,
-                             Node* src_klass = NULL, Node* dest_klass = NULL);
+                             Node* src_klass = NULL, Node* dest_klass = NULL,
+                             Node* src_length = NULL, Node* dest_length = NULL);
 
   void connect_outputs(GraphKit* kit);
 
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -601,6 +601,10 @@
   bool          method_has_option(const char * option) {
     return method() != NULL && method()->has_option(option);
   }
+  template<typename T>
+  bool          method_has_option_value(const char * option, T& value) {
+    return method() != NULL && method()->has_option_value(option, value);
+  }
 #ifndef PRODUCT
   bool          trace_opto_output() const       { return _trace_opto_output; }
   bool              parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
--- a/hotspot/src/share/vm/opto/escape.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -945,7 +945,8 @@
                   strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
-                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0)
+                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0)
                   ))) {
             call->dump();
             fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -285,6 +285,7 @@
   bool inline_updateCRC32();
   bool inline_updateBytesCRC32();
   bool inline_updateByteBufferCRC32();
+  bool inline_multiplyToLen();
 };
 
 
@@ -293,8 +294,12 @@
   vmIntrinsics::ID id = m->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
-  if (DisableIntrinsic[0] != '\0'
-      && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) {
+  ccstr disable_intr = NULL;
+
+  if ((DisableIntrinsic[0] != '\0'
+       && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
+      (method_has_option_value("DisableIntrinsic", disable_intr)
+       && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) {
     // disabled by a user request on the command line:
     // example: -XX:DisableIntrinsic=_hashCode,_getClass
     return NULL;
@@ -477,6 +482,10 @@
     if (!UseAESIntrinsics) return NULL;
     break;
 
+  case vmIntrinsics::_multiplyToLen:
+    if (!UseMultiplyToLenIntrinsic) return NULL;
+    break;
+
   case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
   case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
     if (!UseAESIntrinsics) return NULL;
@@ -836,7 +845,6 @@
   case vmIntrinsics::_isArray:
   case vmIntrinsics::_isPrimitive:
   case vmIntrinsics::_getSuperclass:
-  case vmIntrinsics::_getComponentType:
   case vmIntrinsics::_getClassAccessFlags:      return inline_native_Class_query(intrinsic_id());
 
   case vmIntrinsics::_floatToRawIntBits:
@@ -876,6 +884,9 @@
   case vmIntrinsics::_digestBase_implCompressMB:
     return inline_digestBase_implCompressMB(predicate);
 
+  case vmIntrinsics::_multiplyToLen:
+    return inline_multiplyToLen();
+
   case vmIntrinsics::_encodeISOArray:
     return inline_encodeISOArray();
 
@@ -3400,10 +3411,6 @@
     prim_return_value = null();
     return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR);
     break;
-  case vmIntrinsics::_getComponentType:
-    prim_return_value = null();
-    return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR);
-    break;
   case vmIntrinsics::_getClassAccessFlags:
     prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
     return_type = TypeInt::INT;  // not bool!  6297094
@@ -3520,17 +3527,6 @@
     }
     break;
 
-  case vmIntrinsics::_getComponentType:
-    if (generate_array_guard(kls, region) != NULL) {
-      // Be sure to pin the oop load to the guard edge just created:
-      Node* is_array_ctrl = region->in(region->req()-1);
-      Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset()));
-      Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered);
-      phi->add_req(cmo);
-    }
-    query_value = null();  // non-array case is null
-    break;
-
   case vmIntrinsics::_getClassAccessFlags:
     p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset()));
     query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered);
@@ -3859,7 +3855,7 @@
       Node* orig_tail = _gvn.transform(new SubINode(orig_length, start));
       Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
 
-      newcopy = new_array(klass_node, length, 0);  // no argments to push
+      newcopy = new_array(klass_node, length, 0);  // no arguments to push
 
       // Generate a direct call to the right arraycopy function(s).
       // We know the copy is disjoint but we might not know if the
@@ -3869,7 +3865,8 @@
 
       Node* alloc = tightly_coupled_allocation(newcopy, NULL);
 
-      ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL);
+      ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL,
+                                              load_object_klass(original), klass_node);
       if (!is_copyOfRange) {
         ac->set_copyof();
       } else {
@@ -4792,8 +4789,8 @@
                                           // Create LoadRange and LoadKlass nodes for use during macro expansion here
                                           // so the compiler has a chance to eliminate them: during macro expansion,
                                           // we have to set their control (CastPP nodes are eliminated).
-                                          load_array_length(src), load_array_length(dest),
-                                          load_object_klass(src), load_object_klass(dest));
+                                          load_object_klass(src), load_object_klass(dest),
+                                          load_array_length(src), load_array_length(dest));
 
   if (notest) {
     ac->set_arraycopy_notest();
@@ -4924,6 +4921,106 @@
   return true;
 }
 
+//-------------inline_multiplyToLen-----------------------------------
+bool LibraryCallKit::inline_multiplyToLen() {
+  assert(UseMultiplyToLenIntrinsic, "not implementated on this platform");
+
+  address stubAddr = StubRoutines::multiplyToLen();
+  if (stubAddr == NULL) {
+    return false; // Intrinsic's stub is not implemented on this platform
+  }
+  const char* stubName = "multiplyToLen";
+
+  assert(callee()->signature()->size() == 5, "multiplyToLen has 5 parameters");
+
+  Node* x    = argument(1);
+  Node* xlen = argument(2);
+  Node* y    = argument(3);
+  Node* ylen = argument(4);
+  Node* z    = argument(5);
+
+  const Type* x_type = x->Value(&_gvn);
+  const Type* y_type = y->Value(&_gvn);
+  const TypeAryPtr* top_x = x_type->isa_aryptr();
+  const TypeAryPtr* top_y = y_type->isa_aryptr();
+  if (top_x  == NULL || top_x->klass()  == NULL ||
+      top_y == NULL || top_y->klass() == NULL) {
+    // failed array check
+    return false;
+  }
+
+  BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType y_elem = y_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (x_elem != T_INT || y_elem != T_INT) {
+    return false;
+  }
+
+  // Set the original stack and the reexecute bit for the interpreter to reexecute
+  // the bytecode that invokes BigInteger.multiplyToLen() if deoptimization happens
+  // on the return from z array allocation in runtime.
+  { PreserveReexecuteState preexecs(this);
+    jvms()->set_should_reexecute(true);
+
+    Node* x_start = array_element_address(x, intcon(0), x_elem);
+    Node* y_start = array_element_address(y, intcon(0), y_elem);
+    // 'x_start' points to x array + scaled xlen
+    // 'y_start' points to y array + scaled ylen
+
+    // Allocate the result array
+    Node* zlen = _gvn.transform(new AddINode(xlen, ylen));
+    Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+
+    IdealKit ideal(this);
+
+#define __ ideal.
+     Node* one = __ ConI(1);
+     Node* zero = __ ConI(0);
+     IdealVariable need_alloc(ideal), z_alloc(ideal);  __ declarations_done();
+     __ set(need_alloc, zero);
+     __ set(z_alloc, z);
+     __ if_then(z, BoolTest::eq, null()); {
+       __ increment (need_alloc, one);
+     } __ else_(); {
+       // Update graphKit memory and control from IdealKit.
+       sync_kit(ideal);
+       Node* zlen_arg = load_array_length(z);
+       // Update IdealKit memory and control from graphKit.
+       __ sync_kit(this);
+       __ if_then(zlen_arg, BoolTest::lt, zlen); {
+         __ increment (need_alloc, one);
+       } __ end_if();
+     } __ end_if();
+
+     __ if_then(__ value(need_alloc), BoolTest::ne, zero); {
+       // Update graphKit memory and control from IdealKit.
+       sync_kit(ideal);
+       Node * narr = new_array(klass_node, zlen, 1);
+       // Update IdealKit memory and control from graphKit.
+       __ sync_kit(this);
+       __ set(z_alloc, narr);
+     } __ end_if();
+
+     sync_kit(ideal);
+     z = __ value(z_alloc);
+     _gvn.set_type(z, TypeAryPtr::INTS);
+     // Final sync IdealKit and GraphKit.
+     final_sync(ideal);
+#undef __
+
+    Node* z_start = array_element_address(z, intcon(0), T_INT);
+
+    Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                                   OptoRuntime::multiplyToLen_Type(),
+                                   stubAddr, stubName, TypePtr::BOTTOM,
+                                   x_start, xlen, y_start, ylen, z_start, zlen);
+  } // original reexecute is set back here
+
+  C->set_has_split_ifs(true); // Has chance for split-if optimization
+  set_result(z);
+  return true;
+}
+
+
 /**
  * Calculate CRC32 for byte.
  * int java.util.zip.CRC32.update(int crc, int b)
--- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -506,6 +506,8 @@
     Node* src_klass  = ac->in(ArrayCopyNode::SrcKlass);
     Node* dest_klass = ac->in(ArrayCopyNode::DestKlass);
 
+    assert(src_klass != NULL && dest_klass != NULL, "should have klasses");
+
     // Generate the subtype check.
     // This might fold up statically, or then again it might not.
     //
@@ -1209,6 +1211,7 @@
 
     // (7) src_offset + length must not exceed length of src.
     Node* alen = ac->in(ArrayCopyNode::SrcLen);
+    assert(alen != NULL, "need src len");
     generate_limit_guard(&ctrl,
                          src_offset, length,
                          alen,
@@ -1216,6 +1219,7 @@
 
     // (8) dest_offset + length must not exceed length of dest.
     alen = ac->in(ArrayCopyNode::DestLen);
+    assert(alen != NULL, "need dest len");
     generate_limit_guard(&ctrl,
                          dest_offset, length,
                          alen,
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1799,13 +1799,6 @@
       }
       const Type* aift = load_array_final_field(tkls, klass);
       if (aift != NULL)  return aift;
-      if (tkls->offset() == in_bytes(ArrayKlass::component_mirror_offset())
-          && klass->is_array_klass()) {
-        // The field is ArrayKlass::_component_mirror.  Return its (constant) value.
-        // (Folds up aClassConstant.getComponentType, common in Arrays.copyOf.)
-        assert(Opcode() == Op_LoadP, "must load an oop from _component_mirror");
-        return TypeInstPtr::make(klass->as_array_klass()->component_mirror());
-      }
       if (tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
         // The field is Klass::_java_mirror.  Return its (constant) value.
         // (Folds up the 2nd indirection in anObjConstant.getClass().)
@@ -2200,18 +2193,15 @@
   }
 
   // Simplify k.java_mirror.as_klass to plain k, where k is a Klass*.
-  // Simplify ak.component_mirror.array_klass to plain ak, ak an ArrayKlass.
   // See inline_native_Class_query for occurrences of these patterns.
   // Java Example:  x.getClass().isAssignableFrom(y)
-  // Java Example:  Array.newInstance(x.getClass().getComponentType(), n)
   //
   // This improves reflective code, often making the Class
   // mirror go completely dead.  (Current exception:  Class
   // mirrors may appear in debug info, but we could clean them out by
   // introducing a new debug info operator for Klass*.java_mirror).
   if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass()
-      && (offset == java_lang_Class::klass_offset_in_bytes() ||
-          offset == java_lang_Class::array_klass_offset_in_bytes())) {
+      && offset == java_lang_Class::klass_offset_in_bytes()) {
     // We are loading a special hidden field from a Class mirror,
     // the field which points to its Klass or ArrayKlass metaobject.
     if (base->is_Load()) {
@@ -2223,9 +2213,6 @@
           && adr2->is_AddP()
           ) {
         int mirror_field = in_bytes(Klass::java_mirror_offset());
-        if (offset == java_lang_Class::array_klass_offset_in_bytes()) {
-          mirror_field = in_bytes(ArrayKlass::component_mirror_offset());
-        }
         if (tkls->offset() == mirror_field) {
           return adr2->in(AddPNode::Base);
         }
@@ -2799,9 +2786,10 @@
   assert(n->is_ClearArray(), "sanity");
   intptr_t offset;
   AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset);
-  // This method is called only before Allocate nodes are expanded during
-  // macro nodes expansion. Before that ClearArray nodes are only generated
-  // in LibraryCallKit::generate_arraycopy() which follows allocations.
+  // This method is called only before Allocate nodes are expanded
+  // during macro nodes expansion. Before that ClearArray nodes are
+  // only generated in PhaseMacroExpand::generate_arraycopy() (before
+  // Allocate nodes are expanded) which follows allocations.
   assert(alloc != NULL, "should have allocation");
   if (alloc->_idx == instance_id) {
     // Can not bypass initialization of the instance we are looking for.
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -42,10 +42,14 @@
   _max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
   _a(Thread::current()->resource_area()),
   _table( NEW_ARENA_ARRAY( _a , Node* , _max ) ), // (Node**)_a->Amalloc(_max * sizeof(Node*)) ),
-  _inserts(0), _insert_limit( insert_limit() ),
-  _look_probes(0), _lookup_hits(0), _lookup_misses(0),
+  _inserts(0), _insert_limit( insert_limit() )
+#ifndef PRODUCT
+  ,_look_probes(0), _lookup_hits(0), _lookup_misses(0),
+  _delete_probes(0), _delete_hits(0), _delete_misses(0),
   _total_insert_probes(0), _total_inserts(0),
-  _insert_probes(0), _grows(0) {
+  _insert_probes(0), _grows(0)
+#endif
+{
   // _sentinel must be in the current node space
   _sentinel = new ProjNode(NULL, TypeFunc::Control);
   memset(_table,0,sizeof(Node*)*_max);
@@ -56,11 +60,14 @@
   _max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
   _a(arena),
   _table( NEW_ARENA_ARRAY( _a , Node* , _max ) ),
-  _inserts(0), _insert_limit( insert_limit() ),
-  _look_probes(0), _lookup_hits(0), _lookup_misses(0),
+  _inserts(0), _insert_limit( insert_limit() )
+#ifndef PRODUCT
+  ,_look_probes(0), _lookup_hits(0), _lookup_misses(0),
   _delete_probes(0), _delete_hits(0), _delete_misses(0),
   _total_insert_probes(0), _total_inserts(0),
-  _insert_probes(0), _grows(0) {
+  _insert_probes(0), _grows(0)
+#endif
+{
   // _sentinel must be in the current node space
   _sentinel = new ProjNode(NULL, TypeFunc::Control);
   memset(_table,0,sizeof(Node*)*_max);
@@ -87,15 +94,15 @@
   // ((Node*)n)->set_hash( n->hash() );
   uint hash = n->hash();
   if (hash == Node::NO_HASH) {
-    debug_only( _lookup_misses++ );
+    NOT_PRODUCT( _lookup_misses++ );
     return NULL;
   }
   uint key = hash & (_max-1);
   uint stride = key | 0x01;
-  debug_only( _look_probes++ );
+  NOT_PRODUCT( _look_probes++ );
   Node *k = _table[key];        // Get hashed value
   if( !k ) {                    // ?Miss?
-    debug_only( _lookup_misses++ );
+    NOT_PRODUCT( _lookup_misses++ );
     return NULL;                // Miss!
   }
 
@@ -108,16 +115,16 @@
         if( n->in(i)!=k->in(i)) // Different inputs?
           goto collision;       // "goto" is a speed hack...
       if( n->cmp(*k) ) {        // Check for any special bits
-        debug_only( _lookup_hits++ );
+        NOT_PRODUCT( _lookup_hits++ );
         return k;               // Hit!
       }
     }
   collision:
-    debug_only( _look_probes++ );
+    NOT_PRODUCT( _look_probes++ );
     key = (key + stride/*7*/) & (_max-1); // Stride through table with relative prime
     k = _table[key];            // Get hashed value
     if( !k ) {                  // ?Miss?
-      debug_only( _lookup_misses++ );
+      NOT_PRODUCT( _lookup_misses++ );
       return NULL;              // Miss!
     }
   }
@@ -132,16 +139,16 @@
   // n->set_hash( );
   uint hash = n->hash();
   if (hash == Node::NO_HASH) {
-    debug_only( _lookup_misses++ );
+    NOT_PRODUCT( _lookup_misses++ );
     return NULL;
   }
   uint key = hash & (_max-1);
   uint stride = key | 0x01;     // stride must be relatively prime to table siz
   uint first_sentinel = 0;      // replace a sentinel if seen.
-  debug_only( _look_probes++ );
+  NOT_PRODUCT( _look_probes++ );
   Node *k = _table[key];        // Get hashed value
   if( !k ) {                    // ?Miss?
-    debug_only( _lookup_misses++ );
+    NOT_PRODUCT( _lookup_misses++ );
     _table[key] = n;            // Insert into table!
     debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
     check_grow();               // Grow table if insert hit limit
@@ -160,16 +167,16 @@
         if( n->in(i)!=k->in(i)) // Different inputs?
           goto collision;       // "goto" is a speed hack...
       if( n->cmp(*k) ) {        // Check for any special bits
-        debug_only( _lookup_hits++ );
+        NOT_PRODUCT( _lookup_hits++ );
         return k;               // Hit!
       }
     }
   collision:
-    debug_only( _look_probes++ );
+    NOT_PRODUCT( _look_probes++ );
     key = (key + stride) & (_max-1); // Stride through table w/ relative prime
     k = _table[key];            // Get hashed value
     if( !k ) {                  // ?Miss?
-      debug_only( _lookup_misses++ );
+      NOT_PRODUCT( _lookup_misses++ );
       key = (first_sentinel == 0) ? key : first_sentinel; // ?saw sentinel?
       _table[key] = n;          // Insert into table!
       debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
@@ -200,7 +207,7 @@
   uint stride = key | 0x01;
 
   while( 1 ) {                  // While probing hash table
-    debug_only( _insert_probes++ );
+    NOT_PRODUCT( _insert_probes++ );
     Node *k = _table[key];      // Get hashed value
     if( !k || (k == _sentinel) ) break;       // Found a slot
     assert( k != n, "already inserted" );
@@ -218,7 +225,7 @@
   Node *k;
   uint hash = n->hash();
   if (hash == Node::NO_HASH) {
-    debug_only( _delete_misses++ );
+    NOT_PRODUCT( _delete_misses++ );
     return false;
   }
   uint key = hash & (_max-1);
@@ -226,10 +233,10 @@
   debug_only( uint counter = 0; );
   for( ; /* (k != NULL) && (k != _sentinel) */; ) {
     debug_only( counter++ );
-    debug_only( _delete_probes++ );
+    NOT_PRODUCT( _delete_probes++ );
     k = _table[key];            // Get hashed value
     if( !k ) {                  // Miss?
-      debug_only( _delete_misses++ );
+      NOT_PRODUCT( _delete_misses++ );
 #ifdef ASSERT
       if( VerifyOpto ) {
         for( uint i=0; i < _max; i++ )
@@ -239,7 +246,7 @@
       return false;             // Miss! Not in chain
     }
     else if( n == k ) {
-      debug_only( _delete_hits++ );
+      NOT_PRODUCT( _delete_hits++ );
       _table[key] = _sentinel;  // Hit! Label as deleted entry
       debug_only(((Node*)n)->exit_hash_lock()); // Unlock the node upon removal from table.
       return true;
@@ -271,11 +278,13 @@
   uint   old_max   = _max;
   Node **old_table = _table;
   // Construct new table with twice the space
+#ifndef PRODUCT
   _grows++;
   _total_inserts       += _inserts;
   _total_insert_probes += _insert_probes;
+  _insert_probes   = 0;
+#endif
   _inserts         = 0;
-  _insert_probes   = 0;
   _max     = _max << 1;
   _table   = NEW_ARENA_ARRAY( _a , Node* , _max ); // (Node**)_a->Amalloc( _max * sizeof(Node*) );
   memset(_table,0,sizeof(Node*)*_max);
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -100,7 +100,6 @@
 #ifndef PRODUCT
   Node  *find_index(uint idx);  // For debugging
   void   dump();                // For debugging, dump statistics
-#endif
   uint   _grows;                // For debugging, count of table grow()s
   uint   _look_probes;          // For debugging, count of hash probes
   uint   _lookup_hits;          // For debugging, count of hash_finds
@@ -111,6 +110,7 @@
   uint   _delete_misses;        // For debugging, count of hash probes for deletes
   uint   _total_inserts;        // For debugging, total inserts into hash table
   uint   _total_insert_probes;  // For debugging, total probes while inserting
+#endif
 };
 
 
--- a/hotspot/src/share/vm/opto/runtime.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -922,6 +922,30 @@
   return TypeFunc::make(domain, range);
 }
 
+const TypeFunc* OptoRuntime::multiplyToLen_Type() {
+  // create input type (domain)
+  int num_args      = 6;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL;    // x
+  fields[argp++] = TypeInt::INT;        // xlen
+  fields[argp++] = TypePtr::NOTNULL;    // y
+  fields[argp++] = TypeInt::INT;        // ylen
+  fields[argp++] = TypePtr::NOTNULL;    // z
+  fields[argp++] = TypeInt::INT;        // zlen
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // no result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = NULL;
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+  return TypeFunc::make(domain, range);
+}
+
+
+
 //------------- Interpreter state access for on stack replacement
 const TypeFunc* OptoRuntime::osr_end_Type() {
   // create input type (domain)
--- a/hotspot/src/share/vm/opto/runtime.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/opto/runtime.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -310,6 +310,8 @@
   static const TypeFunc* sha_implCompress_Type();
   static const TypeFunc* digestBase_implCompressMB_Type();
 
+  static const TypeFunc* multiplyToLen_Type();
+
   static const TypeFunc* updateBytesCRC32_Type();
 
   // leaf on stack replacement interpreter accessor types
--- a/hotspot/src/share/vm/prims/jvm.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -1403,14 +1403,6 @@
 JVM_END
 
 
-JVM_ENTRY(jclass, JVM_GetComponentType(JNIEnv *env, jclass cls))
-  JVMWrapper("JVM_GetComponentType");
-  oop mirror = JNIHandles::resolve_non_null(cls);
-  oop result = Reflection::array_component_type(mirror, CHECK_NULL);
-  return (jclass) JNIHandles::make_local(env, result);
-JVM_END
-
-
 JVM_ENTRY(jint, JVM_GetClassModifiers(JNIEnv *env, jclass cls))
   JVMWrapper("JVM_GetClassModifiers");
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
--- a/hotspot/src/share/vm/prims/jvm.h	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -483,9 +483,6 @@
 JNIEXPORT jboolean JNICALL
 JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
 
-JNIEXPORT jclass JNICALL
-JVM_GetComponentType(JNIEnv *env, jclass cls);
-
 JNIEXPORT jint JNICALL
 JVM_GetClassModifiers(JNIEnv *env, jclass cls);
 
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -191,7 +191,8 @@
       // It is not guaranteed that we can get such information here only
       // by analyzing bytecode in deoptimized frames. This is why this flag
       // is set during method compilation (see Compile::Process_OopMap_Node()).
-      bool save_oop_result = chunk->at(0)->scope()->return_oop();
+      // If the previous frame was popped, we don't have a result.
+      bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution();
       Handle return_value;
       if (save_oop_result) {
         // Reallocation may trigger GC. If deoptimization happened on return from
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -390,7 +390,7 @@
     return NULL;
   }
 
-  oop result = ArrayKlass::cast(klass)->component_mirror();
+  oop result = java_lang_Class::component_mirror(mirror);
 #ifdef ASSERT
   oop result2 = NULL;
   if (ArrayKlass::cast(klass)->dimension() == 1) {
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -135,6 +135,8 @@
 address StubRoutines::_updateBytesCRC32 = NULL;
 address StubRoutines::_crc_table_adr = NULL;
 
+address StubRoutines::_multiplyToLen = NULL;
+
 double (* StubRoutines::_intrinsic_log   )(double) = NULL;
 double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
 double (* StubRoutines::_intrinsic_exp   )(double) = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -202,6 +202,8 @@
   static address _updateBytesCRC32;
   static address _crc_table_adr;
 
+  static address _multiplyToLen;
+
   // These are versions of the java.lang.Math methods which perform
   // the same operations as the intrinsic version.  They are used for
   // constant folding in the compiler to ensure equivalence.  If the
@@ -358,6 +360,8 @@
   static address updateBytesCRC32()    { return _updateBytesCRC32; }
   static address crc_table_addr()      { return _crc_table_adr; }
 
+  static address multiplyToLen()       {return _multiplyToLen; }
+
   static address select_fill_function(BasicType t, bool aligned, const char* &name);
 
   static address zero_aligned_words()   { return _zero_aligned_words; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -274,7 +274,6 @@
   volatile_nonstatic_field(ArrayKlass,         _higher_dimension,                             Klass*)                                \
   volatile_nonstatic_field(ArrayKlass,         _lower_dimension,                              Klass*)                                \
   nonstatic_field(ArrayKlass,                  _vtable_len,                                   int)                                   \
-  nonstatic_field(ArrayKlass,                  _component_mirror,                             oop)                                   \
   nonstatic_field(CompiledICHolder,     _holder_method,                                Method*)                               \
   nonstatic_field(CompiledICHolder,     _holder_klass,                                 Klass*)                                \
   nonstatic_field(ConstantPool,         _tags,                                         Array<u1>*)                            \
@@ -811,6 +810,7 @@
      static_field(StubRoutines,                _cipherBlockChaining_decryptAESCrypt,          address)                               \
      static_field(StubRoutines,                _updateBytesCRC32,                             address)                               \
      static_field(StubRoutines,                _crc_table_adr,                                address)                               \
+     static_field(StubRoutines,                _multiplyToLen,                                address)                               \
                                                                                                                                      \
   /*****************/                                                                                                                \
   /* SharedRuntime */                                                                                                                \
--- a/hotspot/src/share/vm/utilities/hashtable.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -37,21 +37,22 @@
 #include "utilities/numberSeq.hpp"
 
 
-// This is a generic hashtable, designed to be used for the symbol
-// and string tables.
-//
-// It is implemented as an open hash table with a fixed number of buckets.
-//
-// %note:
-//  - HashtableEntrys are allocated in blocks to reduce the space overhead.
+// This hashtable is implemented as an open hash table with a fixed number of buckets.
 
-template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
-  BasicHashtableEntry<F>* entry;
-
-  if (_free_list) {
+template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry_free_list() {
+  BasicHashtableEntry<F>* entry = NULL;
+  if (_free_list != NULL) {
     entry = _free_list;
     _free_list = _free_list->next();
-  } else {
+  }
+  return entry;
+}
+
+// HashtableEntrys are allocated in blocks to reduce the space overhead.
+template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
+  BasicHashtableEntry<F>* entry = new_entry_free_list();
+
+  if (entry == NULL) {
     if (_first_free_entry + _entry_size >= _end_block) {
       int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
       int len = _entry_size * block_size;
@@ -84,9 +85,9 @@
 // This is somewhat an arbitrary heuristic but if one bucket gets to
 // rehash_count which is currently 100, there's probably something wrong.
 
-template <MEMFLAGS F> bool BasicHashtable<F>::check_rehash_table(int count) {
-  assert(table_size() != 0, "underflow");
-  if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
+template <class T, MEMFLAGS F> bool RehashableHashtable<T, F>::check_rehash_table(int count) {
+  assert(this->table_size() != 0, "underflow");
+  if (count > (((double)this->number_of_entries()/(double)this->table_size())*rehash_multiple)) {
     // Set a flag for the next safepoint, which should be at some guaranteed
     // safepoint interval.
     return true;
@@ -94,13 +95,13 @@
   return false;
 }
 
-template <class T, MEMFLAGS F> juint Hashtable<T, F>::_seed = 0;
+template <class T, MEMFLAGS F> juint RehashableHashtable<T, F>::_seed = 0;
 
 // Create a new table and using alternate hash code, populate the new table
 // with the existing elements.   This can be used to change the hash code
 // and could in the future change the size of the table.
 
-template <class T, MEMFLAGS F> void Hashtable<T, F>::move_to(Hashtable<T, F>* new_table) {
+template <class T, MEMFLAGS F> void RehashableHashtable<T, F>::move_to(RehashableHashtable<T, F>* new_table) {
 
   // Initialize the global seed for hashing.
   _seed = AltHashing::compute_seed();
@@ -110,7 +111,7 @@
 
   // Iterate through the table and create a new entry for the new table
   for (int i = 0; i < new_table->table_size(); ++i) {
-    for (HashtableEntry<T, F>* p = bucket(i); p != NULL; ) {
+    for (HashtableEntry<T, F>* p = this->bucket(i); p != NULL; ) {
       HashtableEntry<T, F>* next = p->next();
       T string = p->literal();
       // Use alternate hashing algorithm on the symbol in the first table
@@ -239,11 +240,11 @@
   }
 }
 
-template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(Symbol *symbol) {
+template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(Symbol *symbol) {
   return symbol->size() * HeapWordSize;
 }
 
-template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(oop oop) {
+template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(oop oop) {
   // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
   // and the String.value array is shared by several Strings. However, starting from JDK8,
   // the String.value array is not shared anymore.
@@ -256,12 +257,12 @@
 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
 // add a new function Hashtable<T, F>::literal_size(MyNewType lit)
 
-template <class T, MEMFLAGS F> void Hashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
+template <class T, MEMFLAGS F> void RehashableHashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
   NumberSeq summary;
   int literal_bytes = 0;
   for (int i = 0; i < this->table_size(); ++i) {
     int count = 0;
-    for (HashtableEntry<T, F>* e = bucket(i);
+    for (HashtableEntry<T, F>* e = this->bucket(i);
        e != NULL; e = e->next()) {
       count++;
       literal_bytes += literal_size(e->literal());
@@ -271,7 +272,7 @@
   double num_buckets = summary.num();
   double num_entries = summary.sum();
 
-  int bucket_bytes = (int)num_buckets * sizeof(bucket(0));
+  int bucket_bytes = (int)num_buckets * sizeof(HashtableBucket<F>);
   int entry_bytes  = (int)num_entries * sizeof(HashtableEntry<T, F>);
   int total_bytes = literal_bytes +  bucket_bytes + entry_bytes;
 
@@ -354,12 +355,20 @@
 
 
 // Explicitly instantiate these types
+#if INCLUDE_ALL_GCS
+template class Hashtable<nmethod*, mtGC>;
+template class HashtableEntry<nmethod*, mtGC>;
+template class BasicHashtable<mtGC>;
+#endif
 template class Hashtable<ConstantPool*, mtClass>;
+template class RehashableHashtable<Symbol*, mtSymbol>;
+template class RehashableHashtable<oopDesc*, mtSymbol>;
 template class Hashtable<Symbol*, mtSymbol>;
 template class Hashtable<Klass*, mtClass>;
 template class Hashtable<oop, mtClass>;
 #if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
 template class Hashtable<oop, mtSymbol>;
+template class RehashableHashtable<oop, mtSymbol>;
 #endif // SOLARIS || CHECK_UNHANDLED_OOPS
 template class Hashtable<oopDesc*, mtSymbol>;
 template class Hashtable<Symbol*, mtClass>;
--- a/hotspot/src/share/vm/utilities/hashtable.hpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.hpp	Wed Jul 05 20:00:59 2017 +0200
@@ -178,11 +178,6 @@
   void verify_lookup_length(double load);
 #endif
 
-  enum {
-    rehash_count = 100,
-    rehash_multiple = 60
-  };
-
   void initialize(int table_size, int entry_size, int number_of_entries);
 
   // Accessor
@@ -194,12 +189,12 @@
   // The following method is not MT-safe and must be done under lock.
   BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }
 
+  // Attempt to get an entry from the free list
+  BasicHashtableEntry<F>* new_entry_free_list();
+
   // Table entry management
   BasicHashtableEntry<F>* new_entry(unsigned int hashValue);
 
-  // Check that the table is unbalanced
-  bool check_rehash_table(int count);
-
   // Used when moving the entry to another table
   // Clean up links, but do not add to free_list
   void unlink_entry(BasicHashtableEntry<F>* entry) {
@@ -277,8 +272,30 @@
     return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
   }
 
+};
+
+template <class T, MEMFLAGS F> class RehashableHashtable : public Hashtable<T, F> {
+ protected:
+
+  enum {
+    rehash_count = 100,
+    rehash_multiple = 60
+  };
+
+  // Check that the table is unbalanced
+  bool check_rehash_table(int count);
+
+ public:
+  RehashableHashtable(int table_size, int entry_size)
+    : Hashtable<T, F>(table_size, entry_size) { }
+
+  RehashableHashtable(int table_size, int entry_size,
+                   HashtableBucket<F>* buckets, int number_of_entries)
+    : Hashtable<T, F>(table_size, entry_size, buckets, number_of_entries) { }
+
+
   // Function to move these elements into the new table.
-  void move_to(Hashtable<T, F>* new_table);
+  void move_to(RehashableHashtable<T, F>* new_table);
   static bool use_alternate_hashcode()  { return _seed != 0; }
   static juint seed()                    { return _seed; }
 
@@ -292,7 +309,6 @@
   static int literal_size(ConstantPool *cp) {Unimplemented(); return 0;}
   static int literal_size(Klass *k)         {Unimplemented(); return 0;}
 
-public:
   void dump_table(outputStream* st, const char *table_name);
 
  private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArrayOfNoTypeCheck.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8055910
+ * @summary Arrays.copyOf doesn't perform subtype check
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
+ *
+ */
+
+import java.util.Arrays;
+
+public class TestArrayOfNoTypeCheck {
+
+    static class A {
+    }
+
+    static class B extends A {
+    }
+
+    static B[] test(A[] arr) {
+        return Arrays.copyOf(arr, 10, B[].class);
+    }
+
+    static public void main(String[] args) {
+        A[] arr = new A[20];
+        for (int i = 0; i < 20000; i++) {
+            test(arr);
+        }
+        A[] arr2 = new A[20];
+        arr2[0] = new A();
+        boolean exception = false;
+        try {
+            test(arr2);
+        } catch (ArrayStoreException ase) {
+            exception = true;
+        }
+        if (!exception) {
+            throw new RuntimeException("TEST FAILED: ArrayStoreException not thrown");
+        }
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build AddExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class AddExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build AddExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class AddExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build DecrementExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class DecrementExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build DecrementExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class DecrementExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build IncrementExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class IncrementExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build IncrementExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class IncrementExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,6 +22,7 @@
  */
 
 import com.oracle.java.testlibrary.Platform;
+import intrinsics.Verifier;
 
 import java.io.FileOutputStream;
 import java.lang.reflect.Executable;
@@ -79,10 +80,10 @@
 
         System.out.println("Expected intrinsic count is " + expectedIntrinsicCount + " name " + getIntrinsicId());
 
-        final FileOutputStream out = new FileOutputStream(getVMOption("LogFile") + ".verify.properties");
+        final FileOutputStream out = new FileOutputStream(getVMOption("LogFile") + Verifier.PROPERTY_FILE_SUFFIX);
         Properties expectedProps = new Properties();
-        expectedProps.setProperty("intrinsic.name", getIntrinsicId());
-        expectedProps.setProperty("intrinsic.expectedCount", String.valueOf(expectedIntrinsicCount));
+        expectedProps.setProperty(Verifier.INTRINSIC_NAME_PROPERTY, getIntrinsicId());
+        expectedProps.setProperty(Verifier.INTRINSIC_EXPECTED_COUNT_PROPERTY, String.valueOf(expectedIntrinsicCount));
         expectedProps.store(out, null);
 
         out.close();
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build MultiplyExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class MultiplyExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build MultiplyExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class MultiplyExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build NegateExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class NegateExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build NegateExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class NegateExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build SubtractExactIntTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
 
  */
 
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ *          /compiler/testlibrary
  * @build SubtractExactLongTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
  *                   -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
  *                   -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
  */
 
 public class SubtractExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/Verifier.java	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.Properties;
-
-public class Verifier {
-
-    public static void main(String[] args) throws Exception {
-        if (args.length == 0)
-            throw new RuntimeException("Test bug, nothing to verify");
-        for (String hsLogFile : args) {
-            verify(hsLogFile);
-        }
-    }
-
-    private static void verify(String hsLogFile) throws Exception {
-        System.out.println("Verifying " + hsLogFile);
-
-        final Properties expectedProperties = new Properties();
-        final FileReader reader = new FileReader(hsLogFile + ".verify.properties");
-        expectedProperties.load(reader);
-        reader.close();
-
-        int fullMatchCnt = 0;
-        int suspectCnt = 0;
-        final String intrinsicId = expectedProperties.getProperty("intrinsic.name");
-        final String prefix = "<intrinsic id='";
-        final String prefixWithId = prefix + intrinsicId + "'";
-        final int expectedCount = Integer.parseInt(expectedProperties.getProperty("intrinsic.expectedCount"));
-
-        BufferedReader r = new BufferedReader(new FileReader(hsLogFile));
-        String s;
-        while ((s = r.readLine()) != null) {
-            if (s.startsWith(prefix)) {
-                if (s.startsWith(prefixWithId)) {
-                    fullMatchCnt++;
-                } else {
-                    suspectCnt++;
-                    System.out.println("WARNING: Other intrinsic detected " + s);
-                }
-            }
-        }
-        r.close();
-
-        System.out.println("Intrinsic " + intrinsicId + " verification, expected: " + expectedCount + ", matched: " + fullMatchCnt + ", suspected: " + suspectCnt);
-        if (expectedCount != fullMatchCnt)
-            throw new RuntimeException("Unexpected count of intrinsic  " + prefixWithId + " expected:" + expectedCount + ", matched: " + fullMatchCnt + ", suspected: " + suspectCnt);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/multiplytolen/TestMultiplyToLen.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8055494
+ * @summary Add C2 x86 intrinsic for BigInteger::multiplyToLen() method
+ *
+ * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch
+ *      -XX:CompileCommand=exclude,TestMultiplyToLen::main
+ *      -XX:CompileCommand=option,TestMultiplyToLen::base_multiply,ccstr,DisableIntrinsic,_multiplyToLen
+ *      -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_multiplyToLen
+ *      -XX:CompileCommand=inline,java.math.BigInteger::multiply TestMultiplyToLen
+ */
+
+import java.util.Random;
+import java.math.*;
+
+public class TestMultiplyToLen {
+
+    // Avoid intrinsic by preventing inlining multiply() and multiplyToLen().
+    public static BigInteger base_multiply(BigInteger op1, BigInteger op2) {
+      return op1.multiply(op2);
+    }
+
+    // Generate multiplyToLen() intrinsic by inlining multiply().
+    public static BigInteger new_multiply(BigInteger op1, BigInteger op2) {
+      return op1.multiply(op2);
+    }
+
+    public static boolean bytecompare(BigInteger b1, BigInteger b2) {
+      byte[] data1 = b1.toByteArray();
+      byte[] data2 = b2.toByteArray();
+      if (data1.length != data2.length)
+        return false;
+      for (int i = 0; i < data1.length; i++) {
+        if (data1[i] != data2[i])
+          return false;
+      }
+      return true;
+    }
+
+    public static String stringify(BigInteger b) {
+      String strout= "";
+      byte [] data = b.toByteArray();
+      for (int i = 0; i < data.length; i++) {
+        strout += (String.format("%02x",data[i]) + " ");
+      }
+      return strout;
+    }
+
+    public static void main(String args[]) throws Exception {
+
+      BigInteger oldsum = new BigInteger("0");
+      BigInteger newsum = new BigInteger("0");
+
+      BigInteger b1, b2, oldres, newres;
+
+      Random rand = new Random();
+      long seed = System.nanoTime();
+      Random rand1 = new Random();
+      long seed1 = System.nanoTime();
+      rand.setSeed(seed);
+      rand1.setSeed(seed1);
+
+      for (int j = 0; j < 1000000; j++) {
+        int rand_int = rand1.nextInt(3136)+32;
+        int rand_int1 = rand1.nextInt(3136)+32;
+        b1 = new BigInteger(rand_int, rand);
+        b2 = new BigInteger(rand_int1, rand);
+
+        oldres = base_multiply(b1,b2);
+        newres = new_multiply(b1,b2);
+
+        oldsum = oldsum.add(oldres);
+        newsum = newsum.add(newres);
+
+        if (!bytecompare(oldres,newres)) {
+          System.out.print("mismatch for:b1:" + stringify(b1) + " :b2:" + stringify(b2) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres));
+          System.out.println(b1);
+          System.out.println(b2);
+          throw new Exception("Failed");
+        }
+      }
+      if (!bytecompare(oldsum,newsum))  {
+        System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum));
+        throw new Exception("Failed");
+      } else {
+        System.out.println("Success");
+      }
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/SHAOptionsBase.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import sha.predicate.IntrinsicPredicates;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Base class for all CLI tests on SHA-related options.
+ *
+ * Instead of using huge complex tests for each option, each test is constructed
+ * from several test cases shared among different tests.
+ */
+public class SHAOptionsBase extends CommandLineOptionTest {
+    protected static final String USE_SHA_OPTION = "UseSHA";
+    protected static final String USE_SHA1_INTRINSICS_OPTION
+            = "UseSHA1Intrinsics";
+    protected static final String USE_SHA256_INTRINSICS_OPTION
+            = "UseSHA256Intrinsics";
+    protected static final String USE_SHA512_INTRINSICS_OPTION
+            = "UseSHA512Intrinsics";
+
+    // Note that strings below will be passed to
+    // CommandLineOptionTest.verifySameJVMStartup and thus are regular
+    // expressions, not just a plain strings.
+    protected static final String SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE
+            = "SHA instructions are not available on this CPU";
+    protected static final String SHA1_INSTRUCTION_IS_NOT_AVAILABLE
+            = "SHA1 instruction is not available on this CPU\\.";
+    protected static final String SHA256_INSTRUCTION_IS_NOT_AVAILABLE
+            = "SHA256 instruction \\(for SHA-224 and SHA-256\\) "
+            + "is not available on this CPU\\.";
+    protected static final String SHA512_INSTRUCTION_IS_NOT_AVAILABLE
+            = "SHA512 instruction \\(for SHA-384 and SHA-512\\) "
+            + "is not available on this CPU\\.";
+    protected static final String SHA_INTRINSICS_ARE_NOT_AVAILABLE
+            = "SHA intrinsics are not available on this CPU";
+
+    private final TestCase[] testCases;
+
+    /**
+     * Returns warning message that should occur in VM output if an option with
+     * the name {@code optionName} was turned on and CPU does not support
+     * required instructions.
+     *
+     * @param optionName The name of the option for which warning message should
+     *                   be returned.
+     * @return A warning message that will be printed out to VM output if CPU
+     *         instructions required by the option are not supported.
+     */
+    protected static String getWarningForUnsupportedCPU(String optionName) {
+        if (Platform.isSparc()) {
+            switch (optionName) {
+                case SHAOptionsBase.USE_SHA_OPTION:
+                    return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE;
+                case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+                    return SHAOptionsBase.SHA1_INSTRUCTION_IS_NOT_AVAILABLE;
+                case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+                    return SHAOptionsBase.SHA256_INSTRUCTION_IS_NOT_AVAILABLE;
+                case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+                    return SHAOptionsBase.SHA512_INSTRUCTION_IS_NOT_AVAILABLE;
+                default:
+                    throw new Error("Unexpected option " + optionName);
+            }
+        } else if (Platform.isX64() || Platform.isX86()) {
+            switch (optionName) {
+                case SHAOptionsBase.USE_SHA_OPTION:
+                    return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE;
+                case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+                case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+                case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+                    return SHAOptionsBase.SHA_INTRINSICS_ARE_NOT_AVAILABLE;
+                default:
+                    throw new Error("Unexpected option " + optionName);
+            }
+        } else {
+            throw new Error("Support for CPUs other then X86 or SPARC is not "
+                    + "implemented.");
+        }
+    }
+
+    /**
+     * Returns the predicate indicating whether or not CPU instructions required
+     * by the option with name {@code optionName} are available.
+     *
+     * @param optionName The name of the option for which a predicate should be
+     *                   returned.
+     * @return The predicate on availability of CPU instructions required by the
+     *         option.
+     */
+    protected static BooleanSupplier getPredicateForOption(String optionName) {
+        switch (optionName) {
+            case SHAOptionsBase.USE_SHA_OPTION:
+                return IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE;
+            case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+                return IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE;
+            case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+                return IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE;
+            case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+                return IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE;
+            default:
+                throw new Error("Unexpected option " + optionName);
+        }
+    }
+
+    public SHAOptionsBase(TestCase... testCases) {
+        super(Boolean.TRUE::booleanValue);
+        this.testCases = testCases;
+    }
+
+    @Override
+    protected void runTestCases() throws Throwable {
+        for (TestCase testCase : testCases) {
+            testCase.test();
+        }
+    }
+
+    public static abstract class TestCase {
+        protected final String optionName;
+        private final BooleanSupplier predicate;
+
+        protected TestCase(String optionName, BooleanSupplier predicate) {
+            this.optionName = optionName;
+            this.predicate = predicate;
+        }
+
+        protected final void test() throws Throwable {
+            String testCaseName = this.getClass().getName();
+            if (!predicate.getAsBoolean()) {
+                System.out.println("Skipping " + testCaseName
+                        + " due to predicate failure.");
+                return;
+            } else {
+                System.out.println("Running " + testCaseName);
+            }
+
+            verifyWarnings();
+            verifyOptionValues();
+        }
+
+        protected void verifyWarnings() throws Throwable {
+        }
+
+        protected void verifyOptionValues() throws Throwable {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA1Intrinsics option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA1IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestUseSHA1IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA1IntrinsicsOptionOnSupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+                SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA1Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA1IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseSHA1IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA1IntrinsicsOptionOnUnsupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(
+                new GenericTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+                new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+                new GenericTestCaseForUnsupportedX86CPU(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+                new GenericTestCaseForOtherCPU(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA256Intrinsics option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA256IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseSHA256IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA256IntrinsicsOptionOnSupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+                SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA256Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA256IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseSHA256IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA256IntrinsicsOptionOnUnsupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(
+                new GenericTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+                new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+                new GenericTestCaseForUnsupportedX86CPU(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+                new GenericTestCaseForOtherCPU(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA512Intrinsics option processing on supported CPU.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA512IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseSHA512IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA512IntrinsicsOptionOnSupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+                SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA512Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA512IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseSHA512IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA512IntrinsicsOptionOnUnsupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(
+                new GenericTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+                new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+                new GenericTestCaseForUnsupportedX86CPU(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+                new GenericTestCaseForOtherCPU(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHAOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestUseSHAOptionOnSupportedCPU
+ */
+public class TestUseSHAOptionOnSupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(
+                new GenericTestCaseForSupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA_OPTION),
+                new UseSHASpecificTestCaseForSupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify UseSHA option processing on unsupported CPU.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHAOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestUseSHAOptionOnUnsupportedCPU
+ */
+public class TestUseSHAOptionOnUnsupportedCPU {
+    public static void main(String args[]) throws Throwable {
+        new SHAOptionsBase(
+                new GenericTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA_OPTION),
+                new UseSHASpecificTestCaseForUnsupportedSparcCPU(
+                        SHAOptionsBase.USE_SHA_OPTION),
+                new GenericTestCaseForUnsupportedX86CPU(
+                        SHAOptionsBase.USE_SHA_OPTION),
+                new GenericTestCaseForOtherCPU(
+                        SHAOptionsBase.USE_SHA_OPTION)).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to non-x86 and
+ * non-SPARC CPUs.
+ */
+public class GenericTestCaseForOtherCPU extends
+        SHAOptionsBase.TestCase {
+    public GenericTestCaseForOtherCPU(String optionName) {
+        // Execute the test case on any CPU except SPARC and X86
+        super(optionName, new NotPredicate(new OrPredicate(Platform::isSparc,
+                new OrPredicate(Platform::isX64, Platform::isX86))));
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that on non-x86 and non-SPARC CPU usage of SHA-related
+        // options will not cause any warnings.
+        CommandLineOptionTest.verifySameJVMStartup(null,
+                new String[] { ".*" + optionName + ".*" }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        CommandLineOptionTest.verifySameJVMStartup(null,
+                new String[] { ".*" + optionName + ".*" }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that option is disabled by default.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+        // Verify that option is disabled even if it was explicitly enabled
+        // using CLI options.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that option is disabled when it explicitly disabled
+        // using CLI options.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to SPARC CPUs which
+ * support instructions required by the tested option.
+ */
+public class GenericTestCaseForSupportedSparcCPU extends
+        SHAOptionsBase.TestCase {
+    public GenericTestCaseForSupportedSparcCPU(String optionName) {
+        super(optionName, new AndPredicate(Platform::isSparc,
+                SHAOptionsBase.getPredicateForOption(optionName)));
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that there are no warning when option is explicitly enabled.
+        CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that option could be disabled even if +UseSHA was passed to
+        // JVM.
+        CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+
+        // Verify that it is possible to enable the tested option and disable
+        // all SHA intrinsics via -UseSHA without any warnings.
+        CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that on supported CPU option is enabled by default.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true");
+
+        // Verify that it is possible to explicitly enable the option.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that it is possible to explicitly disable the option.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+
+        // verify that option is disabled when -UseSHA was passed to JVM.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, false));
+
+        // Verify that it is possible to explicitly disable the tested option
+        // even if +UseSHA was passed to JVM.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to SPARC CPUs which don't
+ * support instruction required by the tested option.
+ */
+public class GenericTestCaseForUnsupportedSparcCPU extends
+        SHAOptionsBase.TestCase {
+    public GenericTestCaseForUnsupportedSparcCPU(String optionName) {
+        super(optionName, new AndPredicate(Platform::isSparc,
+                new NotPredicate(SHAOptionsBase.getPredicateForOption(
+                        optionName))));
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        //Verify that option could be disabled without any warnings.
+        CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that option is disabled by default.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+        // Verify that option is disabled even if it was explicitly enabled
+        // using CLI options.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that option is disabled when +UseSHA was passed to JVM.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to X86 CPUs that don't
+ * support SHA-related instructions.
+ */
+public class GenericTestCaseForUnsupportedX86CPU
+        extends SHAOptionsBase.TestCase {
+    public GenericTestCaseForUnsupportedX86CPU(String optionName) {
+        super(optionName, new OrPredicate(Platform::isX64, Platform::isX86));
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that when the tested option is explicitly enabled, then
+        // a warning will occur in VM output.
+        CommandLineOptionTest.verifySameJVMStartup(new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, null, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that the tested option could be explicitly disabled without
+        // a warning.
+        CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that the tested option is disabled by default.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+        // Verify that it is not possible to explicitly enable the option.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+        // Verify that the tested option is disabled even if +UseSHA was passed
+        // to JVM.
+        CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * Test case specific to UseSHA*Intrinsics options targeted to SPARC CPUs which
+ * don't support required instruction, but support other SHA-related
+ * instructions.
+ *
+ * For example, CPU support sha1 instruction, but don't support sha256 or
+ * sha512.
+ */
+public class UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU
+        extends SHAOptionsBase.TestCase {
+    public UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+            String optionName) {
+        // execute test case on SPARC CPU that support any sha* instructions,
+        // but does not support sha* instruction required by the tested option.
+        super(optionName, new AndPredicate(Platform::isSparc,
+                new AndPredicate(
+                        IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE,
+                        new NotPredicate(SHAOptionsBase.getPredicateForOption(
+                                optionName)))));
+    }
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that attempt to enable the tested option will cause a warning.
+        CommandLineOptionTest.verifySameJVMStartup(new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, null, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * UseSHA specific test case targeted to SPARC CPUs which support any sha*
+ * instruction.
+ */
+public class UseSHASpecificTestCaseForSupportedSparcCPU
+        extends SHAOptionsBase.TestCase {
+    public UseSHASpecificTestCaseForSupportedSparcCPU(String optionName) {
+        super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(Platform::isSparc,
+                IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE));
+
+        Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
+                "Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION
+                        + " option only.");
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that there will be no warnings when +UseSHA was passed and
+        // all UseSHA*Intrinsics options were disabled.
+        CommandLineOptionTest.verifySameJVMStartup(
+                null, new String[] { ".*UseSHA.*" }, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that UseSHA is disabled when all UseSHA*Intrinscs are
+        // disabled.
+        CommandLineOptionTest.verifyOptionValueForSameVM(
+                SHAOptionsBase.USE_SHA_OPTION, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+
+        CommandLineOptionTest.verifyOptionValueForSameVM(
+                // Verify that UseSHA is disabled when all UseSHA*Intrinscs are
+                // disabled even if it was explicitly enabled.
+                SHAOptionsBase.USE_SHA_OPTION, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+
+        // Verify that explicitly disabled UseSHA option remains disabled even
+        // if all UseSHA*Intrinsics options were enabled.
+        CommandLineOptionTest.verifyOptionValueForSameVM(
+                SHAOptionsBase.USE_SHA_OPTION, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, false),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * UseSHA specific test case targeted to SPARC CPUs which don't support all sha*
+ * instructions.
+ */
+public class UseSHASpecificTestCaseForUnsupportedSparcCPU
+        extends SHAOptionsBase.TestCase {
+    public UseSHASpecificTestCaseForUnsupportedSparcCPU(String optionName) {
+        super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(Platform::isSparc,
+                new NotPredicate(
+                        IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE)));
+
+        Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
+                "Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION
+                        + " option only.");
+    }
+
+    @Override
+    protected void verifyWarnings() throws Throwable {
+        // Verify that attempt to use UseSHA option will cause a warning.
+        CommandLineOptionTest.verifySameJVMStartup(new String[] {
+                        SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+                }, null, ExitCode.OK,
+                CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+    }
+
+    @Override
+    protected void verifyOptionValues() throws Throwable {
+        // Verify that UseSHA option remains disabled even if all
+        // UseSHA*Intrincs options were enabled.
+        CommandLineOptionTest.verifyOptionValueForSameVM(
+                SHAOptionsBase.USE_SHA_OPTION, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+
+        // Verify that UseSHA option remains disabled even if all
+        // UseSHA*Intrincs options were enabled and UseSHA was enabled as well.
+        CommandLineOptionTest.verifyOptionValueForSameVM(
+                SHAOptionsBase.USE_SHA_OPTION, "false",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+                CommandLineOptionTest.prepareBooleanFlag(
+                        SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/SHASanityTestBase.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 intrinsics.Verifier;
+import sun.hotspot.WhiteBox;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.function.BooleanSupplier;
+
+/**
+ * Base class for sanity tests on SHA intrinsics support.
+ */
+public class SHASanityTestBase {
+    protected static final String SHA1_INTRINSIC_ID
+            = "_sha_implCompress";
+    protected static final String SHA256_INTRINSIC_ID
+            = "_sha2_implCompress";
+    protected static final String SHA512_INTRINSIC_ID
+            = "_sha5_implCompress";
+    protected static final String MB_INTRINSIC_ID
+            = "_digestBase_implCompressMB";
+
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final int MSG_SIZE = 1024;
+    private static final int OFFSET = 0;
+    private static final int ITERATIONS = 10000;
+    private static final int WARMUP_ITERATIONS = 1;
+    private static final String PROVIDER = "SUN";
+
+    private final BooleanSupplier predicate;
+    private final String intrinsicID;
+
+    /**
+     * Construct the new test on intrinsic with ID {@code intrinsicID},
+     * which is expected to be emitted if {@code predicate} is evaluated to
+     * {@code true}.
+     *
+     * @param predicate The predicate indicating if the intrinsic is expected to
+     *                  be used.
+     * @param intrinsicID The ID of the intrinsic to be tested.
+     */
+    protected SHASanityTestBase(BooleanSupplier predicate, String intrinsicID) {
+        this.predicate = predicate;
+        this.intrinsicID = intrinsicID;
+    }
+
+    /**
+     * Run the test and dump properties to file.
+     *
+     * @throws Exception when something went wrong.
+     */
+    public final void test() throws Exception {
+        String algorithm = Objects.requireNonNull(
+                System.getProperty("algorithm"),
+                "Algorithm name should be specified.");
+
+        dumpProperties();
+
+        TestSHA.testSHA(SHASanityTestBase.PROVIDER, algorithm,
+                SHASanityTestBase.MSG_SIZE, SHASanityTestBase.OFFSET,
+                SHASanityTestBase.ITERATIONS,
+                SHASanityTestBase.WARMUP_ITERATIONS);
+    }
+
+    /**
+     * Dump properties containing information about the tested intrinsic name
+     * and whether or not is should be used to the file
+     * &lt;LogFile value&gt;.verify.properties.
+     *
+     * @throws IOException when something went wrong during dumping to file.
+     */
+    private void dumpProperties() throws IOException {
+        Properties properties = new Properties();
+        properties.setProperty(Verifier.INTRINSIC_NAME_PROPERTY, intrinsicID);
+        properties.setProperty(Verifier.INTRINSIC_IS_EXPECTED_PROPERTY,
+                String.valueOf(predicate.getAsBoolean()));
+
+        String logFileName
+                = SHASanityTestBase.WHITE_BOX.getStringVMFlag("LogFile");
+        FileOutputStream fileOutputStream = new FileOutputStream(logFileName
+                + Verifier.PROPERTY_FILE_SUFFIX);
+
+        properties.store(fileOutputStream, null);
+        fileOutputStream.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8035968
+ * @summary Verify that SHA-1 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA1Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA1Intrinsics
+ *                   -Dalgorithm=SHA-1 TestSHA1Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:-UseSHA1Intrinsics
+ *                   -Dalgorithm=SHA-1 TestSHA1Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                   intrinsics.Verifier positive.log negative.log
+ */
+import sha.predicate.IntrinsicPredicates;
+
+public class TestSHA1Intrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.SHA1_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-1 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA1MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA1Intrinsics -XX:-UseSHA256Intrinsics
+ *                   -XX:-UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-1 TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_def.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA1Intrinsics -Dalgorithm=SHA-1
+ *                   TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ *                   -Dalgorithm=SHA-1 TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                   intrinsics.Verifier positive.log positive_def.log
+ *                   negative.log
+ */
+public class TestSHA1MultiBlockIntrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.MB_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-256 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA256Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_224.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-224 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_224.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:-UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-224 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_256.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-256 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_256.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:-UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-256 TestSHA256Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                    intrinsics.Verifier positive_224.log positive_256.log
+ *                    negative_224.log negative_256.log
+ */
+public class TestSHA256Intrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.SHA256_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-256 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA256MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_224.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics -XX:-UseSHA1Intrinsics
+ *                   -XX:-UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-224 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_224_def.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics -Dalgorithm=SHA-224
+ *                   TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_224.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ *                   -Dalgorithm=SHA-224 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_256.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics -XX:-UseSHA1Intrinsics
+ *                   -XX:-UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-256 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_256_def.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA256Intrinsics -Dalgorithm=SHA-256
+ *                   TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_256.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ *                   -Dalgorithm=SHA-256 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                   intrinsics.Verifier positive_224.log positive_256.log
+ *                   positive_224_def.log positive_256_def.log negative_224.log
+ *                   negative_256.log
+ */
+public class TestSHA256MultiBlockIntrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.MB_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-512 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA512Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_384.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-384 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_384.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:-UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-384 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_512.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-512 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_512.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:-UseSHA512Intrinsics
+ *                   -Dalgorithm=SHA-512 TestSHA512Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                    intrinsics.Verifier positive_384.log positive_512.log
+ *                    negative_384.log negative_512.log
+ */
+public class TestSHA512Intrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.SHA512_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-512 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA512MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_384.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics -XX:-UseSHA1Intrinsics
+ *                   -XX:-UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-384 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_384_def.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics -Dalgorithm=SHA-384
+ *                   TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_384.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ *                   -Dalgorithm=SHA-384 TestSHA1Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_512.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics -XX:-UseSHA1Intrinsics
+ *                   -XX:-UseSHA256Intrinsics
+ *                   -Dalgorithm=SHA-512 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=positive_512_def.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA
+ *                   -XX:+UseSHA512Intrinsics -Dalgorithm=SHA-512
+ *                   TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ *                   -XX:Tier4InvocationThreshold=500
+ *                   -XX:+LogCompilation -XX:LogFile=negative_512.log
+ *                   -XX:CompileOnly=sun/security/provider/DigestBase
+ *                   -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ *                   -Dalgorithm=SHA-512 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ *                    intrinsics.Verifier positive_384.log positive_512.log
+ *                    positive_384_def.log positive_512_def.log negative_384.log
+ *                    negative_512.log
+ */
+public class TestSHA512MultiBlockIntrinsics {
+    public static void main(String args[]) throws Exception {
+        new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+                SHASanityTestBase.MB_INTRINSIC_ID).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/intrinsics/Verifier.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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 intrinsics;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.Properties;
+
+public class Verifier {
+    enum VerificationStrategy {
+        VERIFY_STRONG_EQUALITY {
+            @Override
+            void verify(Properties expectedProperties, int fullMatchCnt,
+                        int suspectCnt) {
+                int expectedCount = Integer.parseInt(
+                        expectedProperties.getProperty(
+                                Verifier.INTRINSIC_EXPECTED_COUNT_PROPERTY));
+                String intrinsicID = expectedProperties.getProperty(
+                        Verifier.INTRINSIC_NAME_PROPERTY);
+
+                System.out.println("Intrinsic " + intrinsicID
+                        + " verification, expected: " + expectedCount
+                        + ", matched: " + fullMatchCnt
+                        + ", suspected: " + suspectCnt);
+                if (expectedCount != fullMatchCnt) {
+                    throw new RuntimeException(
+                            "Unexpected count of intrinsic  "
+                                    + intrinsicID
+                                    + " expected:" + expectedCount
+                                    + ", matched: " + fullMatchCnt
+                                    + ", suspected: " + suspectCnt);
+                }
+            }
+        },
+
+        VERIFY_INTRINSIC_USAGE {
+            @Override
+            void verify(Properties expectedProperties, int fullMatchCnt,
+                        int suspectCnt) {
+                boolean isExpected = Boolean.parseBoolean(
+                        expectedProperties.getProperty(
+                                Verifier.INTRINSIC_IS_EXPECTED_PROPERTY));
+                String intrinsicID = expectedProperties.getProperty(
+                        Verifier.INTRINSIC_NAME_PROPERTY);
+
+                System.out.println("Intrinsic " + intrinsicID
+                        + " verification, is expected: " + isExpected
+                        + ", matched: " + fullMatchCnt
+                        + ", suspected: " + suspectCnt);
+                if ((fullMatchCnt == 0 && isExpected)
+                        || (fullMatchCnt > 0 && !isExpected)) {
+                    throw new RuntimeException(
+                            "Unexpected count of intrinsic  "
+                                    + intrinsicID
+                                    + " is expected:" + isExpected
+                                    + ", matched: " + fullMatchCnt
+                                    + ", suspected: " + suspectCnt);
+                }
+            }
+        };
+
+        void verify(Properties expectedProperties, int fullMathCnt,
+                    int suspectCnt) {
+            throw new RuntimeException("Default strategy is not implemented.");
+        }
+    }
+
+    public static final String PROPERTY_FILE_SUFFIX = ".verify.properties";
+    public static final String INTRINSIC_NAME_PROPERTY = "intrinsic.name";
+    public static final String INTRINSIC_IS_EXPECTED_PROPERTY
+            = "intrinsic.expected";
+    public static final String INTRINSIC_EXPECTED_COUNT_PROPERTY
+            = "intrinsic.expectedCount";
+    private static final String DEFAULT_STRATEGY
+            = VerificationStrategy.VERIFY_STRONG_EQUALITY.name();
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            throw new RuntimeException("Test bug, nothing to verify");
+        }
+        for (String hsLogFile : args) {
+            verify(hsLogFile);
+        }
+    }
+
+    private static void verify(String hsLogFile) throws Exception {
+        System.out.println("Verifying " + hsLogFile);
+
+        Properties expectedProperties = new Properties();
+        FileReader reader = new FileReader(hsLogFile
+                + Verifier.PROPERTY_FILE_SUFFIX);
+        expectedProperties.load(reader);
+        reader.close();
+
+        int fullMatchCnt = 0;
+        int suspectCnt = 0;
+        String intrinsicId = expectedProperties.getProperty(
+                Verifier.INTRINSIC_NAME_PROPERTY);
+        String prefix = "<intrinsic id='";
+        String prefixWithId = prefix + intrinsicId + "'";
+
+        try (BufferedReader compLogReader
+                     = new BufferedReader(new FileReader(hsLogFile))) {
+            String logLine;
+            while ((logLine = compLogReader.readLine()) != null) {
+                if (logLine.startsWith(prefix)) {
+                    if (logLine.startsWith(prefixWithId)) {
+                        fullMatchCnt++;
+                    } else {
+                        suspectCnt++;
+                        System.err.println(
+                                "WARNING: Other intrinsic detected " + logLine);
+                    }
+                }
+            }
+        }
+
+        VerificationStrategy strategy = VerificationStrategy.valueOf(
+                System.getProperty("verificationStrategy",
+                        Verifier.DEFAULT_STRATEGY));
+        strategy.verify(expectedProperties, fullMatchCnt, suspectCnt);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 sha.predicate;
+
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.CPUSpecificPredicate;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+import sun.hotspot.WhiteBox;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Helper class aimed to provide predicates on availability of SHA-related
+ * CPU instructions and intrinsics.
+ */
+public class IntrinsicPredicates {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final long TIERED_MAX_LEVEL = 4L;
+    /**
+     * Boolean supplier that check if any method could be compiled by C2.
+     * Method potentially could be compiled by C2 if Server VM is used and
+     * either tiered compilation is disabled or TIERED_MAX_LEVEL tier is
+     * reachable.
+     *
+     * Please don't place this definition after SHA*_INTRINSICS_AVAILABLE
+     * definitions. Otherwise its value will be {@code null} at the time when
+     * all dependent fields will be initialized.
+     */
+    private static final BooleanSupplier COMPILABLE_BY_C2 = () -> {
+        boolean isTiered = IntrinsicPredicates.WHITE_BOX.getBooleanVMFlag(
+                "TieredCompilation");
+        long tieredMaxLevel = IntrinsicPredicates.WHITE_BOX.getIntxVMFlag(
+                "TieredStopAtLevel");
+        boolean maxLevelIsReachable = (tieredMaxLevel
+                == IntrinsicPredicates.TIERED_MAX_LEVEL);
+        return Platform.isServer() && (!isTiered || maxLevelIsReachable);
+    };
+
+    public static final BooleanSupplier SHA1_INSTRUCTION_AVAILABLE
+            = new CPUSpecificPredicate("sparc.*", new String[] { "sha1" },
+                    null);
+
+    public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE
+            = new CPUSpecificPredicate("sparc.*", new String[] { "sha256" },
+                    null);
+
+    public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE
+            = new CPUSpecificPredicate("sparc.*", new String[] { "sha512" },
+                    null);
+
+    public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE
+            = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
+                    new OrPredicate(
+                            IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE,
+                            IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE));
+
+    public static final BooleanSupplier SHA1_INTRINSICS_AVAILABLE
+            = new AndPredicate(new AndPredicate(
+                    IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
+                    IntrinsicPredicates.COMPILABLE_BY_C2),
+                IntrinsicPredicates.booleanOptionValue("UseSHA1Intrinsics"));
+
+    public static final BooleanSupplier SHA256_INTRINSICS_AVAILABLE
+            = new AndPredicate(new AndPredicate(
+                    IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE,
+                    IntrinsicPredicates.COMPILABLE_BY_C2),
+                IntrinsicPredicates.booleanOptionValue("UseSHA256Intrinsics"));
+
+    public static final BooleanSupplier SHA512_INTRINSICS_AVAILABLE
+            = new AndPredicate(new AndPredicate(
+                    IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE,
+                    IntrinsicPredicates.COMPILABLE_BY_C2),
+                IntrinsicPredicates.booleanOptionValue("UseSHA512Intrinsics"));
+
+    private static BooleanSupplier booleanOptionValue(String option) {
+        return () -> IntrinsicPredicates.WHITE_BOX.getBooleanVMFlag(option);
+    }
+
+    private IntrinsicPredicates() {
+    }
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -27,6 +27,7 @@
     private static final String osName      = System.getProperty("os.name");
     private static final String dataModel   = System.getProperty("sun.arch.data.model");
     private static final String vmVersion   = System.getProperty("java.vm.version");
+    private static final String javaVersion = System.getProperty("java.version");
     private static final String osArch      = System.getProperty("os.arch");
     private static final String vmName      = System.getProperty("java.vm.name");
 
@@ -83,7 +84,8 @@
     }
 
     public static boolean isDebugBuild() {
-        return vmVersion.toLowerCase().contains("debug");
+        return (vmVersion.toLowerCase().contains("debug") ||
+                javaVersion.toLowerCase().contains("debug"));
     }
 
     public static String getVMVersion() {
--- a/jaxp/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -2,6 +2,6 @@
 ^dist/
 ^drop/
 ^drop_included/
-^webrev/
+^webrev
 /nbproject/private/
 ^.hgtip
--- a/jaxp/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -272,3 +272,4 @@
 2bfaf29cc90b19948938e3ef1a0983eee68806c7 jdk9-b27
 dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28
 30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29
+d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Wed Jul 05 20:00:59 2017 +0200
@@ -973,6 +973,7 @@
                         fStringBuffer2.append('\n');
                     }
                 } else if (c != -1 && XMLChar.isHighSurrogate(c)) {
+                    fStringBuffer3.clear();
                     if (scanSurrogates(fStringBuffer3)) {
                         stringBuffer.append(fStringBuffer3);
                         if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// Catalog.java - Represents OASIS Open Catalog files.
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -25,29 +19,25 @@
 
 import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
 import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
+import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
+import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
+import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
+import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
+import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
+import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader;
+import java.io.DataInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
-import java.io.DataInputStream;
-
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Locale;
 import java.util.Vector;
-
-import java.net.URL;
-import java.net.MalformedURLException;
-
 import javax.xml.parsers.SAXParserFactory;
 
-import com.sun.org.apache.xml.internal.resolver.CatalogManager;
-import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
-import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
-import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
-import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader;
-import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
-import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
-
 /**
  * Represents OASIS Open Catalog files.
  *
@@ -154,8 +144,6 @@
  *
  * <p>Additional catalogs may also be loaded with the
  * {@link #parseCatalog} method.</p>
- * </dd>
- * </dl>
  *
  * <p><b>Change Log:</b></p>
  * <dl>
@@ -823,7 +811,7 @@
       catalogCwd = FileURL.makeURL("basename");
     } catch (MalformedURLException e) {
       String userdir = SecuritySupport.getSystemProperty("user.dir");
-      userdir.replace('\\', '/');
+      userdir = userdir.replace('\\', '/');
       catalogManager.debug.message(1, "Malformed URL on cwd", userdir);
       catalogCwd = null;
     }
@@ -2113,66 +2101,113 @@
     }
   }
 
-  /**
-   * Perform character normalization on a URI reference.
-   *
-   * @param uriref The URI reference
-   * @return The normalized URI reference.
-   */
-  protected String normalizeURI(String uriref) {
-    if (uriref == null) {
-      return null;
-    }
 
-    byte[] bytes;
-    try {
-      bytes = uriref.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException uee) {
-      // this can't happen
-      catalogManager.debug.message(1, "UTF-8 is an unsupported encoding!?");
-      return uriref;
+    /**
+     * Perform character normalization on a URI reference.
+     *
+     * @param uriref The URI reference
+     * @return The normalized URI reference.
+     */
+    protected String normalizeURI(String uriref) {
+        if (uriref == null) {
+            return null;
+        }
+        final int length = uriref.length();
+        for (int i = 0; i < length; ++i) {
+            char c = uriref.charAt(i);
+            if ((c <= 0x20)    // ctrl
+                    || (c > 0x7F)  // high ascii
+                    || (c == 0x22) // "
+                    || (c == 0x3C) // <
+                    || (c == 0x3E) // >
+                    || (c == 0x5C) // \
+                    || (c == 0x5E) // ^
+                    || (c == 0x60) // `
+                    || (c == 0x7B) // {
+                    || (c == 0x7C) // |
+                    || (c == 0x7D) // }
+                    || (c == 0x7F)) {
+                return normalizeURI(uriref, i);
+            }
+        }
+        return uriref;
     }
 
-    StringBuilder newRef = new StringBuilder(bytes.length);
-    for (int count = 0; count < bytes.length; count++) {
-      int ch = bytes[count] & 0xFF;
-
-      if ((ch <= 0x20)    // ctrl
-          || (ch > 0x7F)  // high ascii
-          || (ch == 0x22) // "
-          || (ch == 0x3C) // <
-          || (ch == 0x3E) // >
-          || (ch == 0x5C) // \
-          || (ch == 0x5E) // ^
-          || (ch == 0x60) // `
-          || (ch == 0x7B) // {
-          || (ch == 0x7C) // |
-          || (ch == 0x7D) // }
-          || (ch == 0x7F)) {
-        newRef.append(encodedByte(ch));
-      } else {
-        newRef.append((char) bytes[count]);
-      }
+    /**
+     * Perform character normalization on a URI reference.
+     *
+     * @param uriref The URI reference
+     * @param index The index of the first character which requires escaping.
+     * @return The normalized URI reference.
+     */
+    private String normalizeURI(String uriref, int index) {
+        final StringBuilder buffer = new StringBuilder();
+        for (int i = 0; i < index; ++i) {
+            buffer.append(uriref.charAt(i));
+        }
+        final byte[] bytes;
+        try {
+            bytes = uriref.substring(index).getBytes("UTF-8");
+        }
+        catch (UnsupportedEncodingException uee) {
+            // this can't happen
+            catalogManager.debug.message(1, "UTF-8 is an unsupported encoding!?");
+            return uriref;
+        }
+        for (int count = 0; count < bytes.length; ++count) {
+            int ch = bytes[count] & 0xFF;
+            if ((ch <= 0x20)    // ctrl
+                    || (ch > 0x7F)  // high ascii
+                    || (ch == 0x22) // "
+                    || (ch == 0x3C) // <
+                    || (ch == 0x3E) // >
+                    || (ch == 0x5C) // \
+                    || (ch == 0x5E) // ^
+                    || (ch == 0x60) // `
+                    || (ch == 0x7B) // {
+                    || (ch == 0x7C) // |
+                    || (ch == 0x7D) // }
+                    || (ch == 0x7F)) {
+                writeEncodedByte(ch, buffer);
+            }
+            else {
+                buffer.append((char) bytes[count]);
+            }
+        }
+        return buffer.toString();
     }
 
-    return newRef.toString();
-  }
+    /**
+     * Perform %-encoding on a single byte.
+     *
+     * @param b The 8-bit integer that represents the byte. (Bytes are signed
+     *          but encoding needs to look at the bytes unsigned.)
+     * @return The %-encoded string for the byte in question.
+     */
+    protected String encodedByte(int b) {
+        StringBuilder buffer = new StringBuilder(3);
+        writeEncodedByte(b, buffer);
+        return buffer.toString();
+    }
 
-  /**
-   * Perform %-encoding on a single byte.
-   *
-   * @param b The 8-bit integer that represents th byte. (Bytes are signed
-              but encoding needs to look at the bytes unsigned.)
-   * @return The %-encoded string for the byte in question.
-   */
-  protected String encodedByte (int b) {
-    String hex = Integer.toHexString(b).toUpperCase();
-    if (hex.length() < 2) {
-      return "%0" + hex;
-    } else {
-      return "%" + hex;
+    /**
+     * Perform %-encoding on a single byte.
+     *
+     * @param b The 8-bit integer that represents the byte. (Bytes are signed
+     *          but encoding needs to look at the bytes unsigned.)
+     * @param buffer The target for the %-encoded string for the byte in question.
+     */
+    private void writeEncodedByte(int b, StringBuilder buffer) {
+        String hex = Integer.toHexString(b).toUpperCase(Locale.ENGLISH);
+        if (hex.length() < 2) {
+            buffer.append("%0");
+            buffer.append(hex);
+        }
+        else {
+            buffer.append('%');
+            buffer.append(hex);
+        }
     }
-  }
 
   // -----------------------------------------------------------------
 
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// CatalogEntry.java - Represents Catalog entries
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -53,18 +47,18 @@
  */
 public class CatalogEntry {
   /** The nextEntry is the ordinal number of the next entry type. */
-  protected static int nextEntry = 0;
+  static int nextEntry = 0;
 
   /**
    * The entryTypes vector maps catalog entry names
    * (e.g., 'BASE' or 'SYSTEM') to their type (1, 2, etc.).
    * Names are case sensitive.
    */
-  protected static Hashtable entryTypes = new Hashtable();
+  static final Hashtable entryTypes = new Hashtable();
 
   /** The entryTypes vector maps catalog entry types to the
       number of arguments they're required to have. */
-  protected static Vector entryArgs = new Vector();
+  static final Vector entryArgs = new Vector();
 
   /**
    * Adds a new catalog entry type.
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// CatalogException.java - Catalog exception
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -36,6 +30,9 @@
  *
  */
 public class CatalogException extends Exception {
+
+  private static final long serialVersionUID = 4007157171817798450L;
+
   /** A wrapper around another exception */
   public static final int WRAPPER = 1;
   /** An invalid entry */
@@ -56,8 +53,8 @@
   /**
    * The embedded exception if tunnelling, or null.
    */
-  private Exception exception = null;
-  private int exceptionType = 0;
+  private final Exception exception;
+  private final int exceptionType;
 
   /**
    * Create a new CatalogException.
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// CatalogManager.java - Access CatalogManager.properties
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -124,78 +118,78 @@
  */
 
 public class CatalogManager {
-  private static String pFiles         = "xml.catalog.files";
-  private static String pVerbosity     = "xml.catalog.verbosity";
-  private static String pPrefer        = "xml.catalog.prefer";
-  private static String pStatic        = "xml.catalog.staticCatalog";
-  private static String pAllowPI       = "xml.catalog.allowPI";
-  private static String pClassname     = "xml.catalog.className";
-  private static String pIgnoreMissing = "xml.catalog.ignoreMissing";
+    private static final String pFiles         = "xml.catalog.files";
+    private static final String pVerbosity     = "xml.catalog.verbosity";
+    private static final String pPrefer        = "xml.catalog.prefer";
+    private static final String pStatic        = "xml.catalog.staticCatalog";
+    private static final String pAllowPI       = "xml.catalog.allowPI";
+    private static final String pClassname     = "xml.catalog.className";
+    private static final String pIgnoreMissing = "xml.catalog.ignoreMissing";
 
-  /** A static CatalogManager instance for sharing */
-  private static CatalogManager staticManager = new CatalogManager();
+    /** A static CatalogManager instance for sharing */
+    private static final CatalogManager staticManager = new CatalogManager();
 
-  /** The bootstrap resolver to use when loading XML Catalogs. */
-  private BootstrapResolver bResolver = new BootstrapResolver();
+    /** The bootstrap resolver to use when loading XML Catalogs. */
+    private BootstrapResolver bResolver = new BootstrapResolver();
 
-  /** Flag to ignore missing property files and/or properties */
-  private boolean ignoreMissingProperties
+    /** Flag to ignore missing property files and/or properties */
+    private boolean ignoreMissingProperties
     = (SecuritySupport.getSystemProperty(pIgnoreMissing) != null
-       || SecuritySupport.getSystemProperty(pFiles) != null);
+    || SecuritySupport.getSystemProperty(pFiles) != null);
 
-  /** Holds the resources after they are loaded from the file. */
-  private ResourceBundle resources;
+    /** Holds the resources after they are loaded from the file. */
+    private ResourceBundle resources;
 
-  /** The name of the CatalogManager properties file. */
-  private String propertyFile = "CatalogManager.properties";
+    /** The name of the CatalogManager properties file. */
+    private String propertyFile = "CatalogManager.properties";
 
-  /** The location of the propertyFile */
-  private URL propertyFileURI = null;
+    /** The location of the propertyFile */
+    private URL propertyFileURI = null;
 
-  /** Default catalog files list. */
-  private String defaultCatalogFiles = "./xcatalog";
+    /** Default catalog files list. */
+    private String defaultCatalogFiles = "./xcatalog";
 
-  /** Current catalog files list. */
-  private String catalogFiles = null;
+    /** Current catalog files list. */
+    private String catalogFiles = null;
 
-  /** Did the catalogFiles come from the properties file? */
-  private boolean fromPropertiesFile = false;
+    /** Did the catalogFiles come from the properties file? */
+    private boolean fromPropertiesFile = false;
 
-  /** Default verbosity level if there is no property setting for it. */
-  private int defaultVerbosity = 1;
+    /** Default verbosity level if there is no property setting for it. */
+    private int defaultVerbosity = 1;
 
-  /** Current verbosity level. */
-  private Integer verbosity = null;
+    /** Current verbosity level. */
+    private Integer verbosity = null;
 
-  /** Default preference setting. */
-  private boolean defaultPreferPublic = true;
+    /** Default preference setting. */
+    private boolean defaultPreferPublic = true;
 
-  /** Current preference setting. */
-  private Boolean preferPublic = null;
+    /** Current preference setting. */
+    private Boolean preferPublic = null;
 
-  /** Default setting of the static catalog flag. */
-  private boolean defaultUseStaticCatalog = true;
+    /** Default setting of the static catalog flag. */
+    private boolean defaultUseStaticCatalog = true;
 
-  /** Current setting of the static catalog flag. */
-  private Boolean useStaticCatalog = null;
+    /** Current setting of the static catalog flag. */
+    private Boolean useStaticCatalog = null;
 
-  /** The static catalog used by this manager. */
-  private static Catalog staticCatalog = null;
+    /** The static catalog used by this manager. */
+    private static volatile Catalog staticCatalog = null;
 
-  /** Default setting of the oasisXMLCatalogPI flag. */
-  private boolean defaultOasisXMLCatalogPI = true;
+    /** Default setting of the oasisXMLCatalogPI flag. */
+    private boolean defaultOasisXMLCatalogPI = true;
 
-  /** Current setting of the oasisXMLCatalogPI flag. */
-  private Boolean oasisXMLCatalogPI = null;
+    /** Current setting of the oasisXMLCatalogPI flag. */
+    private Boolean oasisXMLCatalogPI = null;
 
-  /** Default setting of the relativeCatalogs flag. */
-  private boolean defaultRelativeCatalogs = true;
+    /** Default setting of the relativeCatalogs flag. */
+    private boolean defaultRelativeCatalogs = true;
 
-  /** Current setting of the relativeCatalogs flag. */
-  private Boolean relativeCatalogs = null;
+    /** Current setting of the relativeCatalogs flag. */
+    private Boolean relativeCatalogs = null;
 
-  /** Current catalog class name. */
-  private String catalogClassName = null;
+    /** Current catalog class name. */
+    private String catalogClassName = null;
     /**
      * Indicates whether implementation parts should use
      *   service loader (or similar).
@@ -203,26 +197,26 @@
      */
     private boolean useServicesMechanism;
 
-  /** The manager's debug object. Used for printing debugging messages.
-   *
-   * <p>This field is public so that objects that have access to this
-   * CatalogManager can use this debug object.</p>
-   */
-  public Debug debug = null;
+    /** The manager's debug object. Used for printing debugging messages.
+     *
+     * <p>This field is public so that objects that have access to this
+     * CatalogManager can use this debug object.</p>
+     */
+    public Debug debug = null;
 
-  /** Constructor. */
-  public CatalogManager() {
-    init();
-  }
+    /** Constructor. */
+    public CatalogManager() {
+        init();
+    }
 
-  /** Constructor that specifies an explicit property file. */
-  public CatalogManager(String propertyFile) {
-    this.propertyFile = propertyFile;
-    init();
+    /** Constructor that specifies an explicit property file. */
+    public CatalogManager(String propertyFile) {
+        this.propertyFile = propertyFile;
+        init();
   }
 
   private void init() {
-    debug = new Debug();
+        debug = new Debug();
     // Note that we don't setDebug() here; we do that lazily. Either the
     // user will set it explicitly, or we'll do it automagically if they
     // read from the propertyFile for some other reason. That way, there's
@@ -231,616 +225,638 @@
     if (System.getSecurityManager() == null) {
         useServicesMechanism = true;
     }
-  }
-  /** Set the bootstrap resolver.*/
-  public void setBootstrapResolver(BootstrapResolver resolver) {
-    bResolver = resolver;
-  }
+        // Make sure verbosity is set by xml.catalog.verbosity sysprop
+        // setting, if defined.
+        queryVerbosityFromSysProp();
+    }
 
-  /** Get the bootstrap resolver.*/
-  public BootstrapResolver getBootstrapResolver() {
-    return bResolver;
-  }
+    /** Set the bootstrap resolver
+     * @param resolver the bootstrap resolver
+     */
+    public void setBootstrapResolver(BootstrapResolver resolver) {
+        bResolver = resolver;
+    }
 
-  /**
-   * Load the properties from the propertyFile and build the
-   * resources from it.
-   */
-  private synchronized void readProperties() {
-    try {
-      propertyFileURI = CatalogManager.class.getResource("/"+propertyFile);
-      InputStream in =
-        CatalogManager.class.getResourceAsStream("/"+propertyFile);
-      if (in==null) {
-        if (!ignoreMissingProperties) {
-          System.err.println("Cannot find "+propertyFile);
-          // there's no reason to give this warning more than once
-          ignoreMissingProperties = true;
+    /** Get the bootstrap resolver
+     * @return the bootstrap resolver
+     */
+    public BootstrapResolver getBootstrapResolver() {
+        return bResolver;
+    }
+
+    /** Query system property for verbosity level. */
+    private void queryVerbosityFromSysProp() {
+        String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
+        if (verbStr != null) {
+            try {
+                int verb = Integer.parseInt(verbStr.trim());
+                verbosity = new Integer(verb);
+                debug.setDebug(verb);
+            } catch (Exception e) {
+                System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
+            }
         }
-        return;
-      }
-      resources = new PropertyResourceBundle(in);
-    } catch (MissingResourceException mre) {
-      if (!ignoreMissingProperties) {
-        System.err.println("Cannot read "+propertyFile);
-      }
-    } catch (java.io.IOException e) {
-      if (!ignoreMissingProperties) {
-        System.err.println("Failure trying to read "+propertyFile);
-      }
     }
 
-    // This is a bit of a hack. After we've successfully read the properties,
-    // use them to set the default debug level, if the user hasn't already set
-    // the default debug level.
-    if (verbosity == null) {
-      try {
-        String verbStr = resources.getString("verbosity");
-        int verb = Integer.parseInt(verbStr.trim());
-        debug.setDebug(verb);
-        verbosity = new Integer(verb);
-      } catch (Exception e) {
-        // nop
-      }
-    }
-  }
-
-  /**
-   * Allow access to the static CatalogManager
-   */
-  public static CatalogManager getStaticManager() {
-    return staticManager;
-  }
-
-  /**
-   * How are missing properties handled?
-   *
-   * <p>If true, missing or unreadable property files will
-   * not be reported. Otherwise, a message will be sent to System.err.
-   * </p>
-   */
-  public boolean getIgnoreMissingProperties() {
-    return ignoreMissingProperties;
-  }
+    /**
+     * Load the properties from the propertyFile and build the
+     * resources from it.
+     */
+    private synchronized void readProperties() {
+        try {
+            propertyFileURI = CatalogManager.class.getResource("/"+propertyFile);
+            InputStream in =
+                    CatalogManager.class.getResourceAsStream("/"+propertyFile);
+            if (in==null) {
+                if (!ignoreMissingProperties) {
+                    System.err.println("Cannot find "+propertyFile);
+                    // there's no reason to give this warning more than once
+                    ignoreMissingProperties = true;
+                }
+                return;
+            }
+            resources = new PropertyResourceBundle(in);
+        } catch (MissingResourceException mre) {
+            if (!ignoreMissingProperties) {
+                System.err.println("Cannot read "+propertyFile);
+            }
+        } catch (java.io.IOException e) {
+            if (!ignoreMissingProperties) {
+                System.err.println("Failure trying to read "+propertyFile);
+            }
+        }
 
-  /**
-   * How should missing properties be handled?
-   *
-   * <p>If ignore is true, missing or unreadable property files will
-   * not be reported. Otherwise, a message will be sent to System.err.
-   * </p>
-   */
-  public void setIgnoreMissingProperties(boolean ignore) {
-    ignoreMissingProperties = ignore;
-  }
-
-  /**
-   * How are missing properties handled?
-   *
-   * <p>If ignore is true, missing or unreadable property files will
-   * not be reported. Otherwise, a message will be sent to System.err.
-   * </p>
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public void ignoreMissingProperties(boolean ignore) {
-    setIgnoreMissingProperties(ignore);
-  }
-
-  /**
-   * Obtain the verbosity setting from the properties.
-   *
-   * @return The verbosity level from the propertyFile or the
-   * defaultVerbosity.
-   */
-  private int queryVerbosity () {
-    String defaultVerbStr = Integer.toString(defaultVerbosity);
-
-    String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
-
-    if (verbStr == null) {
-      if (resources==null) readProperties();
-      if (resources != null) {
-        try {
-          verbStr = resources.getString("verbosity");
-        } catch (MissingResourceException e) {
-          verbStr = defaultVerbStr;
+        // This is a bit of a hack. After we've successfully read the properties,
+        // use them to set the default debug level, if the user hasn't already set
+        // the default debug level.
+        if (verbosity == null) {
+            try {
+                String verbStr = resources.getString("verbosity");
+                int verb = Integer.parseInt(verbStr.trim());
+                debug.setDebug(verb);
+                verbosity = new Integer(verb);
+            } catch (Exception e) {
+                // nop
+            }
         }
-      } else {
-        verbStr = defaultVerbStr;
-      }
     }
 
-    int verb = defaultVerbosity;
+    /**
+     * Allow access to the static CatalogManager
+     */
+    public static CatalogManager getStaticManager() {
+        return staticManager;
+    }
 
-    try {
-      verb = Integer.parseInt(verbStr.trim());
-    } catch (Exception e) {
-      System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
+    /**
+     * How are missing properties handled?
+     *
+     * <p>If true, missing or unreadable property files will
+     * not be reported. Otherwise, a message will be sent to System.err.
+     * </p>
+     */
+    public boolean getIgnoreMissingProperties() {
+        return ignoreMissingProperties;
     }
 
-    // This is a bit of a hack. After we've successfully got the verbosity,
-    // we have to use it to set the default debug level,
-    // if the user hasn't already set the default debug level.
-    if (verbosity == null) {
-      debug.setDebug(verb);
-      verbosity = new Integer(verb);
+    /**
+     * How should missing properties be handled?
+     *
+     * <p>If ignore is true, missing or unreadable property files will
+     * not be reported. Otherwise, a message will be sent to System.err.
+     * </p>
+     */
+    public void setIgnoreMissingProperties(boolean ignore) {
+        ignoreMissingProperties = ignore;
+    }
+
+    /**
+     * How are missing properties handled?
+     *
+     * <p>If ignore is true, missing or unreadable property files will
+     * not be reported. Otherwise, a message will be sent to System.err.
+     * </p>
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public void ignoreMissingProperties(boolean ignore) {
+        setIgnoreMissingProperties(ignore);
     }
 
-    return verb;
-  }
+    /**
+     * Obtain the verbosity setting from the properties.
+     *
+     * @return The verbosity level from the propertyFile or the
+     * defaultVerbosity.
+     */
+    private int queryVerbosity () {
+        String defaultVerbStr = Integer.toString(defaultVerbosity);
+
+        String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
 
-  /**
-   * What is the current verbosity?
-   */
-  public int getVerbosity() {
-    if (verbosity == null) {
-      verbosity = new Integer(queryVerbosity());
+        if (verbStr == null) {
+            if (resources==null) readProperties();
+            if (resources != null) {
+                try {
+                    verbStr = resources.getString("verbosity");
+                } catch (MissingResourceException e) {
+                    verbStr = defaultVerbStr;
+                }
+            } else {
+                verbStr = defaultVerbStr;
+            }
+        }
+
+        int verb = defaultVerbosity;
+
+        try {
+            verb = Integer.parseInt(verbStr.trim());
+        } catch (Exception e) {
+            System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
+        }
+
+        // This is a bit of a hack. After we've successfully got the verbosity,
+        // we have to use it to set the default debug level,
+        // if the user hasn't already set the default debug level.
+        if (verbosity == null) {
+            debug.setDebug(verb);
+            verbosity = new Integer(verb);
+        }
+
+        return verb;
     }
 
-    return verbosity.intValue();
-  }
-
-  /**
-   * Set the current verbosity.
-   */
-  public void setVerbosity (int verbosity) {
-    this.verbosity = new Integer(verbosity);
-    debug.setDebug(verbosity);
-  }
+    /**
+     * What is the current verbosity?
+     */
+    public int getVerbosity() {
+        if (verbosity == null) {
+            verbosity = new Integer(queryVerbosity());
+        }
 
-  /**
-   * What is the current verbosity?
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public int verbosity () {
-    return getVerbosity();
-  }
+        return verbosity.intValue();
+    }
 
-  /**
-   * Obtain the relativeCatalogs setting from the properties.
-   *
-   * @return The relativeCatalogs setting from the propertyFile or the
-   * defaultRelativeCatalogs.
-   */
-  private boolean queryRelativeCatalogs () {
-    if (resources==null) readProperties();
-
-    if (resources==null) return defaultRelativeCatalogs;
+    /**
+     * Set the current verbosity.
+     */
+    public void setVerbosity (int verbosity) {
+        this.verbosity = new Integer(verbosity);
+        debug.setDebug(verbosity);
+    }
 
-    try {
-      String allow = resources.getString("relative-catalogs");
-      return (allow.equalsIgnoreCase("true")
-              || allow.equalsIgnoreCase("yes")
-              || allow.equalsIgnoreCase("1"));
-    } catch (MissingResourceException e) {
-      return defaultRelativeCatalogs;
+    /**
+     * What is the current verbosity?
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public int verbosity () {
+        return getVerbosity();
     }
-  }
 
-  /**
-   * Get the relativeCatalogs setting.
-   *
-   * <p>This property is used when the catalogFiles property is
-   * interrogated. If true, then relative catalog entry file names
-   * are returned. If false, relative catalog entry file names are
-   * made absolute with respect to the properties file before returning
-   * them.</p>
-   *
-   * <p>This property <emph>only applies</emph> when the catalog files
-   * come from a properties file. If they come from a system property or
-   * the default list, they are never considered relative. (What would
-   * they be relative to?)</p>
-   *
-   * <p>In the properties, a value of 'yes', 'true', or '1' is considered
-   * true, anything else is false.</p>
-   *
-   * @return The relativeCatalogs setting from the propertyFile or the
-   * defaultRelativeCatalogs.
-   */
-  public boolean getRelativeCatalogs () {
-    if (relativeCatalogs == null) {
-      relativeCatalogs = new Boolean(queryRelativeCatalogs());
+    /**
+     * Obtain the relativeCatalogs setting from the properties.
+     *
+     * @return The relativeCatalogs setting from the propertyFile or the
+     * defaultRelativeCatalogs.
+     */
+    private boolean queryRelativeCatalogs () {
+        if (resources==null) readProperties();
+
+        if (resources==null) return defaultRelativeCatalogs;
+
+        try {
+            String allow = resources.getString("relative-catalogs");
+            return (allow.equalsIgnoreCase("true")
+                    || allow.equalsIgnoreCase("yes")
+                    || allow.equalsIgnoreCase("1"));
+        } catch (MissingResourceException e) {
+            return defaultRelativeCatalogs;
+        }
     }
 
-    return relativeCatalogs.booleanValue();
-  }
-
-  /**
-   * Set the relativeCatalogs setting.
-   *
-   * @see #getRelativeCatalogs()
-   */
-  public void setRelativeCatalogs (boolean relative) {
-    relativeCatalogs = new Boolean(relative);
-  }
-
-  /**
-   * Get the relativeCatalogs setting.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public boolean relativeCatalogs () {
-    return getRelativeCatalogs();
-  }
+    /**
+     * Get the relativeCatalogs setting.
+     *
+     * <p>This property is used when the catalogFiles property is
+     * interrogated. If true, then relative catalog entry file names
+     * are returned. If false, relative catalog entry file names are
+     * made absolute with respect to the properties file before returning
+     * them.</p>
+     *
+     * <p>This property <emph>only applies</emph> when the catalog files
+     * come from a properties file. If they come from a system property or
+     * the default list, they are never considered relative. (What would
+     * they be relative to?)</p>
+     *
+     * <p>In the properties, a value of 'yes', 'true', or '1' is considered
+     * true, anything else is false.</p>
+     *
+     * @return The relativeCatalogs setting from the propertyFile or the
+     * defaultRelativeCatalogs.
+     */
+    public boolean getRelativeCatalogs () {
+        if (relativeCatalogs == null) {
+            relativeCatalogs = queryRelativeCatalogs() ? Boolean.TRUE : Boolean.FALSE;
+        }
 
-  /**
-   * Obtain the list of catalog files from the properties.
-   *
-   * @return A semicolon delimited list of catlog file URIs
-   */
-  private String queryCatalogFiles () {
-    String catalogList = SecuritySupport.getSystemProperty(pFiles);
-    fromPropertiesFile = false;
+        return relativeCatalogs.booleanValue();
+    }
 
-    if (catalogList == null) {
-      if (resources == null) readProperties();
-      if (resources != null) {
-        try {
-          catalogList = resources.getString("catalogs");
-          fromPropertiesFile = true;
-        } catch (MissingResourceException e) {
-          System.err.println(propertyFile + ": catalogs not found.");
-          catalogList = null;
-        }
-      }
+    /**
+     * Set the relativeCatalogs setting.
+     *
+     * @see #getRelativeCatalogs()
+     */
+    public void setRelativeCatalogs (boolean relative) {
+        relativeCatalogs = relative ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
+     * Get the relativeCatalogs setting.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public boolean relativeCatalogs () {
+        return getRelativeCatalogs();
     }
 
-    if (catalogList == null) {
-      catalogList = defaultCatalogFiles;
+    /**
+     * Obtain the list of catalog files from the properties.
+     *
+     * @return A semicolon delimited list of catlog file URIs
+     */
+    private String queryCatalogFiles () {
+        String catalogList = SecuritySupport.getSystemProperty(pFiles);
+        fromPropertiesFile = false;
+
+        if (catalogList == null) {
+            if (resources == null) readProperties();
+            if (resources != null) {
+                try {
+                    catalogList = resources.getString("catalogs");
+                    fromPropertiesFile = true;
+                } catch (MissingResourceException e) {
+                    System.err.println(propertyFile + ": catalogs not found.");
+                    catalogList = null;
+                }
+            }
+        }
+
+        if (catalogList == null) {
+            catalogList = defaultCatalogFiles;
+        }
+
+        return catalogList;
     }
 
-    return catalogList;
-  }
-
-  /**
-   * Return the current list of catalog files.
-   *
-   * @return A vector of the catalog file names or null if no catalogs
-   * are available in the properties.
-   */
-  public Vector getCatalogFiles() {
-    if (catalogFiles == null) {
-      catalogFiles = queryCatalogFiles();
-    }
+    /**
+     * Return the current list of catalog files.
+     *
+     * @return A vector of the catalog file names or null if no catalogs
+     * are available in the properties.
+     */
+    public Vector getCatalogFiles() {
+        if (catalogFiles == null) {
+            catalogFiles = queryCatalogFiles();
+        }
 
-    StringTokenizer files = new StringTokenizer(catalogFiles, ";");
-    Vector catalogs = new Vector();
-    while (files.hasMoreTokens()) {
-      String catalogFile = files.nextToken();
-      URL absURI = null;
+        StringTokenizer files = new StringTokenizer(catalogFiles, ";");
+        Vector catalogs = new Vector();
+        while (files.hasMoreTokens()) {
+            String catalogFile = files.nextToken();
+            URL absURI = null;
 
-      if (fromPropertiesFile && !relativeCatalogs()) {
-        try {
-          absURI = new URL(propertyFileURI, catalogFile);
-          catalogFile = absURI.toString();
-        } catch (MalformedURLException mue) {
-          absURI = null;
+            if (fromPropertiesFile && !relativeCatalogs()) {
+                try {
+                    absURI = new URL(propertyFileURI, catalogFile);
+                    catalogFile = absURI.toString();
+                } catch (MalformedURLException mue) {
+                    absURI = null;
+                }
+            }
+
+            catalogs.add(catalogFile);
         }
-      }
 
-      catalogs.add(catalogFile);
+        return catalogs;
     }
 
-    return catalogs;
-  }
-
-  /**
-   * Set the list of catalog files.
-   */
-  public void setCatalogFiles(String fileList) {
-    catalogFiles = fileList;
-    fromPropertiesFile = false;
-  }
+    /**
+     * Set the list of catalog files.
+     */
+    public void setCatalogFiles(String fileList) {
+        catalogFiles = fileList;
+        fromPropertiesFile = false;
+    }
 
-  /**
-   * Return the current list of catalog files.
-   *
-   * @return A vector of the catalog file names or null if no catalogs
-   * are available in the properties.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public Vector catalogFiles() {
-    return getCatalogFiles();
-  }
-
-  /**
-   * Obtain the preferPublic setting from the properties.
-   *
-   * <p>In the properties, a value of 'public' is true,
-   * anything else is false.</p>
-   *
-   * @return True if prefer is public or the
-   * defaultPreferSetting.
-   */
-  private boolean queryPreferPublic () {
-    String prefer = SecuritySupport.getSystemProperty(pPrefer);
-
-    if (prefer == null) {
-      if (resources==null) readProperties();
-      if (resources==null) return defaultPreferPublic;
-      try {
-        prefer = resources.getString("prefer");
-      } catch (MissingResourceException e) {
-        return defaultPreferPublic;
-      }
+    /**
+     * Return the current list of catalog files.
+     *
+     * @return A vector of the catalog file names or null if no catalogs
+     * are available in the properties.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public Vector catalogFiles() {
+        return getCatalogFiles();
     }
 
-    if (prefer == null) {
-      return defaultPreferPublic;
+    /**
+     * Obtain the preferPublic setting from the properties.
+     *
+     * <p>In the properties, a value of 'public' is true,
+     * anything else is false.</p>
+     *
+     * @return True if prefer is public or the
+     * defaultPreferSetting.
+     */
+    private boolean queryPreferPublic () {
+        String prefer = SecuritySupport.getSystemProperty(pPrefer);
+
+        if (prefer == null) {
+            if (resources==null) readProperties();
+            if (resources==null) return defaultPreferPublic;
+            try {
+                prefer = resources.getString("prefer");
+            } catch (MissingResourceException e) {
+                return defaultPreferPublic;
+            }
+        }
+
+        if (prefer == null) {
+            return defaultPreferPublic;
+        }
+
+        return (prefer.equalsIgnoreCase("public"));
+    }
+
+    /**
+     * Return the current prefer public setting.
+     *
+     * @return True if public identifiers are preferred.
+     */
+    public boolean getPreferPublic () {
+        if (preferPublic == null) {
+            preferPublic = queryPreferPublic() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return preferPublic.booleanValue();
+    }
+
+    /**
+     * Set the prefer public setting.
+     */
+    public void setPreferPublic (boolean preferPublic) {
+        this.preferPublic = preferPublic ? Boolean.TRUE : Boolean.FALSE;
     }
 
-    return (prefer.equalsIgnoreCase("public"));
-  }
-
-  /**
-   * Return the current prefer public setting.
-   *
-   * @return True if public identifiers are preferred.
-   */
-  public boolean getPreferPublic () {
-    if (preferPublic == null) {
-      preferPublic = new Boolean(queryPreferPublic());
-    }
-    return preferPublic.booleanValue();
-  }
-
-  /**
-   * Set the prefer public setting.
-   */
-  public void setPreferPublic (boolean preferPublic) {
-    this.preferPublic = new Boolean(preferPublic);
-  }
-
-  /**
-   * Return the current prefer public setting.
-   *
-   * @return True if public identifiers are preferred.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public boolean preferPublic () {
-    return getPreferPublic();
-  }
-
-  /**
-   * Obtain the static-catalog setting from the properties.
-   *
-   * <p>In the properties, a value of 'yes', 'true', or '1' is considered
-   * true, anything else is false.</p>
-   *
-   * @return The static-catalog setting from the propertyFile or the
-   * defaultUseStaticCatalog.
-   */
-  private boolean queryUseStaticCatalog () {
-    String staticCatalog = SecuritySupport.getSystemProperty(pStatic);
-
-    if (staticCatalog == null) {
-      if (resources==null) readProperties();
-      if (resources==null) return defaultUseStaticCatalog;
-      try {
-        staticCatalog = resources.getString("static-catalog");
-      } catch (MissingResourceException e) {
-        return defaultUseStaticCatalog;
-      }
+    /**
+     * Return the current prefer public setting.
+     *
+     * @return True if public identifiers are preferred.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public boolean preferPublic () {
+        return getPreferPublic();
     }
 
-    if (staticCatalog == null) {
-      return defaultUseStaticCatalog;
-    }
+    /**
+     * Obtain the static-catalog setting from the properties.
+     *
+     * <p>In the properties, a value of 'yes', 'true', or '1' is considered
+     * true, anything else is false.</p>
+     *
+     * @return The static-catalog setting from the propertyFile or the
+     * defaultUseStaticCatalog.
+     */
+    private boolean queryUseStaticCatalog () {
+        String staticCatalog = SecuritySupport.getSystemProperty(pStatic);
 
-    return (staticCatalog.equalsIgnoreCase("true")
-            || staticCatalog.equalsIgnoreCase("yes")
-            || staticCatalog.equalsIgnoreCase("1"));
-  }
+        if (staticCatalog == null) {
+            if (resources==null) readProperties();
+            if (resources==null) return defaultUseStaticCatalog;
+            try {
+                staticCatalog = resources.getString("static-catalog");
+            } catch (MissingResourceException e) {
+                return defaultUseStaticCatalog;
+            }
+        }
 
-  /**
-   * Get the current use static catalog setting.
-   */
-  public boolean getUseStaticCatalog() {
-    if (useStaticCatalog == null) {
-      useStaticCatalog = new Boolean(queryUseStaticCatalog());
+        if (staticCatalog == null) {
+            return defaultUseStaticCatalog;
+        }
+
+        return (staticCatalog.equalsIgnoreCase("true")
+                || staticCatalog.equalsIgnoreCase("yes")
+                || staticCatalog.equalsIgnoreCase("1"));
     }
 
-    return useStaticCatalog.booleanValue();
-  }
+    /**
+     * Get the current use static catalog setting.
+     */
+    public boolean getUseStaticCatalog() {
+        if (useStaticCatalog == null) {
+            useStaticCatalog = queryUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
+        }
 
-  /**
-   * Set the use static catalog setting.
-   */
-  public void setUseStaticCatalog(boolean useStatic) {
-    useStaticCatalog = new Boolean(useStatic);
-  }
+        return useStaticCatalog.booleanValue();
+    }
 
-  /**
-   * Get the current use static catalog setting.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public boolean staticCatalog() {
-    return getUseStaticCatalog();
-  }
+    /**
+     * Set the use static catalog setting.
+     */
+    public void setUseStaticCatalog(boolean useStatic) {
+        useStaticCatalog = useStatic ? Boolean.TRUE : Boolean.FALSE;
+    }
 
-  /**
-   * Get a new catalog instance.
-   *
-   * This method always returns a new instance of the underlying catalog class.
-   */
-  public Catalog getPrivateCatalog() {
-    Catalog catalog = staticCatalog;
-
-    if (useStaticCatalog == null) {
-      useStaticCatalog = new Boolean(getUseStaticCatalog());
+    /**
+     * Get the current use static catalog setting.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public boolean staticCatalog() {
+        return getUseStaticCatalog();
     }
 
-    if (catalog == null || !useStaticCatalog.booleanValue()) {
-
-      try {
-        String catalogClassName = getCatalogClassName();
+    /**
+     * Get a new catalog instance.
+     *
+     * This method always returns a new instance of the underlying catalog class.
+     */
+    public Catalog getPrivateCatalog() {
+        Catalog catalog = staticCatalog;
 
-        if (catalogClassName == null) {
-          catalog = new Catalog();
-        } else {
-          try {
-            catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance();
-          } catch (ClassNotFoundException cnfe) {
-            debug.message(1,"Catalog class named '"
-                          + catalogClassName
-                          + "' could not be found. Using default.");
-            catalog = new Catalog();
-          } catch (ClassCastException cnfe) {
-            debug.message(1,"Class named '"
-                          + catalogClassName
-                          + "' is not a Catalog. Using default.");
-            catalog = new Catalog();
-          }
+        if (useStaticCatalog == null) {
+            useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
         }
 
-        catalog.setCatalogManager(this);
-        catalog.setupReaders();
-        catalog.loadSystemCatalogs();
-      } catch (Exception ex) {
-        ex.printStackTrace();
-      }
+        if (catalog == null || !useStaticCatalog.booleanValue()) {
+
+            try {
+                String catalogClassName = getCatalogClassName();
 
-      if (useStaticCatalog.booleanValue()) {
-        staticCatalog = catalog;
-      }
+                if (catalogClassName == null) {
+                    catalog = new Catalog();
+                } else {
+                    try {
+                        catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance();
+                    } catch (ClassNotFoundException cnfe) {
+                        debug.message(1,"Catalog class named '"
+                                + catalogClassName
+                                + "' could not be found. Using default.");
+                        catalog = new Catalog();
+                    } catch (ClassCastException cnfe) {
+                        debug.message(1,"Class named '"
+                                + catalogClassName
+                                + "' is not a Catalog. Using default.");
+                        catalog = new Catalog();
+                    }
+                }
+
+                catalog.setCatalogManager(this);
+                catalog.setupReaders();
+                catalog.loadSystemCatalogs();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+
+            if (useStaticCatalog.booleanValue()) {
+                staticCatalog = catalog;
+            }
+        }
+
+        return catalog;
     }
 
-    return catalog;
-  }
-
-  /**
-   * Get a catalog instance.
-   *
-   * If this manager uses static catalogs, the same static catalog will
-   * always be returned. Otherwise a new catalog will be returned.
-   */
-  public Catalog getCatalog() {
-    Catalog catalog = staticCatalog;
-
-    if (useStaticCatalog == null) {
-      useStaticCatalog = new Boolean(getUseStaticCatalog());
-    }
-
-    if (catalog == null || !useStaticCatalog.booleanValue()) {
-      catalog = getPrivateCatalog();
-      if (useStaticCatalog.booleanValue()) {
-        staticCatalog = catalog;
-      }
-    }
+    /**
+     * Get a catalog instance.
+     *
+     * If this manager uses static catalogs, the same static catalog will
+     * always be returned. Otherwise a new catalog will be returned.
+     */
+    public Catalog getCatalog() {
+        Catalog catalog = staticCatalog;
 
-    return catalog;
-  }
+        if (useStaticCatalog == null) {
+            useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
+        }
 
-  /**
-   * <p>Obtain the oasisXMLCatalogPI setting from the properties.</p>
-   *
-   * <p>In the properties, a value of 'yes', 'true', or '1' is considered
-   * true, anything else is false.</p>
-   *
-   * @return The oasisXMLCatalogPI setting from the propertyFile or the
-   * defaultOasisXMLCatalogPI.
-   */
-  public boolean queryAllowOasisXMLCatalogPI () {
-    String allow = SecuritySupport.getSystemProperty(pAllowPI);
+        if (catalog == null || !useStaticCatalog.booleanValue()) {
+            catalog = getPrivateCatalog();
+            if (useStaticCatalog.booleanValue()) {
+                staticCatalog = catalog;
+            }
+        }
 
-    if (allow == null) {
-      if (resources==null) readProperties();
-      if (resources==null) return defaultOasisXMLCatalogPI;
-      try {
-        allow = resources.getString("allow-oasis-xml-catalog-pi");
-      } catch (MissingResourceException e) {
-        return defaultOasisXMLCatalogPI;
-      }
+        return catalog;
     }
 
-    if (allow == null) {
-      return defaultOasisXMLCatalogPI;
+    /**
+     * <p>Obtain the oasisXMLCatalogPI setting from the properties.</p>
+     *
+     * <p>In the properties, a value of 'yes', 'true', or '1' is considered
+     * true, anything else is false.</p>
+     *
+     * @return The oasisXMLCatalogPI setting from the propertyFile or the
+     * defaultOasisXMLCatalogPI.
+     */
+    public boolean queryAllowOasisXMLCatalogPI () {
+        String allow = SecuritySupport.getSystemProperty(pAllowPI);
+
+        if (allow == null) {
+            if (resources==null) readProperties();
+            if (resources==null) return defaultOasisXMLCatalogPI;
+            try {
+                allow = resources.getString("allow-oasis-xml-catalog-pi");
+            } catch (MissingResourceException e) {
+                return defaultOasisXMLCatalogPI;
+            }
+        }
+
+        if (allow == null) {
+            return defaultOasisXMLCatalogPI;
+        }
+
+        return (allow.equalsIgnoreCase("true")
+                || allow.equalsIgnoreCase("yes")
+                || allow.equalsIgnoreCase("1"));
     }
 
-    return (allow.equalsIgnoreCase("true")
-            || allow.equalsIgnoreCase("yes")
-            || allow.equalsIgnoreCase("1"));
-  }
+    /**
+     * Get the current XML Catalog PI setting.
+     */
+    public boolean getAllowOasisXMLCatalogPI () {
+        if (oasisXMLCatalogPI == null) {
+            oasisXMLCatalogPI = queryAllowOasisXMLCatalogPI() ? Boolean.TRUE : Boolean.FALSE;
+        }
 
-  /**
-   * Get the current XML Catalog PI setting.
-   */
-  public boolean getAllowOasisXMLCatalogPI () {
-    if (oasisXMLCatalogPI == null) {
-      oasisXMLCatalogPI = new Boolean(queryAllowOasisXMLCatalogPI());
+        return oasisXMLCatalogPI.booleanValue();
+    }
+
+    public boolean useServicesMechanism() {
+        return useServicesMechanism;
+    }
+    /**
+     * Set the XML Catalog PI setting
+     */
+    public void setAllowOasisXMLCatalogPI(boolean allowPI) {
+        oasisXMLCatalogPI = allowPI ? Boolean.TRUE : Boolean.FALSE;
     }
 
-    return oasisXMLCatalogPI.booleanValue();
-  }
-
-  public boolean useServicesMechanism() {
-      return useServicesMechanism;
-  }
-  /**
-   * Set the XML Catalog PI setting
-   */
-  public void setAllowOasisXMLCatalogPI(boolean allowPI) {
-    oasisXMLCatalogPI = new Boolean(allowPI);
-  }
-
-  /**
-   * Get the current XML Catalog PI setting.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public boolean allowOasisXMLCatalogPI() {
-    return getAllowOasisXMLCatalogPI();
-  }
-
-  /**
-   * Obtain the Catalog class name setting from the properties.
-   *
-   */
-  public String queryCatalogClassName () {
-    String className = SecuritySupport.getSystemProperty(pClassname);
-
-    if (className == null) {
-      if (resources==null) readProperties();
-      if (resources==null) return null;
-      try {
-        return resources.getString("catalog-class-name");
-      } catch (MissingResourceException e) {
-        return null;
-      }
+    /**
+     * Get the current XML Catalog PI setting.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public boolean allowOasisXMLCatalogPI() {
+        return getAllowOasisXMLCatalogPI();
     }
 
-    return className;
-  }
+    /**
+     * Obtain the Catalog class name setting from the properties.
+     *
+     */
+    public String queryCatalogClassName () {
+        String className = SecuritySupport.getSystemProperty(pClassname);
 
-  /**
-   * Get the current Catalog class name.
-   */
-  public String getCatalogClassName() {
-    if (catalogClassName == null) {
-      catalogClassName = queryCatalogClassName();
+        if (className == null) {
+            if (resources==null) readProperties();
+            if (resources==null) return null;
+            try {
+                return resources.getString("catalog-class-name");
+            } catch (MissingResourceException e) {
+                return null;
+            }
+        }
+
+        return className;
     }
 
-    return catalogClassName;
-  }
+    /**
+     * Get the current Catalog class name.
+     */
+    public String getCatalogClassName() {
+        if (catalogClassName == null) {
+            catalogClassName = queryCatalogClassName();
+        }
 
-  /**
-   * Set the Catalog class name.
-   */
-  public void setCatalogClassName(String className) {
-    catalogClassName = className;
-  }
+        return catalogClassName;
+    }
 
-  /**
-   * Get the current Catalog class name.
-   *
-   * @deprecated No longer static; use get/set methods.
-   */
-  public String catalogClassName() {
-    return getCatalogClassName();
-  }
+    /**
+     * Set the Catalog class name.
+     */
+    public void setCatalogClassName(String className) {
+        catalogClassName = className;
+    }
+
+    /**
+     * Get the current Catalog class name.
+     *
+     * @deprecated No longer static; use get/set methods.
+     */
+    public String catalogClassName() {
+        return getCatalogClassName();
+    }
 }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// Resolver.java - Represents an extension of OASIS Open Catalog files.
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -94,7 +88,7 @@
 
     SAXCatalogReader saxReader = new SAXCatalogReader(spf);
 
-    saxReader.setCatalogParser(null, "XMLCatalog",
+    saxReader.setCatalogParser(null, "XCatalog",
                                "com.sun.org.apache.xml.internal.resolver.readers.XCatalogReader");
 
     saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName,
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// BootstrapResolver.java - Resolve entities and URIs internally
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -65,14 +59,17 @@
   /** System identifier for OASIS XML Catalog files. */
   public static final String xmlCatalogSysId = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd";
 
+  /** Public identifier for legacy Apache XCatalog files.  There is no official system identifier for XCatalog files. */
+  public static final String xCatalogPubId = "-//DTD XCatalog//EN";
+
   /** Private hash used for public identifiers. */
-  private Hashtable publicMap = new Hashtable();
+  private final Hashtable publicMap = new Hashtable();
 
   /** Private hash used for system identifiers. */
-  private Hashtable systemMap = new Hashtable();
+  private final Hashtable systemMap = new Hashtable();
 
   /** Private hash used for URIs. */
-  private Hashtable uriMap = new Hashtable();
+  private final Hashtable uriMap = new Hashtable();
 
   /** Constructor. */
   public BootstrapResolver() {
@@ -91,6 +88,11 @@
     if (url != null) {
       uriMap.put(xmlCatalogXSD, url.toString());
     }
+
+    url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/xcatalog.dtd");
+    if (url != null) {
+      publicMap.put(xCatalogPubId, url.toString());
+    }
   }
 
   /** SAX resolveEntity API. */
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// Debug.java - Print debug messages
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// FileURL.java - Construct a file: scheme URL
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// Namespaces.java - Analyze namespace nodes in a DOM tree
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -47,8 +41,9 @@
         String name = element.getTagName();
         String prefix = "";
 
-        if (name.indexOf(':') > 0) {
-            prefix = name.substring(0, name.indexOf(':'));
+        final int indexOfColon = name.indexOf(':');
+        if (indexOfColon > 0) {
+            prefix = name.substring(0, indexOfColon);
         }
 
         return prefix;
@@ -64,8 +59,9 @@
     public static String getLocalName(Element element) {
         String name = element.getTagName();
 
-        if (name.indexOf(':') > 0) {
-            name = name.substring(name.indexOf(':')+1);
+        final int indexOfColon = name.indexOf(':');
+        if (indexOfColon > 0) {
+            name = name.substring(indexOfColon + 1);
         }
 
         return name;
@@ -85,7 +81,7 @@
             return null;
         }
 
-        if (prefix.equals("")) {
+        if (prefix.length() == 0) {
             if (((Element) node).hasAttribute("xmlns")) {
                 return ((Element) node).getAttribute("xmlns");
             }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// PublicId.java - Information about public identifiers
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -34,7 +28,8 @@
  *
  */
 public abstract class PublicId {
-  protected PublicId() { }
+
+  protected PublicId() {}
 
   /**
    * Normalize a public identifier.
@@ -58,18 +53,17 @@
    * @return The normalized identifier.
    */
   public static String normalize(String publicId) {
-    String normal = publicId.replace('\t', ' ');
-    normal = normal.replace('\r', ' ');
-    normal = normal.replace('\n', ' ');
-    normal = normal.trim();
+      String normal = publicId.replace('\t', ' ');
+      normal = normal.replace('\r', ' ');
+      normal = normal.replace('\n', ' ');
+      normal = normal.trim();
 
-    int pos;
+      int pos;
 
-    while ((pos = normal.indexOf("  ")) >= 0) {
-      normal = normal.substring(0, pos) + normal.substring(pos+1);
-    }
-
-    return normal;
+      while ((pos = normal.indexOf("  ")) >= 0) {
+          normal = normal.substring(0, pos) + normal.substring(pos+1);
+      }
+      return normal;
   }
 
   /**
@@ -83,21 +77,24 @@
    * @return The normalized identifier.
    */
   public static String encodeURN(String publicId) {
-    String urn = PublicId.normalize(publicId);
+      String urn = PublicId.normalize(publicId);
 
-    urn = PublicId.stringReplace(urn, "%", "%25");
-    urn = PublicId.stringReplace(urn, ";", "%3B");
-    urn = PublicId.stringReplace(urn, "'", "%27");
-    urn = PublicId.stringReplace(urn, "?", "%3F");
-    urn = PublicId.stringReplace(urn, "#", "%23");
-    urn = PublicId.stringReplace(urn, "+", "%2B");
-    urn = PublicId.stringReplace(urn, " ", "+");
-    urn = PublicId.stringReplace(urn, "::", ";");
-    urn = PublicId.stringReplace(urn, ":", "%3A");
-    urn = PublicId.stringReplace(urn, "//", ":");
-    urn = PublicId.stringReplace(urn, "/", "%2F");
+      urn = PublicId.stringReplace(urn, "%", "%25");
+      urn = PublicId.stringReplace(urn, ";", "%3B");
+      urn = PublicId.stringReplace(urn, "'", "%27");
+      urn = PublicId.stringReplace(urn, "?", "%3F");
+      urn = PublicId.stringReplace(urn, "#", "%23");
+      urn = PublicId.stringReplace(urn, "+", "%2B");
+      urn = PublicId.stringReplace(urn, " ", "+");
+      urn = PublicId.stringReplace(urn, "::", ";");
+      urn = PublicId.stringReplace(urn, ":", "%3A");
+      urn = PublicId.stringReplace(urn, "//", ":");
+      urn = PublicId.stringReplace(urn, "/", "%2F");
 
-    return "urn:publicid:" + urn;
+      StringBuilder buffer = new StringBuilder(13 + urn.length());
+      buffer.append("urn:publicid:");
+      buffer.append(urn);
+      return buffer.toString();
   }
 
   /**
@@ -111,51 +108,62 @@
    * @return The normalized identifier.
    */
   public static String decodeURN(String urn) {
-    String publicId = "";
-
-    if (urn.startsWith("urn:publicid:")) {
-      publicId = urn.substring(13);
-    } else {
-      return urn;
-    }
+      String publicId;
+      if (urn.startsWith("urn:publicid:")) {
+          publicId = urn.substring(13);
+      }
+      else {
+          return urn;
+      }
 
-    publicId = PublicId.stringReplace(publicId, "%2F", "/");
-    publicId = PublicId.stringReplace(publicId, ":", "//");
-    publicId = PublicId.stringReplace(publicId, "%3A", ":");
-    publicId = PublicId.stringReplace(publicId, ";", "::");
-    publicId = PublicId.stringReplace(publicId, "+", " ");
-    publicId = PublicId.stringReplace(publicId, "%2B", "+");
-    publicId = PublicId.stringReplace(publicId, "%23", "#");
-    publicId = PublicId.stringReplace(publicId, "%3F", "?");
-    publicId = PublicId.stringReplace(publicId, "%27", "'");
-    publicId = PublicId.stringReplace(publicId, "%3B", ";");
-    publicId = PublicId.stringReplace(publicId, "%25", "%");
+      final boolean hasEscape = (publicId.indexOf('%') >= 0);
+      if (hasEscape) {
+          publicId = PublicId.stringReplace(publicId, "%2F", "/");
+      }
+      publicId = PublicId.stringReplace(publicId, ":", "//");
+      if (hasEscape) {
+          publicId = PublicId.stringReplace(publicId, "%3A", ":");
+      }
+      publicId = PublicId.stringReplace(publicId, ";", "::");
+      publicId = PublicId.stringReplace(publicId, "+", " ");
+      if (hasEscape) {
+          publicId = PublicId.stringReplace(publicId, "%2B", "+");
+          publicId = PublicId.stringReplace(publicId, "%23", "#");
+          publicId = PublicId.stringReplace(publicId, "%3F", "?");
+          publicId = PublicId.stringReplace(publicId, "%27", "'");
+          publicId = PublicId.stringReplace(publicId, "%3B", ";");
+          publicId = PublicId.stringReplace(publicId, "%25", "%");
+      }
 
-    return publicId;
-    }
+      return publicId;
+  }
 
   /**
    * Replace one string with another.
-   *
    */
   private static String stringReplace(String str,
-                                      String oldStr,
-                                      String newStr) {
-
-    String result = "";
-    int pos = str.indexOf(oldStr);
-
-    //    System.out.println(str + ": " + oldStr + " => " + newStr);
-
-    while (pos >= 0) {
-      //      System.out.println(str + " (" + pos + ")");
-      result += str.substring(0, pos);
-      result += newStr;
-      str = str.substring(pos+1);
-
-      pos = str.indexOf(oldStr);
-    }
-
-    return result + str;
+          String oldStr,
+          String newStr) {
+      int pos = str.indexOf(oldStr);
+      if (pos >= 0) {
+          final StringBuilder buffer = new StringBuilder();
+          final int oldStrLength = oldStr.length();
+          int start = 0;
+          do {
+              for (int i = start; i < pos; ++i) {
+                  buffer.append(str.charAt(i));
+              }
+              buffer.append(newStr);
+              start = pos + oldStrLength;
+              pos = str.indexOf(oldStr, start);
+          }
+          while (pos >= 0);
+          final int strLength = str.length();
+          for (int i = start; i < strLength; ++i) {
+              buffer.append(str.charAt(i));
+          }
+          return buffer.toString();
+      }
+      return str;
   }
 }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// CatalogReader.java - An interface for reading catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// DOMCatalogParser.java - An interface for reading catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// DOMCatalogReader.java - Read XML Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// ExtendedXMLCatalogReader.java - Read XML Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -166,7 +160,7 @@
       String baseURI = (String) baseURIStack.peek();
 
       if (!baseURI.equals(popURI)) {
-        entryType = catalog.BASE;
+        entryType = Catalog.BASE;
         entryArgs.add(baseURI);
 
         debug.message(4, "(reset) xml:base", baseURI);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// OASISXMLCatalogReader.java - Read XML Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -23,16 +17,16 @@
 
 package com.sun.org.apache.xml.internal.resolver.readers;
 
-import java.util.Stack;
-import java.util.Vector;
-import java.util.Enumeration;
 import com.sun.org.apache.xml.internal.resolver.Catalog;
 import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
 import com.sun.org.apache.xml.internal.resolver.CatalogException;
 import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
-
+import java.util.Enumeration;
+import java.util.Stack;
+import java.util.Vector;
+import javax.xml.parsers.SAXParserFactory;
+import org.w3c.dom.*;
 import org.xml.sax.*;
-import org.w3c.dom.*;
 
 /**
  * Parse OASIS Entity Resolution Technical Committee
@@ -71,6 +65,17 @@
     return catalog;
   }
 
+  /** Default constructor */
+  public OASISXMLCatalogReader() {
+    super();
+  }
+
+  /** Constructor allowing for providing custom SAX parser factory */
+  public OASISXMLCatalogReader(SAXParserFactory parserFactory, Catalog catalog) {
+    super(parserFactory);
+    setCatalog(catalog);
+  }
+
   /**
    * Are we in an extension namespace?
    *
@@ -102,7 +107,7 @@
     return;
   }
 
-  /** The SAX <code>startDocument</code> method does nothing. */
+  /** The SAX <code>startDocument</code> */
   public void startDocument ()
     throws SAXException {
     baseURIStack.push(catalog.getCurrentBase());
@@ -371,14 +376,14 @@
       }
 
       if (localName.equals("doctype")) {
-        entryType = catalog.DOCTYPE;
+        entryType = Catalog.DOCTYPE;
         entryArgs.add(atts.getValue("name"));
         entryArgs.add(atts.getValue("uri"));
       } else if (localName.equals("document")) {
-        entryType = catalog.DOCUMENT;
+        entryType = Catalog.DOCUMENT;
         entryArgs.add(atts.getValue("uri"));
       } else if (localName.equals("dtddecl")) {
-        entryType = catalog.DTDDECL;
+        entryType = Catalog.DTDDECL;
         entryArgs.add(atts.getValue("publicId"));
         entryArgs.add(atts.getValue("uri"));
       } else if (localName.equals("entity")) {
@@ -432,7 +437,7 @@
       && checkAttributes(atts, attName2);
   }
 
-  /** The SAX <code>endElement</code> method does nothing. */
+  /** The SAX <code>endElement</code> */
   public void endElement (String namespaceURI,
                           String localName,
                           String qName)
@@ -452,7 +457,7 @@
       String baseURI = (String) baseURIStack.peek();
 
       if (!baseURI.equals(popURI)) {
-        entryType = catalog.BASE;
+        entryType = Catalog.BASE;
         entryArgs.add(baseURI);
 
         debug.message(4, "(reset) xml:base", baseURI);
@@ -477,7 +482,7 @@
         String override = (String) overrideStack.peek();
 
         if (!override.equals(popOverride)) {
-          entryType = catalog.OVERRIDE;
+          entryType = Catalog.OVERRIDE;
           entryArgs.add(override);
           overrideStack.push(override);
 
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// SAXCatalogParser.java - An interface for reading catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// SAXCatalogReader.java - Read XML Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -77,427 +71,423 @@
  *
  */
 public class SAXCatalogReader implements CatalogReader, ContentHandler, DocumentHandler {
-  /** The SAX Parser Factory */
-  protected SAXParserFactory parserFactory = null;
+    /** The SAX Parser Factory */
+    protected SAXParserFactory parserFactory = null;
 
-  /** The SAX Parser Class */
-  protected String parserClass = null;
+    /** The SAX Parser Class */
+    protected String parserClass = null;
 
-  /**
+    /**
      * Mapping table from QNames to CatalogParser classes.
      *
      * <p>Each key in this hash table has the form "elementname"
      * or "{namespaceuri}elementname". The former is used if the
      * namespace URI is null.</p>
      */
-  protected Hashtable namespaceMap = new Hashtable();
+    protected Hashtable namespaceMap = new Hashtable();
 
-  /** The parser in use for the current catalog. */
-  private SAXCatalogParser saxParser = null;
+    /** The parser in use for the current catalog. */
+    private SAXCatalogParser saxParser = null;
 
-  /** Set if something goes horribly wrong. It allows the class to
+    /** Set if something goes horribly wrong. It allows the class to
      * ignore the rest of the events that are received.
      */
-  private boolean abandonHope = false;
+    private boolean abandonHope = false;
 
-  /** The Catalog that we're working for. */
-  private Catalog catalog;
+    /** The Catalog that we're working for. */
+    private Catalog catalog;
 
-  /** Set the XML SAX Parser Factory.
-   */
-  public void setParserFactory(SAXParserFactory parserFactory) {
-    this.parserFactory = parserFactory;
-  }
+    /** Set the XML SAX Parser Factory.
+     */
+    public void setParserFactory(SAXParserFactory parserFactory) {
+        this.parserFactory = parserFactory;
+    }
 
-  /** Set the XML SAX Parser Class
-   */
-  public void setParserClass(String parserClass) {
-    this.parserClass = parserClass;
-  }
+    /** Set the XML SAX Parser Class
+     */
+    public void setParserClass(String parserClass) {
+        this.parserClass = parserClass;
+    }
 
-  /** Get the parser factory currently in use. */
-  public SAXParserFactory getParserFactory() {
-    return parserFactory;
-  }
+    /** Get the parser factory currently in use. */
+    public SAXParserFactory getParserFactory() {
+        return parserFactory;
+    }
 
-  /** Get the parser class currently in use. */
-  public String getParserClass() {
-    return parserClass;
-  }
+    /** Get the parser class currently in use. */
+    public String getParserClass() {
+        return parserClass;
+    }
 
-  /** The debug class to use for this reader.
-   *
-   * This is a bit of a hack. Anyway, whenever we read for a catalog,
-   * we extract the debug object
-   * from the catalog's manager so that we can use it to print messages.
-   *
-   * In production, we don't really expect any messages so it doesn't
-   * really matter. But it's still a bit of a hack.
-   */
-  protected Debug debug = CatalogManager.getStaticManager().debug;
+    /** The debug class to use for this reader.
+     *
+     * This is a bit of a hack. Anyway, whenever we read for a catalog,
+     * we extract the debug object
+     * from the catalog's manager so that we can use it to print messages.
+     *
+     * In production, we don't really expect any messages so it doesn't
+     * really matter. But it's still a bit of a hack.
+     */
+    protected Debug debug = CatalogManager.getStaticManager().debug;
+
+    /** The constructor */
+    public SAXCatalogReader() {
+        parserFactory = null;
+        parserClass = null;
+    }
 
-  /** The constructor */
-  public SAXCatalogReader() {
-    parserFactory = null;
-    parserClass = null;
-  }
+    /** The constructor */
+    public SAXCatalogReader(SAXParserFactory parserFactory) {
+        this.parserFactory = parserFactory;
+    }
+
+    /** The constructor */
+    public SAXCatalogReader(String parserClass) {
+        this.parserClass = parserClass;
+    }
 
-  /** The constructor */
-  public SAXCatalogReader(SAXParserFactory parserFactory) {
-    this.parserFactory = parserFactory;
-  }
+    /**
+     * Set the SAXCatalogParser class for the given namespace/root
+     * element type.
+     */
+    public void setCatalogParser(String namespaceURI,
+            String rootElement,
+            String parserClass) {
+        namespaceURI = namespaceURI != null ? namespaceURI.trim() : "";
+        namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
+    }
 
-  /** The constructor */
-  public SAXCatalogReader(String parserClass) {
-    this.parserClass = parserClass;
-  }
-
-  /** Set the SAXCatalogParser class for the given namespace/root
+    /**
+     * Get the SAXCatalogParser class for the given namespace/root
      * element type.
      */
-  public void setCatalogParser(String namespaceURI,
-                               String rootElement,
-                               String parserClass) {
-    if (namespaceURI == null) {
-      namespaceMap.put(rootElement, parserClass);
-    } else {
-      namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
-    }
-  }
-
-  /** Get the SAXCatalogParser class for the given namespace/root
-     * element type.
-     */
-  public String getCatalogParser(String namespaceURI,
-                                 String rootElement) {
-    if (namespaceURI == null) {
-      return (String) namespaceMap.get(rootElement);
-    } else {
-      return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
+    public String getCatalogParser(String namespaceURI,
+            String rootElement) {
+        namespaceURI = namespaceURI != null ? namespaceURI.trim() : "";
+        return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
     }
-  }
+
+    /**
+     * Parse an XML Catalog file.
+     *
+     * @param catalog The catalog to which this catalog file belongs
+     * @param fileUrl The URL or filename of the catalog file to process
+     *
+     * @throws MalformedURLException Improper fileUrl
+     * @throws IOException Error reading catalog file
+     */
+    public void readCatalog(Catalog catalog, String fileUrl)
+            throws MalformedURLException, IOException,
+            CatalogException {
+
+        URL url = null;
 
-  /**
-   * Parse an XML Catalog file.
-   *
-   * @param catalog The catalog to which this catalog file belongs
-   * @param fileUrl The URL or filename of the catalog file to process
-   *
-   * @throws MalformedURLException Improper fileUrl
-   * @throws IOException Error reading catalog file
-   */
-  public void readCatalog(Catalog catalog, String fileUrl)
-    throws MalformedURLException, IOException,
-           CatalogException {
+        try {
+            url = new URL(fileUrl);
+        } catch (MalformedURLException e) {
+            url = new URL("file:///" + fileUrl);
+        }
+
+        debug = catalog.getCatalogManager().debug;
 
-    URL url = null;
-
-    try {
-      url = new URL(fileUrl);
-    } catch (MalformedURLException e) {
-      url = new URL("file:///" + fileUrl);
+        try {
+            URLConnection urlCon = url.openConnection();
+            readCatalog(catalog, urlCon.getInputStream());
+        } catch (FileNotFoundException e) {
+            catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
+                    url.toString());
+        }
     }
 
-    debug = catalog.getCatalogManager().debug;
+    /**
+     * Parse an XML Catalog stream.
+     *
+     * @param catalog The catalog to which this catalog file belongs
+     * @param is The input stream from which the catalog will be read
+     *
+     * @throws MalformedURLException Improper fileUrl
+     * @throws IOException Error reading catalog file
+     * @throws CatalogException A Catalog exception
+     */
+    public void readCatalog(Catalog catalog, InputStream is)
+            throws IOException, CatalogException {
 
-    try {
-      URLConnection urlCon = url.openConnection();
-      readCatalog(catalog, urlCon.getInputStream());
-    } catch (FileNotFoundException e) {
-      catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
-                    url.toString());
-    }
-  }
+        // Create an instance of the parser
+        if (parserFactory == null && parserClass == null) {
+            debug.message(1, "Cannot read SAX catalog without a parser");
+            throw new CatalogException(CatalogException.UNPARSEABLE);
+        }
+
+        debug = catalog.getCatalogManager().debug;
+        EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
+
+        this.catalog = catalog;
 
-  /**
-   * Parse an XML Catalog stream.
-   *
-   * @param catalog The catalog to which this catalog file belongs
-   * @param is The input stream from which the catalog will be read
-   *
-   * @throws MalformedURLException Improper fileUrl
-   * @throws IOException Error reading catalog file
-   * @throws CatalogException A Catalog exception
-   */
-  public void readCatalog(Catalog catalog, InputStream is)
-    throws IOException, CatalogException {
+        try {
+            if (parserFactory != null) {
+                SAXParser parser = parserFactory.newSAXParser();
+                SAXParserHandler spHandler = new SAXParserHandler();
+                spHandler.setContentHandler(this);
+                if (bResolver != null) {
+                    spHandler.setEntityResolver(bResolver);
+                }
+                parser.parse(new InputSource(is), spHandler);
+            } else {
+                Parser parser = (Parser) ReflectUtil.forName(parserClass).newInstance();
+                parser.setDocumentHandler(this);
+                if (bResolver != null) {
+                    parser.setEntityResolver(bResolver);
+                }
+                parser.parse(new InputSource(is));
+            }
+        } catch (ClassNotFoundException cnfe) {
+            throw new CatalogException(CatalogException.UNPARSEABLE);
+        } catch (IllegalAccessException iae) {
+            throw new CatalogException(CatalogException.UNPARSEABLE);
+        } catch (InstantiationException ie) {
+            throw new CatalogException(CatalogException.UNPARSEABLE);
+        } catch (ParserConfigurationException pce) {
+            throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
+        } catch (SAXException se) {
+            Exception e = se.getException();
+            // FIXME: there must be a better way
+            UnknownHostException uhe = new UnknownHostException();
+            FileNotFoundException fnfe = new FileNotFoundException();
+            if (e != null) {
+                if (e.getClass() == uhe.getClass()) {
+                    throw new CatalogException(CatalogException.PARSE_FAILED,
+                            e.toString());
+                } else if (e.getClass() == fnfe.getClass()) {
+                    throw new CatalogException(CatalogException.PARSE_FAILED,
+                            e.toString());
+                }
+            }
+            throw new CatalogException(se);
+        }
+    }
 
-    // Create an instance of the parser
-    if (parserFactory == null && parserClass == null) {
-      debug.message(1, "Cannot read SAX catalog without a parser");
-      throw new CatalogException(CatalogException.UNPARSEABLE);
+    // ----------------------------------------------------------------------
+    // Implement the SAX ContentHandler interface
+
+    /** The SAX <code>setDocumentLocator</code> method. Does nothing. */
+    public void setDocumentLocator (Locator locator) {
+        if (saxParser != null) {
+            saxParser.setDocumentLocator(locator);
+        }
+    }
+
+    /** The SAX <code>startDocument</code> method. Does nothing. */
+    public void startDocument () throws SAXException {
+        saxParser = null;
+        abandonHope = false;
+        return;
     }
 
-    debug = catalog.getCatalogManager().debug;
-    EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
-
-    this.catalog = catalog;
+    /** The SAX <code>endDocument</code> method. Does nothing. */
+    public void endDocument ()throws SAXException {
+        if (saxParser != null) {
+            saxParser.endDocument();
+        }
+    }
 
-    try {
-      if (parserFactory != null) {
-        SAXParser parser = parserFactory.newSAXParser();
-        SAXParserHandler spHandler = new SAXParserHandler();
-        spHandler.setContentHandler(this);
-        if (bResolver != null) {
-          spHandler.setEntityResolver(bResolver);
-        }
-        parser.parse(new InputSource(is), spHandler);
-      } else {
-        Parser parser = (Parser) ReflectUtil.forName(parserClass).newInstance();
-        parser.setDocumentHandler(this);
-        if (bResolver != null) {
-          parser.setEntityResolver(bResolver);
+    /**
+     * The SAX <code>startElement</code> method.
+     *
+     * <p>The catalog parser is selected based on the namespace of the
+     * first element encountered in the catalog.</p>
+     */
+    public void startElement (String name,
+            AttributeList atts)
+                    throws SAXException {
+
+        if (abandonHope) {
+            return;
         }
-        parser.parse(new InputSource(is));
-      }
-    } catch (ClassNotFoundException cnfe) {
-      throw new CatalogException(CatalogException.UNPARSEABLE);
-    } catch (IllegalAccessException iae) {
-      throw new CatalogException(CatalogException.UNPARSEABLE);
-    } catch (InstantiationException ie) {
-      throw new CatalogException(CatalogException.UNPARSEABLE);
-    } catch (ParserConfigurationException pce) {
-      throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
-    } catch (SAXException se) {
-      Exception e = se.getException();
-      // FIXME: there must be a better way
-      UnknownHostException uhe = new UnknownHostException();
-      FileNotFoundException fnfe = new FileNotFoundException();
-      if (e != null) {
-        if (e.getClass() == uhe.getClass()) {
-          throw new CatalogException(CatalogException.PARSE_FAILED,
-                                     e.toString());
-        } else if (e.getClass() == fnfe.getClass()) {
-          throw new CatalogException(CatalogException.PARSE_FAILED,
-                                     e.toString());
-        }
-      }
-      throw new CatalogException(se);
-    }
-  }
+
+        if (saxParser == null) {
+            String prefix = "";
+            if (name.indexOf(':') > 0) {
+                prefix = name.substring(0, name.indexOf(':'));
+            }
 
-  // ----------------------------------------------------------------------
-  // Implement the SAX ContentHandler interface
+            String localName = name;
+            if (localName.indexOf(':') > 0) {
+                localName = localName.substring(localName.indexOf(':')+1);
+            }
+
+            String namespaceURI = null;
+            if (prefix.length() == 0) {
+                namespaceURI = atts.getValue("xmlns");
+            } else {
+                namespaceURI = atts.getValue("xmlns:" + prefix);
+            }
+
+            String saxParserClass = getCatalogParser(namespaceURI,
+                    localName);
 
-  /** The SAX <code>setDocumentLocator</code> method. Does nothing. */
-  public void setDocumentLocator (Locator locator) {
-    if (saxParser != null) {
-      saxParser.setDocumentLocator(locator);
-    }
-  }
+            if (saxParserClass == null) {
+                abandonHope = true;
+                if (namespaceURI == null) {
+                    debug.message(2, "No Catalog parser for " + name);
+                } else {
+                    debug.message(2, "No Catalog parser for "
+                            + "{" + namespaceURI + "}"
+                            + name);
+                }
+                return;
+            }
 
-  /** The SAX <code>startDocument</code> method. Does nothing. */
-  public void startDocument () throws SAXException {
-    saxParser = null;
-    abandonHope = false;
-    return;
-  }
+            try {
+                saxParser = (SAXCatalogParser)
+                        ReflectUtil.forName(saxParserClass).newInstance();
 
-  /** The SAX <code>endDocument</code> method. Does nothing. */
-  public void endDocument ()throws SAXException {
-    if (saxParser != null) {
-      saxParser.endDocument();
-    }
-  }
-
-  /**
-   * The SAX <code>startElement</code> method.
-   *
-   * <p>The catalog parser is selected based on the namespace of the
-   * first element encountered in the catalog.</p>
-   */
-  public void startElement (String name,
-                            AttributeList atts)
-    throws SAXException {
-
-    if (abandonHope) {
-      return;
+                saxParser.setCatalog(catalog);
+                saxParser.startDocument();
+                saxParser.startElement(name, atts);
+            } catch (ClassNotFoundException cnfe) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, cnfe.toString());
+            } catch (InstantiationException ie) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, ie.toString());
+            } catch (IllegalAccessException iae) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, iae.toString());
+            } catch (ClassCastException cce ) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, cce.toString());
+            }
+        } else {
+            saxParser.startElement(name, atts);
+        }
     }
 
-    if (saxParser == null) {
-      String prefix = "";
-      if (name.indexOf(':') > 0) {
-        prefix = name.substring(0, name.indexOf(':'));
-      }
-
-      String localName = name;
-      if (localName.indexOf(':') > 0) {
-        localName = localName.substring(localName.indexOf(':')+1);
-      }
-
-      String namespaceURI = null;
-      if (prefix.equals("")) {
-        namespaceURI = atts.getValue("xmlns");
-      } else {
-        namespaceURI = atts.getValue("xmlns:" + prefix);
-      }
+    /**
+     * The SAX2 <code>startElement</code> method.
+     *
+     * <p>The catalog parser is selected based on the namespace of the
+     * first element encountered in the catalog.</p>
+     */
+    public void startElement (String namespaceURI,
+            String localName,
+            String qName,
+            Attributes atts)
+                    throws SAXException {
 
-      String saxParserClass = getCatalogParser(namespaceURI,
-                                               localName);
+        if (abandonHope) {
+            return;
+        }
 
-      if (saxParserClass == null) {
-        abandonHope = true;
-        if (namespaceURI == null) {
-          debug.message(2, "No Catalog parser for " + name);
-        } else {
-          debug.message(2, "No Catalog parser for "
-                        + "{" + namespaceURI + "}"
-                        + name);
-        }
-        return;
-      }
-
-      try {
-        saxParser = (SAXCatalogParser)
-          ReflectUtil.forName(saxParserClass).newInstance();
+        if (saxParser == null) {
+            String saxParserClass = getCatalogParser(namespaceURI,
+                    localName);
 
-        saxParser.setCatalog(catalog);
-        saxParser.startDocument();
-        saxParser.startElement(name, atts);
-      } catch (ClassNotFoundException cnfe) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, cnfe.toString());
-      } catch (InstantiationException ie) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, ie.toString());
-      } catch (IllegalAccessException iae) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, iae.toString());
-      } catch (ClassCastException cce ) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, cce.toString());
-      }
-    } else {
-      saxParser.startElement(name, atts);
-    }
-  }
+            if (saxParserClass == null) {
+                abandonHope = true;
+                if (namespaceURI == null) {
+                    debug.message(2, "No Catalog parser for " + localName);
+                } else {
+                    debug.message(2, "No Catalog parser for "
+                            + "{" + namespaceURI + "}"
+                            + localName);
+                }
+                return;
+            }
+
+            try {
+                saxParser = (SAXCatalogParser)
+                        ReflectUtil.forName(saxParserClass).newInstance();
 
-  /**
-   * The SAX2 <code>startElement</code> method.
-   *
-   * <p>The catalog parser is selected based on the namespace of the
-   * first element encountered in the catalog.</p>
-   */
-  public void startElement (String namespaceURI,
-                            String localName,
-                            String qName,
-                            Attributes atts)
-    throws SAXException {
-
-    if (abandonHope) {
-      return;
+                saxParser.setCatalog(catalog);
+                saxParser.startDocument();
+                saxParser.startElement(namespaceURI, localName, qName, atts);
+            } catch (ClassNotFoundException cnfe) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, cnfe.toString());
+            } catch (InstantiationException ie) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, ie.toString());
+            } catch (IllegalAccessException iae) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, iae.toString());
+            } catch (ClassCastException cce ) {
+                saxParser = null;
+                abandonHope = true;
+                debug.message(2, cce.toString());
+            }
+        } else {
+            saxParser.startElement(namespaceURI, localName, qName, atts);
+        }
     }
 
-    if (saxParser == null) {
-      String saxParserClass = getCatalogParser(namespaceURI,
-                                               localName);
+    /** The SAX <code>endElement</code> method. Does nothing. */
+    public void endElement (String name) throws SAXException {
+        if (saxParser != null) {
+            saxParser.endElement(name);
+        }
+    }
 
-      if (saxParserClass == null) {
-        abandonHope = true;
-        if (namespaceURI == null) {
-          debug.message(2, "No Catalog parser for " + localName);
-        } else {
-          debug.message(2, "No Catalog parser for "
-                        + "{" + namespaceURI + "}"
-                        + localName);
+    /** The SAX2 <code>endElement</code> method. Does nothing. */
+    public void endElement (String namespaceURI,
+            String localName,
+            String qName) throws SAXException {
+        if (saxParser != null) {
+            saxParser.endElement(namespaceURI, localName, qName);
         }
-        return;
-      }
-
-      try {
-        saxParser = (SAXCatalogParser)
-          ReflectUtil.forName(saxParserClass).newInstance();
+    }
 
-        saxParser.setCatalog(catalog);
-        saxParser.startDocument();
-        saxParser.startElement(namespaceURI, localName, qName, atts);
-      } catch (ClassNotFoundException cnfe) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, cnfe.toString());
-      } catch (InstantiationException ie) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, ie.toString());
-      } catch (IllegalAccessException iae) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, iae.toString());
-      } catch (ClassCastException cce ) {
-        saxParser = null;
-        abandonHope = true;
-        debug.message(2, cce.toString());
-      }
-    } else {
-      saxParser.startElement(namespaceURI, localName, qName, atts);
+    /** The SAX <code>characters</code> method. Does nothing. */
+    public void characters (char ch[], int start, int length)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.characters(ch, start, length);
+        }
     }
-  }
 
-  /** The SAX <code>endElement</code> method. Does nothing. */
-  public void endElement (String name) throws SAXException {
-    if (saxParser != null) {
-      saxParser.endElement(name);
+    /** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
+    public void ignorableWhitespace (char ch[], int start, int length)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.ignorableWhitespace(ch, start, length);
+        }
     }
-  }
 
-  /** The SAX2 <code>endElement</code> method. Does nothing. */
-  public void endElement (String namespaceURI,
-                          String localName,
-                          String qName) throws SAXException {
-    if (saxParser != null) {
-      saxParser.endElement(namespaceURI, localName, qName);
+    /** The SAX <code>processingInstruction</code> method. Does nothing. */
+    public void processingInstruction (String target, String data)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.processingInstruction(target, data);
+        }
     }
-  }
 
-  /** The SAX <code>characters</code> method. Does nothing. */
-  public void characters (char ch[], int start, int length)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.characters(ch, start, length);
+    /** The SAX <code>startPrefixMapping</code> method. Does nothing. */
+    public void startPrefixMapping (String prefix, String uri)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.startPrefixMapping (prefix, uri);
+        }
     }
-  }
-
-  /** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
-  public void ignorableWhitespace (char ch[], int start, int length)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.ignorableWhitespace(ch, start, length);
-    }
-  }
 
-  /** The SAX <code>processingInstruction</code> method. Does nothing. */
-  public void processingInstruction (String target, String data)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.processingInstruction(target, data);
+    /** The SAX <code>endPrefixMapping</code> method. Does nothing. */
+    public void endPrefixMapping (String prefix)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.endPrefixMapping (prefix);
+        }
     }
-  }
-
-  /** The SAX <code>startPrefixMapping</code> method. Does nothing. */
-  public void startPrefixMapping (String prefix, String uri)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.startPrefixMapping (prefix, uri);
-    }
-  }
 
-  /** The SAX <code>endPrefixMapping</code> method. Does nothing. */
-  public void endPrefixMapping (String prefix)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.endPrefixMapping (prefix);
+    /** The SAX <code>skippedentity</code> method. Does nothing. */
+    public void skippedEntity (String name)
+            throws SAXException {
+        if (saxParser != null) {
+            saxParser.skippedEntity(name);
+        }
     }
-  }
-
-  /** The SAX <code>skippedentity</code> method. Does nothing. */
-  public void skippedEntity (String name)
-    throws SAXException {
-    if (saxParser != null) {
-      saxParser.skippedEntity(name);
-    }
-  }
 }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// SAXParserHandler.java - An entity-resolving DefaultHandler
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// TR9401CatalogReader.java - Read OASIS Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -23,13 +17,14 @@
 
 package com.sun.org.apache.xml.internal.resolver.readers;
 
-import java.io.InputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Vector;
 import com.sun.org.apache.xml.internal.resolver.Catalog;
 import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
 import com.sun.org.apache.xml.internal.resolver.CatalogException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.Locale;
+import java.util.Vector;
 
 /**
  * Parses OASIS Open Catalog files.
@@ -97,7 +92,7 @@
         if (caseSensitive) {
           entryToken = token;
         } else {
-          entryToken = token.toUpperCase();
+          entryToken = token.toUpperCase(Locale.ENGLISH);
         }
 
         if (entryToken.equals("DELEGATE")) {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// TextCatalogReader.java - Read text/plain Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -23,18 +17,19 @@
 
 package com.sun.org.apache.xml.internal.resolver.readers;
 
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.MalformedURLException;
-import java.util.Vector;
-import java.util.Stack;
 import com.sun.org.apache.xml.internal.resolver.Catalog;
 import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
 import com.sun.org.apache.xml.internal.resolver.CatalogException;
 import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Locale;
+import java.util.Stack;
+import java.util.Vector;
 
 /**
  * Parses plain text Catalog files.
@@ -140,7 +135,7 @@
         if (caseSensitive) {
           entryToken = token;
         } else {
-          entryToken = token.toUpperCase();
+          entryToken = token.toUpperCase(Locale.ENGLISH);
         }
 
         try {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// XCatalogReader.java - Read XML Catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -34,7 +28,7 @@
 import javax.xml.parsers.*;
 
 /**
- * Parse "xcatalog" XML Catalog files, this is the XML Catalog format
+ * Parse "XCatalog" XML Catalog files, this is the XML Catalog format
  * developed by John Cowan and supported by Apache.
  *
  * @see Catalog
@@ -52,6 +46,7 @@
   /** Set the current catalog. */
   public void setCatalog (Catalog catalog) {
     this.catalog = catalog;
+    debug = catalog.getCatalogManager().debug;
   }
 
   /** Get the current catalog. */
@@ -59,13 +54,19 @@
     return catalog;
   }
 
-  /** The constructor */
-  public XCatalogReader(SAXParserFactory parserFactory) {
+  /** Default constructor */
+  public XCatalogReader() {
+    super();
+  }
+
+  /** Constructor allowing for providing custom SAX parser factory */
+  public XCatalogReader(SAXParserFactory parserFactory, Catalog catalog) {
     super(parserFactory);
+    setCatalog(catalog);
   }
 
   // ----------------------------------------------------------------------
-  // Implement the SAX DocumentHandler interface
+  // Implement the SAX ContentHandler interface
 
   /** The SAX <code>setDocumentLocator</code> method does nothing. */
   public void setDocumentLocator (Locator locator) {
@@ -106,44 +107,44 @@
     Vector entryArgs = new Vector();
 
     if (localName.equals("Base")) {
-      entryType = catalog.BASE;
+      entryType = Catalog.BASE;
       entryArgs.add(atts.getValue("HRef"));
 
-      catalog.getCatalogManager().debug.message(4, "Base", atts.getValue("HRef"));
+      debug.message(4, "Base", atts.getValue("HRef"));
     } else if (localName.equals("Delegate")) {
-      entryType = catalog.DELEGATE_PUBLIC;
-      entryArgs.add(atts.getValue("PublicId"));
+      entryType = Catalog.DELEGATE_PUBLIC;
+      entryArgs.add(atts.getValue("PublicID"));
       entryArgs.add(atts.getValue("HRef"));
 
-      catalog.getCatalogManager().debug.message(4, "Delegate",
-                    PublicId.normalize(atts.getValue("PublicId")),
+      debug.message(4, "Delegate",
+                    PublicId.normalize(atts.getValue("PublicID")),
                     atts.getValue("HRef"));
     } else if (localName.equals("Extend")) {
-      entryType = catalog.CATALOG;
+      entryType = Catalog.CATALOG;
       entryArgs.add(atts.getValue("HRef"));
 
-      catalog.getCatalogManager().debug.message(4, "Extend", atts.getValue("HRef"));
+      debug.message(4, "Extend", atts.getValue("HRef"));
     } else if (localName.equals("Map")) {
-      entryType = catalog.PUBLIC;
-      entryArgs.add(atts.getValue("PublicId"));
+      entryType = Catalog.PUBLIC;
+      entryArgs.add(atts.getValue("PublicID"));
       entryArgs.add(atts.getValue("HRef"));
 
-      catalog.getCatalogManager().debug.message(4, "Map",
-                    PublicId.normalize(atts.getValue("PublicId")),
+      debug.message(4, "Map",
+                    PublicId.normalize(atts.getValue("PublicID")),
                     atts.getValue("HRef"));
     } else if (localName.equals("Remap")) {
-      entryType = catalog.SYSTEM;
-      entryArgs.add(atts.getValue("SystemId"));
+      entryType = Catalog.SYSTEM;
+      entryArgs.add(atts.getValue("SystemID"));
       entryArgs.add(atts.getValue("HRef"));
 
-      catalog.getCatalogManager().debug.message(4, "Remap",
-                    atts.getValue("SystemId"),
+      debug.message(4, "Remap",
+                    atts.getValue("SystemID"),
                     atts.getValue("HRef"));
-    } else if (localName.equals("XMLCatalog")) {
+    } else if (localName.equals("XCatalog")) {
       // nop, start of catalog
     } else {
       // This is equivalent to an invalid catalog entry type
-      catalog.getCatalogManager().debug.message(1, "Invalid catalog entry type", localName);
+      debug.message(1, "Invalid catalog entry type", localName);
     }
 
     if (entryType >= 0) {
@@ -152,21 +153,21 @@
         catalog.addEntry(ce);
       } catch (CatalogException cex) {
         if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
-          catalog.getCatalogManager().debug.message(1, "Invalid catalog entry type", localName);
+          debug.message(1, "Invalid catalog entry type", localName);
         } else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
-          catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", localName);
+          debug.message(1, "Invalid catalog entry", localName);
         }
       }
     }
-    }
+  }
 
-    /** The SAX <code>endElement</code> method does nothing. */
-    public void endElement (String namespaceURI,
-                            String localName,
-                            String qName)
-      throws SAXException {
-      return;
-    }
+  /** The SAX <code>endElement</code> method does nothing. */
+  public void endElement (String namespaceURI,
+                          String localName,
+                          String qName)
+    throws SAXException {
+    return;
+  }
 
   /** The SAX <code>characters</code> method does nothing. */
   public void characters (char ch[], int start, int length)
@@ -185,4 +186,23 @@
     throws SAXException {
     return;
   }
+
+  /** The SAX <code>skippedEntity</code> method does nothing. */
+  public void skippedEntity (String name)
+    throws SAXException {
+    return;
+  }
+
+  /** The SAX <code>startPrefixMapping</code> method does nothing. */
+  public void startPrefixMapping(String prefix, String uri)
+    throws SAXException {
+    return;
+  }
+
+  /** The SAX <code>endPrefixMapping</code> method does nothing. */
+  public void endPrefixMapping(String prefix)
+    throws SAXException {
+    return;
+  }
+
 }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// CatalogResolver.java - A SAX EntityResolver/JAXP URI Resolver
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -218,7 +212,10 @@
 
         return iSource;
       } catch (Exception e) {
-        catalogManager.debug.message(1, "Failed to create InputSource", resolved);
+        catalogManager.debug.message(1,
+                                     "Failed to create InputSource ("
+                                     + e.toString()
+                                     + ")", resolved);
         return null;
       }
     }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// ResolvingParser.java - An interface for reading catalog files
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -67,17 +61,12 @@
  */
 public class ResolvingParser
   implements Parser, DTDHandler, DocumentHandler, EntityResolver {
-  /** Make the parser Namespace aware? */
-  public static boolean namespaceAware = true;
-
-  /** Make the parser validating? */
-  public static boolean validating = false;
 
   /** Suppress explanatory message?
    *
    * @see #parse(InputSource)
    */
-  public static boolean suppressExplanation = false;
+  private static final boolean suppressExplanation = false;
 
   /** The underlying parser. */
   private SAXParser saxParser = null;
@@ -103,9 +92,6 @@
   /** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */
   private boolean allowXMLCatalogPI = false;
 
-  /** Has an oasis-xml-catalog PI been seen? */
-  private boolean oasisXMLCatalogPI = false;
-
   /** The base URI of the input document, if known. */
   private URL baseURL = null;
 
@@ -125,8 +111,8 @@
     catalogResolver = new CatalogResolver(catalogManager);
     SAXParserFactory spf = catalogManager.useServicesMechanism() ?
                     SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
-    spf.setNamespaceAware(namespaceAware);
-    spf.setValidating(validating);
+    spf.setNamespaceAware(true);
+    spf.setValidating(false);
 
     try {
       saxParser = spf.newSAXParser();
@@ -289,7 +275,6 @@
           if (catalog != null) {
             try {
               catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString());
-              oasisXMLCatalogPI = true;
 
               if (piCatalogResolver == null) {
                 piCatalogResolver = new CatalogResolver(true);
@@ -396,7 +381,10 @@
 
         return iSource;
       } catch (Exception e) {
-        catalogManager.debug.message(1, "Failed to create InputSource", resolved);
+        catalogManager.debug.message(1,
+                                     "Failed to create InputSource ("
+                                     + e.toString()
+                                     + ")", resolved);
         return null;
       }
     } else {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// ResolvingXMLFilter.java - An XMLFilter that performs catalog resolution
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -61,7 +55,7 @@
    *
    * @see #parse(InputSource)
    */
-  public static boolean suppressExplanation = false;
+  private static boolean suppressExplanation = false;
 
   /** The manager for the underlying resolver. */
   CatalogManager catalogManager = CatalogManager.getStaticManager();
@@ -75,9 +69,6 @@
   /** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */
   private boolean allowXMLCatalogPI = false;
 
-  /** Has an oasis-xml-catalog PI been seen? */
-  private boolean oasisXMLCatalogPI = false;
-
   /** The base URI of the input document, if known. */
   private URL baseURL = null;
 
@@ -202,7 +193,10 @@
 
         return iSource;
       } catch (Exception e) {
-        catalogManager.debug.message(1, "Failed to create InputSource", resolved);
+        catalogManager.debug.message(1,
+                                     "Failed to create InputSource ("
+                                     + e.toString()
+                                     + ")", resolved);
         return null;
       }
     } else {
@@ -289,7 +283,6 @@
           if (catalog != null) {
             try {
               catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString());
-              oasisXMLCatalogPI = true;
 
               if (piCatalogResolver == null) {
                 piCatalogResolver = new CatalogResolver(true);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,16 +1,10 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-// ResolvingXMLReader.java - An XMLReader that performs catalog resolution
-
-/*
- * Copyright 2001-2004 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -23,7 +17,6 @@
 
 package com.sun.org.apache.xml.internal.resolver.tools;
 
-import org.xml.sax.*;
 
 import javax.xml.parsers.*;
 
@@ -48,10 +41,10 @@
  */
 public class ResolvingXMLReader extends ResolvingXMLFilter {
   /** Make the parser Namespace aware? */
-  public static boolean namespaceAware = true;
+  private static final boolean namespaceAware = true;
 
   /** Make the parser validating? */
-  public static boolean validating = false;
+  private static final boolean validating = false;
 
   /**
    * Construct a new reader from the JAXP factory.
--- a/jaxws/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxws/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -2,7 +2,7 @@
 ^dist/
 ^drop/
 ^drop_included/
-^webrev/
+^webrev
 /nbproject/private/
 ^.hgtip
 .DS_Store
--- a/jaxws/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/jaxws/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -275,3 +275,4 @@
 dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27
 5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28
 3d1a4bfb6abbf5011ba6d8896301ee3b6ef3ba72 jdk9-b29
+e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30
--- a/jdk/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^webrev
 ^testoutput/
 /nbproject/private/
 ^make/netbeans/.*/build/
--- a/jdk/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -272,3 +272,4 @@
 f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27
 1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28
 2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29
+8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30
--- a/jdk/make/copy/Copy-java.base.gmk	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/copy/Copy-java.base.gmk	Wed Jul 05 20:00:59 2017 +0200
@@ -208,20 +208,6 @@
 
 ################################################################################
 
-ifeq ($(OPENJDK_TARGET_OS), solaris)
-
-  SUNPKCS11_CFG_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/sunpkcs11-solaris.cfg
-  SUNPKCS11_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/sunpkcs11-solaris.cfg
-
-  $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
-	$(call install-file)
-
-  BASE_CONF_FILES += $(SUNPKCS11_CFG_DST)
-
-endif
-
-################################################################################
-
 $(JDK_OUTPUTDIR)/lib/net.properties: $(JDK_TOPDIR)/src/java.base/share/conf/net.properties
 	$(ECHO) $(LOG_INFO) Copying $(@F)
 	$(call install-file)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/copy/Copy-jdk.crypto.pkcs11.gmk	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 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.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+
+  SUNPKCS11_CFG_SRC := \
+      $(JDK_TOPDIR)/src/jdk.crypto.pkcs11/solaris/conf/security/sunpkcs11-solaris.cfg
+  SUNPKCS11_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/sunpkcs11-solaris.cfg
+
+  $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
+	$(call install-file)
+
+  SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
+
+endif
+
+################################################################################
+
+jdk.crypto.pkcs11: $(SECURITY_PKCS11_CONF_FILES)
+
+all: jdk.crypto.pkcs11
+
+.PHONY: all jdk.crypto.pkcs11
+
--- a/jdk/make/data/tzdata/VERSION	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/VERSION	Wed Jul 05 20:00:59 2017 +0200
@@ -1,24 +1,24 @@
 #
 # 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.
 #
-tzdata2014c
+tzdata2014g
--- a/jdk/make/data/tzdata/africa	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/africa	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 #
@@ -49,8 +49,8 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -58,13 +58,13 @@
 # Previous editions of this database used WAT, CAT, SAT, and EAT
 # for +0:00 through +3:00, respectively,
 # but Mark R V Murray reports that
-# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
-# `CAT' is commonly used for +2:00 in countries north of South Africa, and
-# `WAT' is probably the best name for +1:00, as the common phrase for
-# the area that includes Nigeria is ``West Africa''.
-# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
+# 'SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# 'CAT' is commonly used for +2:00 in countries north of South Africa, and
+# 'WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is "West Africa".
+# He has heard of "Western Sahara Time" for +0:00 but can find no reference.
 #
-# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# To make things confusing, 'WAT' seems to have been used for -1:00 long ago;
 # I'd guess that this was because people needed _some_ name for -1:00,
 # and at the time, far west Africa was the only major land area in -1:00.
 # This usage is now obsolete, as the last use of -1:00 on the African
@@ -77,7 +77,7 @@
 #	 2:00	SAST	South Africa Standard Time
 # and Murray suggests the following abbreviation:
 #	 1:00	WAT	West Africa Time
-# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# I realize that this leads to 'WAT' being used for both -1:00 and 1:00
 # for times before 1976, but this is the best I can think of
 # until we get more information.
 #
@@ -117,9 +117,9 @@
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	Algeria	WE%sT	1940 Feb 25 2:00
+Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15  0:01
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	Algeria	WE%sT	1940 Feb 25  2:00
 			1:00	Algeria	CE%sT	1946 Oct  7
 			0:00	-	WET	1956 Jan 29
 			1:00	-	CET	1963 Apr 14
@@ -129,18 +129,8 @@
 			1:00	-	CET
 
 # Angola
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Luanda	0:52:56	-	LMT	1892
-			0:52:04	-	AOT	1911 May 26 # Angola Time
-			1:00	-	WAT
-
 # Benin
-# Whitman says they switched to 1:00 in 1946, not 1934;
-# go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
-			0:00	-	GMT	1934 Feb 26
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Botswana
 # From Paul Eggert (2013-02-21):
@@ -149,14 +139,12 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Gaborone	1:43:40 -	LMT	1885
 			1:30	-	SAST	1903 Mar
-			2:00	-	CAT	1943 Sep 19 2:00
-			2:00	1:00	CAST	1944 Mar 19 2:00
+			2:00	-	CAT	1943 Sep 19  2:00
+			2:00	1:00	CAST	1944 Mar 19  2:00
 			2:00	-	CAT
 
 # Burkina Faso
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Burundi
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -164,52 +152,60 @@
 			2:00	-	CAT
 
 # Cameroon
-# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Douala	0:38:48	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Cape Verde
+#
+# Shanks gives 1907 for the transition to CVT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907			# Praia
+Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907        # Praia
 			-2:00	-	CVT	1942 Sep
 			-2:00	1:00	CVST	1945 Oct 15
-			-2:00	-	CVT	1975 Nov 25 2:00
+			-2:00	-	CVT	1975 Nov 25  2:00
 			-1:00	-	CVT
 
 # Central African Republic
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bangui	1:14:20	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Chad
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Ndjamena	1:00:12 -	LMT	1912
+Zone	Africa/Ndjamena	1:00:12 -	LMT	1912        # N'Djamena
 			1:00	-	WAT	1979 Oct 14
 			1:00	1:00	WAST	1980 Mar  8
 			1:00	-	WAT
 
 # Comoros
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul   # Moroni, Gran Comoro
+Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul # Moroni, Gran Comoro
 			3:00	-	EAT
 
-# Democratic Republic of Congo
+# Democratic Republic of the Congo
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov 9
-			1:00	-	WAT
 Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
 			2:00	-	CAT
+# The above is for the eastern part; see Africa/Lagos for the western part.
 
 # Republic of the Congo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Brazzaville	1:01:08 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
-# Cote D'Ivoire
+# Côte d'Ivoire / Ivory Coast
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
 			 0:00	-	GMT
+Link Africa/Abidjan Africa/Bamako	# Mali
+Link Africa/Abidjan Africa/Banjul	# Gambia
+Link Africa/Abidjan Africa/Conakry	# Guinea
+Link Africa/Abidjan Africa/Dakar	# Senegal
+Link Africa/Abidjan Africa/Freetown	# Sierra Leone
+Link Africa/Abidjan Africa/Lome		# Togo
+Link Africa/Abidjan Africa/Nouakchott	# Mauritania
+Link Africa/Abidjan Africa/Ouagadougou	# Burkina Faso
+Link Africa/Abidjan Africa/Sao_Tome	# São Tomé and Príncipe
+Link Africa/Abidjan Atlantic/St_Helena	# St Helena
 
 # Djibouti
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -254,30 +250,26 @@
 # Egyptians would approve the cancellation."
 #
 # Egypt to cancel daylight saving time
-# <a href="http://www.almasryalyoum.com/en/node/407168">
 # http://www.almasryalyoum.com/en/node/407168
-# </a>
 # or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_egypt04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_egypt04.html
-# </a>
 Rule	Egypt	1995	2010	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	1995	2005	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	1995	2005	-	Sep	lastThu	24:00	0	-
 # From Steffen Thorsen (2006-09-19):
 # The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
 # Egypt will turn back clocks by one hour at the midnight of Thursday
 # after observing the daylight saving time since May.
 # http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
-Rule	Egypt	2006	only	-	Sep	21	23:00s	0	-
+Rule	Egypt	2006	only	-	Sep	21	24:00	0	-
 # From Dirk Losch (2007-08-14):
 # I received a mail from an airline which says that the daylight
 # saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
-# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
+# From Jesper Nørgaard Welen (2007-08-15): [The following agree:]
 # http://www.nentjes.info/Bill/bill5.htm
 # http://www.timeanddate.com/worldclock/city.html?n=53
 # From Steffen Thorsen (2007-09-04): The official information...:
 # http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
-Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
+Rule	Egypt	2007	only	-	Sep	Thu>=1	24:00	0	-
 # From Abdelrahman Hassan (2007-09-06):
 # Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
 # than the year of the Gregorian calendar, Ramadan shifts earlier each
@@ -311,15 +303,9 @@
 #
 # timeanddate[2] and another site I've found[3] also support that.
 #
-# [1] <a href="https://bugzilla.redhat.com/show_bug.cgi?id=492263">
-# https://bugzilla.redhat.com/show_bug.cgi?id=492263
-# </a>
-# [2] <a href="http://www.timeanddate.com/worldclock/clockchange.html?n=53">
-# http://www.timeanddate.com/worldclock/clockchange.html?n=53
-# </a>
-# [3] <a href="http://wwp.greenwichmeantime.com/time-zone/africa/egypt/">
-# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
-# </a>
+# [1] https://bugzilla.redhat.com/show_bug.cgi?id=492263
+# [2] http://www.timeanddate.com/worldclock/clockchange.html?n=53
+# [3] http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
 
 # From Arthur David Olson (2009-04-20):
 # In 2009 (and for the next several years), Ramadan ends before the fourth
@@ -329,14 +315,10 @@
 # From Steffen Thorsen (2009-08-11):
 # We have been able to confirm the August change with the Egyptian Cabinet
 # Information and Decision Support Center:
-# <a href="http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html">
 # http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
-# </a>
 #
 # The Middle East News Agency
-# <a href="http://www.mena.org.eg/index.aspx">
 # http://www.mena.org.eg/index.aspx
-# </a>
 # also reports "Egypt starts winter time on August 21"
 # today in article numbered "71, 11/08/2009 12:25 GMT."
 # Only the title above is available without a subscription to their service,
@@ -344,19 +326,14 @@
 # (at least today).
 
 # From Alexander Krivenyshev (2010-07-20):
-# According to News from Egypt -  Al-Masry Al-Youm Egypt's cabinet has
+# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has
 # decided that Daylight Saving Time will not be used in Egypt during
 # Ramadan.
 #
 # Arabic translation:
-# "Clocks to go back during Ramadan--and then forward again"
-# <a href="http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again">
+# "Clocks to go back during Ramadan - and then forward again"
 # http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_egypt02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
-# </a>
 
 # From Ahmad El-Dardiry (2014-05-07):
 # Egypt is to change back to Daylight system on May 15
@@ -365,46 +342,77 @@
 # From Gunther Vermier (2015-05-13):
 # our Egypt office confirms that the change will be at 15 May "midnight" (24:00)
 
-# From Paul Eggert (2014-05-13):
+# From Imed Chihi (2014-06-04):
+# We have finally "located" a precise official reference about the DST changes
+# in Egypt.  The Ministers Cabinet decision is explained at
+# http://www.cabinet.gov.eg/Media/CabinetMeetingsDetails.aspx?id=347 ...
+# [T]his (Arabic) site is not accessible outside Egypt, but the page ...
+# translates into: "With regard to daylight saving time, it is scheduled to
+# take effect at exactly twelve o'clock this evening, Thursday, 15 MAY 2014,
+# to be suspended by twelve o'clock on the evening of Thursday, 26 JUN 2014,
+# and re-established again at the end of the month of Ramadan, at twelve
+# o'clock on the evening of Thursday, 31 JUL 2014."  This statement has been
+# reproduced by other (more accessible) sites[, e.g.,]...
+# http://elgornal.net/news/news.aspx?id=4699258
+
+# From Paul Eggert (2014-06-04):
 # Sarah El Deeb and Lee Keath of AP report that the Egyptian government says
 # the change is because of blackouts in Cairo, even though Ahram Online (cited
-# above) says DST had no affect on electricity consumption.  The AP story says
-# DST will not be observed during Ramadan.  There is no information about when
-# DST will end.  See:
+# above) says DST had no affect on electricity consumption.  There is
+# no information about when DST will end this fall.  See:
 # http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833
 #
-# For now, guess that later transitions will use 2010's rules, and that
-# Egypt will agree with Morocco (see below) about the date Ramadan starts and
-# ends, though (unlike Morocco) it will switch at 00:00 standard time.  In
-# Egypt the spring-forward transitions are removed for 2020-2022, when the
-# guessed spring-forward date falls during the estimated Ramadan, and all
-# transitions removed for 2023-2038, where the estimated Ramadan falls entirely
-# outside the guessed daylight-saving time.  Ramadan intrudes on the guessed
-# DST starting in 2039, but that's beyond our somewhat-arbitrary cutoff.
-
-Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
-Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
-Rule	Egypt	2010	only	-	Aug	11	0:00	0	-
-Rule	Egypt	2010	only	-	Sep	10	0:00	1:00	S
-Rule	Egypt	2010	only	-	Sep	lastThu	23:00s	0	-
+# For now, guess that later spring and fall transitions will use
+# 2010's rules, and guess that Egypt will switch to standard time at
+# 24:00 the last Thursday before Ramadan, and back to DST at 00:00 the
+# first Friday after Ramadan.  To implement this,
+# transition dates for 2015 through 2037 were determined by running
+# the following program under GNU Emacs 24.3, with the results integrated
+# by hand into the table below.  Ramadan again intrudes on the guessed
+# DST starting in 2038, but that's beyond our somewhat-arbitrary cutoff.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (friday 5))
+#       (while (/= friday (mod a 7))
+#         (setq a (1- a)))
+#       (while (/= friday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (1- a))
+#       (setq b (1- b))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t0\t-\n"
+#                 "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+#     (setq islamic-year (+ 1 islamic-year))))
+Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
+Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
+Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
+Rule	Egypt	2010	only	-	Sep	 9	24:00	1:00	S
+Rule	Egypt	2010	only	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2014	only	-	May	15	24:00	1:00	S
-Rule	Egypt	2014	only	-	Jun	29	 0:00s	0	-
-Rule	Egypt	2014	only	-	Jul	29	 0:00s	1:00	S
-Rule	Egypt	2014	max	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	2014	only	-	Jun	26	24:00	0	-
+Rule	Egypt	2014	only	-	Jul	31	24:00	1:00	S
+Rule	Egypt	2014	max	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2015	2019	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	2015	only	-	Jun	18	 0:00s	0	-
-Rule	Egypt	2015	only	-	Jul	18	 0:00s	1:00	S
-Rule	Egypt	2016	only	-	Jun	 7	 0:00s	0	-
-Rule	Egypt	2016	only	-	Jul	 7	 0:00s	1:00	S
-Rule	Egypt	2017	only	-	May	27	 0:00s	0	-
-Rule	Egypt	2017	only	-	Jun	26	 0:00s	1:00	S
-Rule	Egypt	2018	only	-	May	16	 0:00s	0	-
-Rule	Egypt	2018	only	-	Jun	15	 0:00s	1:00	S
-Rule	Egypt	2019	only	-	May	 6	 0:00s	0	-
-Rule	Egypt	2019	only	-	Jun	 5	 0:00s	1:00	S
-Rule	Egypt	2020	only	-	May	24	 0:00s	1:00	S
-Rule	Egypt	2021	only	-	May	13	 0:00s	1:00	S
-Rule	Egypt	2022	only	-	May	 3	 0:00s	1:00	S
+Rule	Egypt	2015	only	-	Jun	11	24:00	0	-
+Rule	Egypt	2015	only	-	Jul	23	24:00	1:00	S
+Rule	Egypt	2016	only	-	Jun	 2	24:00	0	-
+Rule	Egypt	2016	only	-	Jul	 7	24:00	1:00	S
+Rule	Egypt	2017	only	-	May	25	24:00	0	-
+Rule	Egypt	2017	only	-	Jun	29	24:00	1:00	S
+Rule	Egypt	2018	only	-	May	10	24:00	0	-
+Rule	Egypt	2018	only	-	Jun	14	24:00	1:00	S
+Rule	Egypt	2019	only	-	May	 2	24:00	0	-
+Rule	Egypt	2019	only	-	Jun	 6	24:00	1:00	S
+Rule	Egypt	2020	only	-	May	28	24:00	1:00	S
+Rule	Egypt	2021	only	-	May	13	24:00	1:00	S
+Rule	Egypt	2022	only	-	May	 5	24:00	1:00	S
 Rule	Egypt	2023	max	-	Apr	lastFri	 0:00s	1:00	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -412,60 +420,63 @@
 			2:00	Egypt	EE%sT
 
 # Equatorial Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Malabo	0:35:08 -	LMT	1912
-			0:00	-	GMT	1963 Dec 15
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Eritrea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Asmara	2:35:32 -	LMT	1870
-			2:35:32	-	AMT	1890	      # Asmara Mean Time
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:32	-	AMT	1890        # Asmara Mean Time
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Ethiopia
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
-# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
-# We'll guess that 38E50 is for Adis Dera.
+# From Paul Eggert (2014-07-31):
+# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
+# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
+# 02:00 or 14:00.  Keep this in mind when you ask the time in Amharic.
+#
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
+# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
+# 1890, and that they switched to 3:00 on 1936-05-05.  Perhaps 38E50
+# was for Adis Dera.  Quite likely the Shanks data entries are wrong
+# anyway.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Gabon
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Libreville	0:37:48 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Gambia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Banjul	-1:06:36 -	LMT	1912
-			-1:06:36 -	BMT	1935	# Banjul Mean Time
-			-1:00	-	WAT	1964
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Ghana
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman says DST was observed from 1931 to ``the present'';
-# go with Shanks & Pottenger.
-Rule	Ghana	1936	1942	-	Sep	 1	0:00	0:20	GHST
-Rule	Ghana	1936	1942	-	Dec	31	0:00	0	GMT
+# Whitman says DST was observed from 1931 to "the present";
+# Shanks & Pottenger say 1936 to 1942;
+# and September 1 to January 1 is given by:
+# Scott Keltie J, Epstein M (eds), The Statesman's Year-Book,
+# 57th ed. Macmillan, London (1920), OCLC 609408015, pp xxviii.
+# For lack of better info, assume DST was observed from 1920 to 1942.
+Rule	Ghana	1920	1942	-	Sep	 1	0:00	0:20	GHST
+Rule	Ghana	1920	1942	-	Dec	31	0:00	0	GMT
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Accra	-0:00:52 -	LMT	1918
 			 0:00	Ghana	%s
 
 # Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Conakry	-0:54:52 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Guinea-Bissau
+#
+# Shanks gives 1911-05-26 for the transition to WAT,
+# evidently confusing the date of the Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# with the date that it took effect, namely 1912-01-01.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bissau	-1:02:20 -	LMT	1911 May 26
+Zone	Africa/Bissau	-1:02:20 -	LMT	1912 Jan  1
 			-1:00	-	WAT	1975
 			 0:00	-	GMT
 
@@ -480,8 +491,8 @@
 # Lesotho
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
-			2:00	-	SAST	1943 Sep 19 2:00
-			2:00	1:00	SAST	1944 Mar 19 2:00
+			2:00	-	SAST	1943 Sep 19  2:00
+			2:00	1:00	SAST	1944 Mar 19  2:00
 			2:00	-	SAST
 
 # Liberia
@@ -549,11 +560,11 @@
 			2:00	-	EET	1982
 			1:00	Libya	CE%sT	1990 May  4
 # The 1996 and 1997 entries are from Shanks & Pottenger;
-# the IATA SSIM data contain some obvious errors.
+# the IATA SSIM data entries contain some obvious errors.
 			2:00	-	EET	1996 Sep 30
 			1:00	Libya	CE%sT	1997 Oct  4
-			2:00	-	EET	2012 Nov 10 2:00
-			1:00	Libya	CE%sT	2013 Oct 25 2:00
+			2:00	-	EET	2012 Nov 10  2:00
+			1:00	Libya	CE%sT	2013 Oct 25  2:00
 			2:00	-	EET
 
 # Madagascar
@@ -569,18 +580,8 @@
 			2:00	-	CAT
 
 # Mali
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bamako	-0:32:00 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Jun 20
-			 0:00	-	GMT
-
 # Mauritania
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Nov 28
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Mauritius
 
@@ -604,9 +605,7 @@
 
 # From Steffen Thorsen (2008-07-10):
 # According to
-# <a href="http://www.lexpress.mu/display_article.php?news_id=111216">
 # http://www.lexpress.mu/display_article.php?news_id=111216
-# </a>
 # (in French), Mauritius will start and end their DST a few days earlier
 # than previously announced (2008-11-01 to 2009-03-31).  The new start
 # date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
@@ -621,22 +620,17 @@
 
 # From Alex Krivenyshev (2008-07-11):
 # Seems that English language article "The revival of daylight saving
-# time:  Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
 # published on Monday, June 30, 2008...
 #
 # I guess that article in French "Le gouvernement avance l'introduction
-# de l'heure d'ete" stating that DST in Mauritius starting on October 26
-# and ending on March 27, 2009 is the most recent one.
-# ...
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html">
+# de l'heure d'été" stating that DST in Mauritius starting on October 26
+# and ending on March 27, 2009 is the most recent one....
 # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
-# </a>
 
 # From Riad M. Hossen Ally (2008-08-03):
 # The Government of Mauritius weblink
-# <a href="http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD">
 # http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
-# </a>
 # Cabinet Decision of July 18th, 2008 states as follows:
 #
 # 4. ...Cabinet has agreed to the introduction into the National Assembly
@@ -646,33 +640,25 @@
 # States of America. It will start at two o'clock in the morning on the
 # last Sunday of October and will end at two o'clock in the morning on
 # the last Sunday of March the following year. The summer time for the
-# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
+# year 2008-2009 will, therefore, be effective as from 26 October 2008
 # and end on 29 March 2009.
 
 # From Ed Maste (2008-10-07):
 # THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
 # beginning / ending of summer time is 2 o'clock standard time in the
 # morning of the last Sunday of October / last Sunday of March.
-# <a href="http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf">
 # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
-# </a>
 
 # From Steffen Thorsen (2009-06-05):
 # According to several sources, Mauritius will not continue to observe
 # DST the coming summer...
 #
 # Some sources, in French:
-# <a href="http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB">
 # http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
-# </a>
-# <a href="http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-">
 # http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
-# </a>
 #
 # Our wrap-up:
-# <a href="http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html">
 # http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
-# </a>
 
 # From Arthur David Olson (2009-07-11):
 # The "mauritius-dst-will-not-repeat" wrapup includes this:
@@ -685,18 +671,18 @@
 Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
 Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
+Zone Indian/Mauritius	3:50:00 -	LMT	1907 # Port Louis
 			4:00 Mauritius	MU%sT	# Mauritius Time
 # Agalega Is, Rodriguez
 # no information; probably like Indian/Mauritius
 
 # Mayotte
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
+Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul # Mamoutzou
 			3:00	-	EAT
 
 # Morocco
-# See the `europe' file for Spanish Morocco (Africa/Ceuta).
+# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
 
 # From Alex Krivenyshev (2008-05-09):
 # Here is an article that Morocco plan to introduce Daylight Saving Time between
@@ -704,60 +690,44 @@
 #
 # "... Morocco is to save energy by adjusting its clock during summer so it will
 # be one hour ahead of GMT between 1 June and 27 September, according to
-# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
+# Communication Minister and Government Spokesman, Khalid Naciri...."
 #
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_morocco01.html">
 # http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
-# </a>
-# OR
-# <a href="http://en.afrik.com/news11892.html">
 # http://en.afrik.com/news11892.html
-# </a>
 
 # From Alex Krivenyshev (2008-05-09):
-# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
-# <a href="http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view">
+# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe
+# Presse:
 # http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
-# </a>
 #
 # Morocco shifts to daylight time on June 1st through September 27, Govt.
 # spokesman.
 
 # From Patrice Scattolin (2008-05-09):
 # According to this article:
-# <a href="http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html">
 # http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
-# </a>
-# (and republished here:
-# <a href="http://www.actu.ma/heure-dete-comment_i127896_0.html">
-# http://www.actu.ma/heure-dete-comment_i127896_0.html
-# </a>
-# )
-# the changes occurs at midnight:
+# (and republished here: <http://www.actu.ma/heure-dete-comment_i127896_0.html>)
+# the changes occur at midnight:
 #
-# saturday night may 31st at midnight (which in french is to be
-# intrepreted as the night between saturday and sunday)
-# sunday night the 28th  at midnight
+# Saturday night May 31st at midnight (which in French is to be
+# interpreted as the night between Saturday and Sunday)
+# Sunday night the 28th at midnight
 #
-# Seeing that the 28th is monday, I am guessing that she intends to say
-# the midnight of the 28th which is the midnight between sunday and
-# monday, which jives with other sources that say that it's inclusive
-# june1st to sept 27th.
+# Seeing that the 28th is Monday, I am guessing that she intends to say
+# the midnight of the 28th which is the midnight between Sunday and
+# Monday, which jives with other sources that say that it's inclusive
+# June 1st to Sept 27th.
 #
 # The decision was taken by decree *2-08-224 *but I can't find the decree
 # published on the web.
 #
 # It's also confirmed here:
-# <a href="http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm">
 # http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
-# </a>
-# on a government portal as being  between june 1st and sept 27th (not yet
-# posted in english).
+# on a government portal as being between June 1st and Sept 27th (not yet
+# posted in English).
 #
-# The following google query will generate many relevant hits:
-# <a href="http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search">
+# The following Google query will generate many relevant hits:
 # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
-# </a>
 
 # From Steffen Thorsen (2008-08-27):
 # Morocco will change the clocks back on the midnight between August 31
@@ -765,47 +735,32 @@
 # of September:
 #
 # One article about it (in French):
-# <a href="http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default">
 # http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
-# </a>
 #
 # We have some further details posted here:
-# <a href="http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html">
 # http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
-# </a>
 
 # From Steffen Thorsen (2009-03-17):
 # Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
 # to many sources, such as
-# <a href="http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html">
 # http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
-# </a>
-# <a href="http://www.medi1sat.ma/fr/depeche.aspx?idp=2312">
 # http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
-# </a>
 # (French)
 #
 # Our summary:
-# <a href="http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html">
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to official document from Royaume du Maroc Premier Ministre,
-# Ministere de la Modernisation des Secteurs Publics
+# Ministère de la Modernisation des Secteurs Publics
 #
 # Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
 # concerning the amendment of the legal time, the Ministry of Modernization of
 # Public Sectors announced that the official time in the Kingdom will be
 # advanced 60 minutes from Sunday 31 May 2009 at midnight.
 #
-# <a href="http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf">
 # http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
-# </a>
-#
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_morocco03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
-# </a>
 
 # From Steffen Thorsen (2010-04-13):
 # Several news media in Morocco report that the Ministry of Modernization
@@ -813,51 +768,33 @@
 # 2010-05-02 to 2010-08-08.
 #
 # Example:
-# <a href="http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html">
 # http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html
-# </a>
 # (French)
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html">
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html
-# </a>
 
 # From Dan Abitol (2011-03-30):
 # ...Rules for Africa/Casablanca are the following (24h format)
-# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00
-# The 31th july 2011 at 00:59:59,  [it] will be 31th July 00:00:00
+# The 3rd April 2011 at 00:00:00, [it] will be 3rd April 01:00:00
+# The 31st July 2011 at 00:59:59, [it] will be 31st July 00:00:00
 # ...Official links of change in morocco
 # The change was broadcast on the FM Radio
 # I ve called ANRT (telecom regulations in Morocco) at
 # +212.537.71.84.00
-# <a href="http://www.anrt.net.ma/fr/">
 # http://www.anrt.net.ma/fr/
-# </a>
 # They said that
-# <a href="http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view">
 # http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view
-# </a>
 # is the official publication to look at.
 # They said that the decision was already taken.
 #
 # More articles in the press
-# <a href="http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev">
-# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev
-# </a>
-# e.html
-# <a href="http://www.lematin.ma/Actualite/Express/Article.asp?id=148923">
+# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-leve.html
 # http://www.lematin.ma/Actualite/Express/Article.asp?id=148923
-# </a>
-# <a href="http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim">
 # http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim
-# anche-prochain-5538.html
-# </a>
 
 # From Petr Machata (2011-03-30):
 # They have it written in English here:
-# <a href="http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view">
 # http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view
-# </a>
 #
 # It says there that "Morocco will resume its standard time on July 31,
 # 2011 at midnight." Now they don't say whether they mean midnight of
@@ -865,20 +802,16 @@
 # also been like that in the past.
 
 # From Alexander Krivenyshev (2012-03-09):
-# According to Infom&eacute;diaire web site from Morocco (infomediaire.ma),
-# on March 9, 2012, (in French) Heure l&eacute;gale:
-# Le Maroc adopte officiellement l'heure d'&eacute;t&eacute;
-# <a href="http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9">
+# According to Infomédiaire web site from Morocco (infomediaire.ma),
+# on March 9, 2012, (in French) Heure légale:
+# Le Maroc adopte officiellement l'heure d'été
 # http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9
-# </a>
 # Governing Council adopted draft decree, that Morocco DST starts on
 # the last Sunday of March (March 25, 2012) and ends on
 # last Sunday of September (September 30, 2012)
 # except the month of Ramadan.
 # or (brief)
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_morocco06.html">
 # http://www.worldtimezone.com/dst_news/dst_news_morocco06.html
-# </a>
 
 # From Arthur David Olson (2012-03-10):
 # The infomediaire.ma source indicates that the system is to be in
@@ -889,17 +822,13 @@
 
 # From Christophe Tropamer (2012-03-16):
 # Seen Morocco change again:
-# <a href="http://www.le2uminutes.com/actualite.php">
 # http://www.le2uminutes.com/actualite.php
-# </a>
-# "...&agrave; partir du dernier dimance d'avril et non fins mars,
-# comme annonc&eacute; pr&eacute;c&eacute;demment."
+# "...à partir du dernier dimanche d'avril et non fins mars,
+# comme annoncé précédemment."
 
 # From Milamber Space Network (2012-07-17):
 # The official return to GMT is announced by the Moroccan government:
-# <a href="http://www.mmsp.gov.ma/fr/actualites.aspx?id=288">
 # http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
-# </a>
 #
 # Google translation, lightly edited:
 # Back to the standard time of the Kingdom (GMT)
@@ -917,7 +846,7 @@
 # announced a bit in advance.  On 2012-07-11 the Moroccan government
 # announced that year's Ramadan daylight-saving transitions would be
 # 2012-07-20 and 2012-08-20; see
-# <http://www.mmsp.gov.ma/fr/actualites.aspx?id=288>.
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288
 
 # From Andrew Paprocki (2013-07-02):
 # Morocco announced that the year's Ramadan daylight-savings
@@ -937,39 +866,36 @@
 # From Sebastien Willemijns (2014-03-18):
 # http://www.afriquinfos.com/articles/2014/3/18/maroc-heure-dete-avancez-tous-horloges-247891.asp
 
-# From Paul Eggert (2014-03-19):
-# To estimate what the Moroccan government will do in future years,
-# transition dates for 2014 through 2038 were determined by running
-# the following program under GNU Emacs 24.3:
-#
-# (let ((islamic-year 1435))
-#   (while (< islamic-year 1461)
-#     (let ((a
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 9 1 islamic-year))))
-#	    (b
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 10 1 islamic-year)))))
-#	(insert
-#	 (format
-#	  (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n"
-#		  "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n")
-#	  (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
-#	  (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# From Milamber Space Network (2014-06-05):
+# The Moroccan government has recently announced that the country will return
+# to standard time at 03:00 on Saturday, June 28, 2014 local time....  DST
+# will resume again at 02:00 on Saturday, August 2, 2014....
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=586
+
+# From Paul Eggert (2014-06-05):
+# For now, guess that later spring and fall transitions will use 2014's rules,
+# and guess that Morocco will switch to standard time at 03:00 the last
+# Saturday before Ramadan, and back to DST at 02:00 the first Saturday after
+# Ramadan.  To implement this, transition dates for 2015 through 2037 were
+# determined by running the following program under GNU Emacs 24.3, with the
+# results integrated by hand into the table below.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (saturday 6))
+#       (while (/= saturday (mod (setq a (1- a)) 7)))
+#       (while (/= saturday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t0\t-\n"
+#                 "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
 #     (setq islamic-year (+ 1 islamic-year))))
-#
-# with spring-forward transitions removed for 2023-2025, when the
-# normal spring-forward date falls during the estimated Ramadan; with
-# all transitions removed for 2026-2035, where the estimated Ramadan
-# falls entirely outside daylight-saving time; and with fall-back
-# transitions removed for 2036-2037, where the normal fall-back
-# date falls during the estimated Ramadan.  Normally, the table would
-# stop after 2037 because 32-bit time_t values roll around early in 2038,
-# but that would imply a prediction of perpetual DST after March 2038
-# due to the year-2037 glitches.  So, this table instead stops after
-# 2038, the first non-glitchy year after the 32-bit rollover.
-# An advantage of stopping after 2038 is that it lets zic guess
-# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future.
 
 # RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 
@@ -991,46 +917,44 @@
 Rule	Morocco	2008	only	-	Jun	 1	 0:00	1:00	S
 Rule	Morocco	2008	only	-	Sep	 1	 0:00	0	-
 Rule	Morocco	2009	only	-	Jun	 1	 0:00	1:00	S
-Rule	Morocco	2009	only	-	Aug	 21	 0:00	0	-
+Rule	Morocco	2009	only	-	Aug	21	 0:00	0	-
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	 31	 0	0	-
-Rule	Morocco	2012	2013	-	Apr	 lastSun 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2012	only	-	Jul	 20	 3:00	0	-
-Rule	Morocco	2012	only	-	Aug	 20	 2:00	1:00	S
-Rule	Morocco	2013	only	-	Jul	  7	 3:00	0	-
-Rule	Morocco	2013	only	-	Aug	 10	 2:00	1:00	S
-Rule	Morocco	2013	2035	-	Oct	 lastSun 3:00	0	-
-Rule	Morocco	2014	2022	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2014	only	-	Jun	 29	 3:00	0	-
-Rule	Morocco	2014	only	-	Jul	 29	 2:00	1:00	S
-Rule	Morocco	2015	only	-	Jun	 18	 3:00	0	-
-Rule	Morocco	2015	only	-	Jul	 18	 2:00	1:00	S
-Rule	Morocco	2016	only	-	Jun	  7	 3:00	0	-
-Rule	Morocco	2016	only	-	Jul	  7	 2:00	1:00	S
-Rule	Morocco	2017	only	-	May	 27	 3:00	0	-
-Rule	Morocco	2017	only	-	Jun	 26	 2:00	1:00	S
-Rule	Morocco	2018	only	-	May	 16	 3:00	0	-
-Rule	Morocco	2018	only	-	Jun	 15	 2:00	1:00	S
-Rule	Morocco	2019	only	-	May	  6	 3:00	0	-
-Rule	Morocco	2019	only	-	Jun	  5	 2:00	1:00	S
-Rule	Morocco	2020	only	-	Apr	 24	 3:00	0	-
-Rule	Morocco	2020	only	-	May	 24	 2:00	1:00	S
-Rule	Morocco	2021	only	-	Apr	 13	 3:00	0	-
-Rule	Morocco	2021	only	-	May	 13	 2:00	1:00	S
-Rule	Morocco	2022	only	-	Apr	  3	 3:00	0	-
-Rule	Morocco	2022	only	-	May	  3	 2:00	1:00	S
-Rule	Morocco	2023	only	-	Apr	 22	 2:00	1:00	S
-Rule	Morocco	2024	only	-	Apr	 10	 2:00	1:00	S
-Rule	Morocco	2025	only	-	Mar	 31	 2:00	1:00	S
-Rule	Morocco	2026	max	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2036	only	-	Oct	 21	 3:00	0	-
-Rule	Morocco	2037	only	-	Oct	 11	 3:00	0	-
-Rule	Morocco	2038	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2038	only	-	Oct	 30	 2:00	1:00	S
-Rule	Morocco	2038	max	-	Oct	 lastSun 3:00	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
+Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
+Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
+Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
+Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
+Rule	Morocco	2014	2022	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2014	only	-	Jun	28	 3:00	0	-
+Rule	Morocco	2014	only	-	Aug	 2	 2:00	1:00	S
+Rule	Morocco	2015	only	-	Jun	13	 3:00	0	-
+Rule	Morocco	2015	only	-	Jul	18	 2:00	1:00	S
+Rule	Morocco	2016	only	-	Jun	 4	 3:00	0	-
+Rule	Morocco	2016	only	-	Jul	 9	 2:00	1:00	S
+Rule	Morocco	2017	only	-	May	20	 3:00	0	-
+Rule	Morocco	2017	only	-	Jul	 1	 2:00	1:00	S
+Rule	Morocco	2018	only	-	May	12	 3:00	0	-
+Rule	Morocco	2018	only	-	Jun	16	 2:00	1:00	S
+Rule	Morocco	2019	only	-	May	 4	 3:00	0	-
+Rule	Morocco	2019	only	-	Jun	 8	 2:00	1:00	S
+Rule	Morocco	2020	only	-	Apr	18	 3:00	0	-
+Rule	Morocco	2020	only	-	May	30	 2:00	1:00	S
+Rule	Morocco	2021	only	-	Apr	10	 3:00	0	-
+Rule	Morocco	2021	only	-	May	15	 2:00	1:00	S
+Rule	Morocco	2022	only	-	Apr	 2	 3:00	0	-
+Rule	Morocco	2022	only	-	May	 7	 2:00	1:00	S
+Rule	Morocco	2023	only	-	Apr	22	 2:00	1:00	S
+Rule	Morocco	2024	only	-	Apr	13	 2:00	1:00	S
+Rule	Morocco	2025	only	-	Apr	 5	 2:00	1:00	S
+Rule	Morocco	2026	max	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2035	only	-	Oct	27	 3:00	0	-
+Rule	Morocco	2036	only	-	Oct	18	 3:00	0	-
+Rule	Morocco	2037	only	-	Oct	10	 3:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
@@ -1049,11 +973,17 @@
 # Assume that this has been true since Western Sahara switched to GMT,
 # since most of it was then controlled by Morocco.
 
-Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan
+Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan # El Aaiún
 			-1:00	-	WAT	1976 Apr 14
 			 0:00	Morocco	WE%sT
 
 # Mozambique
+#
+# Shanks gives 1903-03-01 for the transition to CAT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 			2:00	-	CAT
@@ -1062,8 +992,8 @@
 # The 1994-04-03 transition is from Shanks & Pottenger.
 # Shanks & Pottenger report no DST after 1998-04; go with IATA.
 
-# From Petronella Sibeene (2007-03-30) in
-# <http://allafrica.com/stories/200703300178.html>:
+# From Petronella Sibeene (2007-03-30):
+# http://allafrica.com/stories/200703300178.html
 # While the entire country changes its time, Katima Mulilo and other
 # settlements in Caprivi unofficially will not because the sun there
 # rises and sets earlier compared to other regions.  Chief of
@@ -1080,34 +1010,41 @@
 Rule	Namibia	1995	max	-	Apr	Sun>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
-			1:30	-	SWAT	1903 Mar	# SW Africa Time
-			2:00	-	SAST	1942 Sep 20 2:00
-			2:00	1:00	SAST	1943 Mar 21 2:00
+			1:30	-	SWAT	1903 Mar    # SW Africa Time
+			2:00	-	SAST	1942 Sep 20  2:00
+			2:00	1:00	SAST	1943 Mar 21  2:00
 			2:00	-	SAST	1990 Mar 21 # independence
 			2:00	-	CAT	1994 Apr  3
 			1:00	Namibia	WA%sT
 
 # Niger
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Niamey	 0:08:28 -	LMT	1912
-			-1:00	-	WAT	1934 Feb 26
-			 0:00	-	GMT	1960
-			 1:00	-	WAT
+# See Africa/Lagos.
 
 # Nigeria
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
 			1:00	-	WAT
+Link Africa/Lagos Africa/Bangui	     # Central African Republic
+Link Africa/Lagos Africa/Brazzaville # Rep. of the Congo
+Link Africa/Lagos Africa/Douala	     # Cameroon
+Link Africa/Lagos Africa/Kinshasa    # Dem. Rep. of the Congo (west)
+Link Africa/Lagos Africa/Libreville  # Gabon
+Link Africa/Lagos Africa/Luanda	     # Angola
+Link Africa/Lagos Africa/Malabo	     # Equatorial Guinea
+Link Africa/Lagos Africa/Niamey	     # Niger
+Link Africa/Lagos Africa/Porto-Novo  # Benin
 
-# Reunion
+# Réunion
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun	# Saint-Denis
-			4:00	-	RET	# Reunion Time
+Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun # Saint-Denis
+			4:00	-	RET	# Réunion Time
+#
+# Crozet Islands also observes Réunion time; see the 'antarctica' file.
 #
-# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# Scattered Islands (Îles Éparses) administered from Réunion are as follows.
 # The following information about them is taken from
-# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
-# no longer available as of 1999-08-17).
+# Îles Éparses (<http://www.outre-mer.gouv.fr/domtom/ile.htm>, 1997-07-22,
+# in French; no longer available as of 1999-08-17).
 # We have no info about their time zone histories.
 #
 # Bassas da India - uninhabited
@@ -1122,32 +1059,21 @@
 			2:00	-	CAT
 
 # St Helena
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890		# Jamestown
-			-0:22:48 -	JMT	1951	# Jamestown Mean Time
-			 0:00	-	GMT
+# See Africa/Abidjan.
 # The other parts of the St Helena territory are similar:
 #	Tristan da Cunha: on GMT, say Whitman and the CIA
-#	Ascension: on GMT, says usno1995 and the CIA
+#	Ascension: on GMT, say the USNO (1995-12-21) and the CIA
 #	Gough (scientific station since 1955; sealers wintered previously):
 #		on GMT, says the CIA
-#	Inaccessible, Nightingale: no information, but probably GMT
+#	Inaccessible, Nightingale: uninhabited
 
-# Sao Tome and Principe
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
-			-0:36:32 -	LMT	1912	# Lisbon Mean Time
-			 0:00	-	GMT
-
+# São Tomé and Príncipe
 # Senegal
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Dakar	-1:09:44 -	LMT	1912
-			-1:00	-	WAT	1941 Jun
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Seychelles
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
+Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun # Victoria
 			4:00	-	SCT	# Seychelles Time
 # From Paul Eggert (2001-05-30):
 # Aldabra, Farquhar, and Desroches, originally dependencies of the
@@ -1157,17 +1083,7 @@
 # Possibly the islands were uninhabited.
 
 # Sierra Leone
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
-Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
-Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
-Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
-Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Freetown	-0:53:00 -	LMT	1882
-			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
-			-1:00	SL	%s	1957
-			 0:00	SL	%s
+# See Africa/Abidjan.
 
 # Somalia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1190,9 +1106,9 @@
 
 # Sudan
 #
-# From <a href="http://www.sunanews.net/sn13jane.html">
-# Sudan News Agency (2000-01-13)
-# </a>, also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# From <http://www.sunanews.net/sn13jane.html>
+# Sudan News Agency (2000-01-13),
+# also reported by Michaël De Beukelaer-Dossche via Steffen Thorsen:
 # Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
 # Saturday....  This was announced Thursday by Caretaker State Minister for
 # Manpower Abdul-Rahman Nur-Eddin.
@@ -1223,14 +1139,12 @@
 			3:00	-	EAT
 
 # Togo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Lome	0:04:52 -	LMT	1893
-			0:00	-	GMT
+# See Africa/Abidjan.
 
 # Tunisia
 
 # From Gwillim Law (2005-04-30):
-# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
+# My correspondent, Risto Nykänen, has alerted me to another adoption of DST,
 # this time in Tunisia.  According to Yahoo France News
 # <http://fr.news.yahoo.com/050426/5/4dumk.html>, in a story attributed to AP
 # and dated 2005-04-26, "Tunisia has decided to advance its official time by
@@ -1239,8 +1153,8 @@
 # Saturday."  (My translation)
 #
 # From Oscar van Vlijmen (2005-05-02):
-# LaPresse, the first national daily newspaper ...
-# <http://www.lapresse.tn/archives/archives280405/actualites/lheure.html>
+# La Presse, the first national daily newspaper ...
+# http://www.lapresse.tn/archives/archives280405/actualites/lheure.html
 # ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
 # 1h standard time.
 #
@@ -1253,18 +1167,12 @@
 # From Steffen Thorsen (2009-03-16):
 # According to several news sources, Tunisia will not observe DST this year.
 # (Arabic)
-# <a href="http://www.elbashayer.com/?page=viewn&nid=42546">
 # http://www.elbashayer.com/?page=viewn&nid=42546
-# </a>
-# <a href="http://www.babnet.net/kiwidetail-15295.asp">
 # http://www.babnet.net/kiwidetail-15295.asp
-# </a>
 #
 # We have also confirmed this with the US embassy in Tunisia.
 # We have a wrap-up about this on the following page:
-# <a href="http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html">
 # http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to Tunis Afrique Presse News Agency
@@ -1272,20 +1180,17 @@
 # Standard time to be kept the whole year long (tap.info.tn):
 #
 # (in English)
-# <a href="http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157">
 # http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
-# </a>
 #
 # (in Arabic)
-# <a href="http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1">
 # http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
-# </a>
 
-# From Arthur David Olson (2009--3-18):
-# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
-# that the fasting month of ramadan coincides with the period concerned by summer time.
-# Therefore, the standard time will be kept unchanged the whole year long."
-# So foregoing DST seems to be an exception (albeit one that may be repeated in the  future).
+# From Arthur David Olson (2009-03-18):
+# The Tunis Afrique Presse News Agency notice contains this: "This measure is
+# due to the fact that the fasting month of Ramadan coincides with the period
+# concerned by summer time.  Therefore, the standard time will be kept
+# unchanged the whole year long."  So foregoing DST seems to be an exception
+# (albeit one that may be repeated in the future).
 
 # From Alexander Krivenyshev (2010-03-27):
 # According to some news reports Tunis confirmed not to use DST in 2010
@@ -1297,12 +1202,8 @@
 # coincided with the month of Ramadan..."
 #
 # (in Arabic)
-# <a href="http://www.moheet.com/show_news.aspx?nid=358861&pg=1">
 # http://www.moheet.com/show_news.aspx?nid=358861&pg=1
-# <a href="http://www.almadenahnews.com/newss/news.php?c=118&id=38036">
 # http://www.almadenahnews.com/newss/news.php?c=118&id=38036
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_tunis02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_tunis02.html
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1337,7 +1238,7 @@
 # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			1:00	Tunisia	CE%sT
 
 # Uganda
--- a/jdk/make/data/tzdata/antarctica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/antarctica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,19 +21,16 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # From Paul Eggert (1999-11-15):
 # To keep things manageable, we list only locations occupied year-round; see
-# <a href="http://www.comnap.aq/comnap/comnap.nsf/P/Stations/">
 # COMNAP - Stations and Bases
-# </a>
+# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
 # and
-# <a href="http://www.spri.cam.ac.uk/bob/periant.htm">
 # Summary of the Peri-Antarctic Islands (1998-07-23)
-# </a>
+# http://www.spri.cam.ac.uk/bob/periant.htm
 # for information.
 # Unless otherwise specified, we have no time zone information.
 #
@@ -78,19 +75,19 @@
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
-# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
-# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
-# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
+# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
+# Marambio, -6414-05637, since 1969-10-29
 # Orcadas, Laurie I, -6016-04444, since 1904-02-22
-# San Martin, Debenham I, -6807-06708, since 1951-03-21
+# San Martín, Barry I, -6808-06706, since 1951-03-21
 #	(except 1960-03 / 1976-03-21)
 
 # Australia - territories
 # Heard Island, McDonald Islands (uninhabited)
 #	previously sealers and scientific personnel wintered
-#	<a href="http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html">
 #	Margaret Turner reports
-#	</a> (1999-09-30) that they're UTC+5, with no DST;
+#	http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
+#	(1999-09-30) that they're UTC+5, with no DST;
 #	presumably this is when they have visitors.
 #
 # year-round bases
@@ -107,14 +104,10 @@
 # The changes occurred on 2009-10-18 at 02:00 (local times).
 #
 # Government source: (Australian Antarctic Division)
-# <a href="http://www.aad.gov.au/default.asp?casid=37079">
 # http://www.aad.gov.au/default.asp?casid=37079
-# </a>
 #
 # We have more background information here:
-# <a href="http://www.timeanddate.com/news/time/antarctica-new-times.html">
 # http://www.timeanddate.com/news/time/antarctica-new-times.html
-# </a>
 
 # From Steffen Thorsen (2010-03-10):
 # We got these changes from the Australian Antarctic Division: ...
@@ -129,50 +122,49 @@
 # - Mawson station stays on UTC+5.
 #
 # Background:
-# <a href="http://www.timeanddate.com/news/time/antartica-time-changes-2010.html">
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
-# </a>
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	zzz	1969
-			8:00	-	WST	2009 Oct 18 2:00
-						# Western (Aus) Standard Time
-			11:00	-	CAST	2010 Mar 5 2:00
-						# Casey Time
-			8:00	-	WST	2011 Oct 28 2:00
+			8:00	-	AWST	2009 Oct 18  2:00
+						# Australian Western Std Time
+			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
+			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
-			8:00	-	WST
+			8:00	-	AWST
 Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
-			7:00	-	DAVT	1964 Nov # Davis Time
+			7:00	-	DAVT	1964 Nov    # Davis Time
 			0	-	zzz	1969 Feb
-			7:00	-	DAVT	2009 Oct 18 2:00
+			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
-			7:00	-	DAVT	2011 Oct 28 2:00
+			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
 Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
-			6:00	-	MAWT	2009 Oct 18 2:00
-						# Mawson Time
+			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
 # Casey Weather (1998-02-26)
-# </a>
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html">
+# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
 # Davis Station, Antarctica (1998-02-26)
-# </a>
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html">
+# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
 # Mawson Station, Antarctica (1998-02-25)
-# </a>
+# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
+
+# Belgium - year-round base
+# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
 
 # Brazil - year-round base
-# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
+# Ferraz, King George Island, -6205+05824, since 1983/4
+
+# Bulgaria - year-round base
+# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
 
 # Chile - year-round bases and towns
 # Escudero, South Shetland Is, -621157-0585735, since 1994
-# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
-# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
-# Capitan Arturo Prat, -6230-05941
+# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
+# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Prat, -6230-05941
 # Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
 # These locations have always used Santiago time; use TZ='America/Santiago'.
 
@@ -180,31 +172,35 @@
 # Great Wall, King George Island, -6213-05858, since 1985-02-20
 # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
 
-# France - year-round bases
+# France - year-round bases (also see "France & Italy")
 #
 # From Antoine Leca (1997-01-20):
-# Time data are from Nicole Pailleau at the IFRTP
+# Time data entries are from Nicole Pailleau at the IFRTP
 # (French Institute for Polar Research and Technology).
-# She confirms that French Southern Territories and Terre Adelie bases
-# don't observe daylight saving time, even if Terre Adelie supplies came
+# She confirms that French Southern Territories and Terre Adélie bases
+# don't observe daylight saving time, even if Terre Adélie supplies came
 # from Tasmania.
 #
 # French Southern Territories with year-round inhabitants
 #
-# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
-# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
-# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
+#	sealing & whaling stations operated variously 1802/1911+;
+#	see Indian/Reunion.
+#
+# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
+# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
 #	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
 #
 # St Paul Island - near Amsterdam, uninhabited
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
+Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
-# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
+# <http://en.wikipedia.org/wiki/Dumont_d'Urville_Station> (2005-12-05)
 #
 # Another base at Port-Martin, 50km east, began operation in 1947.
 # It was destroyed by fire on 1952-01-14.
@@ -214,20 +210,22 @@
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
 			0	-	zzz	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
-# Reference:
-# <a href="http://en.wikipedia.org/wiki/Dumont_d'Urville_Station">
-# Dumont d'Urville Station (2005-12-05)
-# </a>
+
+# France & Italy - year-round base
+# Concordia, -750600+1232000, since 2005
 
 # Germany - year-round base
-# Georg von Neumayer, -7039-00815
+# Neumayer III, -704080-0081602, since 2009
 
-# India - year-round base
-# Dakshin Gangotri, -7005+01200
+# India - year-round bases
+# Bharati, -692428+0761114, since 2012
+# Maitri, -704558+0114356, since 1989
+
+# Italy - year-round base (also see "France & Italy")
+# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
 
 # Japan - year-round bases
-# Dome Fuji, -7719+03942
-# Syowa, -690022+0393524
+# Syowa (also known as Showa), -690022+0393524, since 1957
 #
 # From Hideyuki Suzuki (1999-02-06):
 # In all Japanese stations, +0300 is used as the standard time.
@@ -239,11 +237,11 @@
 Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
-# <a href="http://www.nipr.ac.jp/english/ara01.html">
 # NIPR Antarctic Research Activities (1999-08-17)
-# </a>
+# http://www.nipr.ac.jp/english/ara01.html
 
 # S Korea - year-round base
+# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
 # King Sejong, King George Island, -6213-05847, since 1988
 
 # New Zealand - claims
@@ -287,11 +285,14 @@
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
-     			0:00	Troll	%s
+			0:00	Troll	%s
 
 # Poland - year-round base
 # Arctowski, King George Island, -620945-0582745, since 1977
 
+# Romania - year-bound base
+# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
+
 # Russia - year-round bases
 # Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
 # Mirny, Davis coast, -6633+09301, since 1956-02
@@ -301,8 +302,8 @@
 #	year-round from 1960/61 to 1992
 
 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
-# <a href="http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP">
-# From Craig Mundell (1994-12-15)</a>:
+# From Craig Mundell (1994-12-15):
+# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
 # Vostok, which is one of the Russian stations, is set on the same
 # time as Moscow, Russia.
 #
@@ -317,7 +318,7 @@
 #
 # From Paul Eggert (2001-05-04):
 # This seems to be hopelessly confusing, so I asked Lee Hotz about it
-# in person.  He said that some Antartic locations set their local
+# in person.  He said that some Antarctic locations set their local
 # time so that noon is the warmest part of the day, and that this
 # changes during the year and does not necessarily correspond to mean
 # solar noon.  So the Vostok time might have been whatever the clocks
@@ -329,9 +330,12 @@
 
 # S Africa - year-round bases
 # Marion Island, -4653+03752
-# Sanae, -7141-00250
+# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
 
-# UK
+# Ukraine - year-round base
+# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
+
+# United Kingdom
 #
 # British Antarctic Territories (BAT) claims
 # South Orkney Islands
@@ -387,7 +391,7 @@
 # but that he found it more convenient to keep GMT+12
 # as supplies for the station were coming from McMurdo Sound,
 # which was on GMT+12 because New Zealand was on GMT+12 all year
-# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
+# at that time (1957).  (Source: Siple's book 90 Degrees South.)
 #
 # From Susan Smith
 # http://www.cybertours.com/whs/pole10.html
--- a/jdk/make/data/tzdata/asia	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/asia	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-08-11):
 #
@@ -49,13 +49,17 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
+#
+# For Russian data circa 1919, a source is:
+# Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+# (See the 'europe' file for a fuller citation.)
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
 #	     std  dst
@@ -70,13 +74,14 @@
 #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
 #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
 #	8:00 CST	China
-#	9:00 CJT	Central Japanese Time (1896/1937)*
+#	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
+#	9:00 JCST	Central Standard Time (Japan, 1896/1937)
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
 #	9:00 KST  KDT	Korea
-#	9:30 CST	(Australian) Central Standard Time
+#	9:30 ACST	Australian Central Standard Time
 #
-# See the `europe' file for Russia and Turkey in Asia.
+# See the 'europe' file for Russia and Turkey in Asia.
 
 # From Guy Harris:
 # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
@@ -86,7 +91,7 @@
 
 ###############################################################################
 
-# These rules are stolen from the `europe' file.
+# These rules are stolen from the 'europe' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
@@ -138,11 +143,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
 			3:00	-	YERT	1957 Mar    # Yerevan Time
-			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia YER%sT	1991 Mar 31  2:00s
 			3:00	1:00	YERST	1991 Sep 23 # independence
-			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
+			3:00 RussiaAsia	AM%sT	1995 Sep 24  2:00s
 			4:00	-	AMT	1997
-			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
+			4:00 RussiaAsia	AM%sT	2012 Mar 25  2:00s
 			4:00	-	AMT
 
 # Azerbaijan
@@ -155,16 +160,16 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
 			3:00	-	BAKT	1957 Mar    # Baku Time
-			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
 			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
-			4:00	-	AZT	1996 # Azerbaijan time
+			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
 
 # Bahrain
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
+Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
@@ -174,13 +179,8 @@
 # Daylight Saving Time from June 16 to Sept 30
 #
 # Bangladesh to introduce daylight saving time likely from June 16
-# <a href="http://www.asiantribune.com/?q=node/17288">
 # http://www.asiantribune.com/?q=node/17288
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
-# </a>
 #
 # "... Bangladesh government has decided to switch daylight saving time from
 # June
@@ -195,17 +195,11 @@
 # the 19th and 20th, and they have not set the end date yet.
 #
 # Some sources:
-# <a href="http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601">
 # http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
-# </a>
-# <a href="http://bdnews24.com/details.php?id=85889&cid=2">
 # http://bdnews24.com/details.php?id=85889&cid=2
-# </a>
 #
 # Our wrap-up:
-# <a href="http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html">
 # http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
-# </a>
 
 # From A. N. M. Kamrus Saadat (2009-06-15):
 # Finally we've got the official mail regarding DST start time where DST start
@@ -220,13 +214,8 @@
 #
 # Following report by same newspaper-"The Daily Star Friday":
 # "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
-# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=107021">
 # http://www.thedailystar.net/newDesign/news-details.php?nid=107021
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
-# </a>
 
 # From Steffen Thorsen (2009-10-13):
 # IANS (Indo-Asian News Service) now reports:
@@ -235,22 +224,15 @@
 # "continue for an indefinite period."
 #
 # One of many places where it is published:
-# <a href="http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html">
 # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
-# </a>
 
 # From Alexander Krivenyshev (2009-12-24):
 # According to Bangladesh newspaper "The Daily Star,"
 # Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
 #
 # Clock goes back 1-hr on Dec 31 night.
-# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=119228">
 # http://www.thedailystar.net/newDesign/news-details.php?nid=119228
-# </a>
-# and
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
-# </a>
 #
 # "...The government yesterday decided to put the clock back by one hour
 # on December 31 midnight and the new time will continue until March 31,
@@ -260,17 +242,12 @@
 # From Alexander Krivenyshev (2010-03-22):
 # According to Bangladesh newspaper "The Daily Star,"
 # Cabinet cancels Daylight Saving Time
-# <a href="http://www.thedailystar.net/newDesign/latest_news.php?nid=22817">
 # http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
-Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
+Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
@@ -301,7 +278,7 @@
 
 # Brunei
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
+Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
 			7:30	-	BNT	1933
 			8:00	-	BNT
 
@@ -310,16 +287,16 @@
 # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
-			6:24:40	-	RMT	1920	   # Rangoon Mean Time?
-			6:30	-	BURT	1942 May   # Burma Time
-			9:00	-	JST	1945 May 3
-			6:30	-	MMT		   # Myanmar Time
+Zone	Asia/Rangoon	6:24:40 -	LMT	1880        # or Yangon
+			6:24:40	-	RMT	1920        # Rangoon Mean Time?
+			6:30	-	BURT	1942 May    # Burma Time
+			9:00	-	JST	1945 May  3
+			6:30	-	MMT	# Myanmar Time
 
 # Cambodia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -332,12 +309,12 @@
 # From Bob Devine (1988-01-28):
 # No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
 # China is across 4 physical time zones, before Feb 1, 1986 only the
-# Peking (Bejing) time zone was recognized.  Since that date, China
-# has two of 'em -- Peking's and Urumqi (named after the capital of
+# Peking (Beijing) time zone was recognized.  Since that date, China
+# has two of 'em - Peking's and Ürümqi (named after the capital of
 # the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
 #
 # . . .I just deleted the DST table and this editor makes it too
-# painful to suck in another copy..  So, here is what I have for
+# painful to suck in another copy.  So, here is what I have for
 # DST start/end dates for Peking's time zone (info from AP):
 #
 #     1986 May 4 - Sept 14
@@ -347,15 +324,16 @@
 # CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
 # CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
 
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that China (except for Hong Kong and Macau)
-# has had a single time zone since 1980 May 1, observing summer DST
-# from 1986 through 1991; this contradicts Devine's
-# note about Time magazine, though apparently _something_ happened in 1986.
-# Go with Shanks & Pottenger for now.  I made up names for the other
-# pre-1980 time zones.
+# From Paul Eggert (2008-02-11):
+# Jim Mann, "A clumsy embrace for another western custom: China on daylight
+# time - sort of", Los Angeles Times, 1986-05-05 ... [says] that China began
+# observing daylight saving time in 1986.
 
-# From Shanks & Pottenger:
+# From Paul Eggert (2014-06-30):
+# Shanks & Pottenger have China switching to a single time zone in 1980, but
+# this doesn't seem to be correct.  They also write that China observed summer
+# DST from 1986 through 1991, which seems to match the above commentary, so
+# go with them for DST rules as follows:
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
 Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
@@ -369,7 +347,7 @@
 # historic timezones from some Taiwan websites.  And yes, there are official
 # Chinese names for these locales (before 1949).
 #
-# From Jesper Norgaard Welen (2006-07-14):
+# From Jesper Nørgaard Welen (2006-07-14):
 # I have investigated the timezones around 1970 on the
 # http://www.astro.com/atlas site [with provinces and county
 # boundaries summarized below]....  A few other exceptions were two
@@ -380,65 +358,97 @@
 # (could be true), for the moment I am assuming that those two
 # counties are mistakes in the astro.com data.
 
-# From Paul Eggert (2008-02-11):
-# I just now checked Google News for western news sources that talk
-# about China's single time zone, and couldn't find anything before 1986
-# talking about China being in one time zone.  (That article was: Jim
-# Mann, "A clumsy embrace for another western custom: China on daylight
-# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
-# article confirms the tz database's data claiming that China began
-# observing daylight saving time in 1986.
+# From Paul Eggert (2014-06-30):
+# Alois Treindl kindly sent me translations of the following two sources:
 #
-# From Thomas S. Mullaney (2008-02-11):
-# I think you're combining two subjects that need to treated
-# separately: daylight savings (which, you're correct, wasn't
-# implemented until the 1980s) and the unified time zone centered near
-# Beijing (which was implemented in 1949). Briefly, there was also a
-# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
-# ceased, and the second eventually recognized (again, in the 1980s).
+# (1)
+# Guo Qingsheng (National Time-Service Center, CAS, Xi'an 710600, China)
+# Beijing Time at the Beginning of the PRC
+# China Historical Materials of Science and Technology
+# (Zhongguo ke ji shi liao, 中国科技史料), Vol. 24, No. 1 (2003)
+# It gives evidence that at the beginning of the PRC, Beijing time was
+# officially apparent solar time!  However, Guo also says that the
+# evidence is dubious, as the relevant institute of astronomy had not
+# been taken over by the PRC yet.  It's plausible that apparent solar
+# time was announced but never implemented, and that people continued
+# to use UT+8.  As the Shanghai radio station (and I presume the
+# observatory) was still under control of French missionaries, it
+# could well have ignored any such mandate.
 #
-# From Paul Eggert (2008-06-30):
-# There seems to be a good chance China switched to a single time zone in 1949
-# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
-# reliable documentary source saying so yet, so for now we still go with
-# Shanks & Pottenger.
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# (2)
+# Guo Qing-sheng (Shaanxi Astronomical Observatory, CAS, Xi'an 710600, China)
+# A Study on the Standard Time Changes for the Past 100 Years in China
+# [undated and unknown publication location]
+# It says several things:
+#   * The Qing dynasty used local apparent solar time throughout China.
+#   * The Republic of China instituted Beijing mean solar time effective
+#     the official calendar book of 1914.
+#   * The French Concession in Shanghai set up signal stations in
+#     French docks in the 1890s, controlled by Xujiahui (Zikawei)
+#     Observatory and set to local mean time.
+#   * "From the end of the 19th century" it changed to UT+8.
+#   * Chinese Customs (by then reduced to a tool of foreign powers)
+#     eventually standardized on this time for all ports, and it
+#     became used by railways as well.
+#   * In 1918 the Central Observatory proposed dividing China into
+#     five time zones (see below for details).  This caught on
+#     at first only in coastal areas observing UT+8.
+#   * During WWII all of China was in theory was at UT+7.  In practice
+#     this was ignored in the west, and I presume was ignored in
+#     Japanese-occupied territory.
+#   * Japanese-occupied Manchuria was at UT+9, i.e., Japan time.
+#   * The five-zone plan was resurrected after WWII and officially put into
+#     place (with some modifications) in March 1948.  It's not clear
+#     how well it was observed in areas under Nationalist control.
+#   * The People's Liberation Army used UT+8 during the civil war.
+#
+# An AP article "Shanghai Internat'l Area Little Changed" in the
+# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
+# different - the occupied districts going by Tokyo time, an hour
+# ahead of that prevailing in the rest of Shanghai."  Guess that the
+# Xujiahui Observatory was under French control and stuck with UT+8.
+#
+# In earlier versions of this file, China had many separate Zone entries, but
+# this was based on what were apparently incorrect data in Shanks & Pottenger.
+# This has now been simplified to the two entries Asia/Shanghai and
+# Asia/Urumqi, with the others being links for backward compatibility.
+# Proposed in 1918 and theoretically in effect until 1949 (although in practice
+# mainly observed in coastal areas), the five zones were:
+#
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Asia/Harbin (currently a link to Asia/Shanghai)
 # Heilongjiang (except Mohe county), Jilin
-Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
-			8:30	-	CHAT	1932 Mar # Changbai Time
-			8:00	-	CST	1940
-			9:00	-	CHAT	1966 May
-			8:30	-	CHAT	1980 May
-			8:00	PRC	C%sT
-# Zhongyuan Time ("Central plain Time")
+#
+# Zhongyuan Time ("Central plain Time") UT+8
+# Asia/Shanghai
 # most of China
-# Milne gives 8:05:56.7; round to nearest.
-Zone	Asia/Shanghai	8:05:57	-	LMT	1928
-			8:00	Shang	C%sT	1949
-			8:00	PRC	C%sT
-# Long-shu Time (probably due to Long and Shu being two names of that area)
+# This currently represents most other zones as well,
+# as apparently these regions have been the same since 1970.
+# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
+# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+#
+# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Asia/Chongqing (currently a link to Asia/Shanghai)
 # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
 # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
 # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
 # Yangchun, Yangjiang, Yu'nan, and Yunfu.
-Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
-			7:00	-	LONT	1980 May # Long-shu Time
-			8:00	PRC	C%sT
-# Xin-zang Time ("Xinjiang-Tibet Time")
+#
+# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Asia/Urumqi
+# This currently represents Kunlun Time as well,
+# as apparently the two regions have been the same since 1970.
 # The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
 # the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
 # Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
 # east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
-# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
+# east Xinjiang, including Ürümqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
 # Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
 # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
 # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
-Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
-			6:00	-	URUT	1980 May # Urumqi Time
-			8:00	PRC	C%sT
-# Kunlun Time
+#
+# Kunlun Time UT+5.5
+# Asia/Kashgar (currently a link to Asia/Urumqi)
 # West Tibet, including Pulan, Aheqi, Shufu, Shule;
 # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
 # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
@@ -455,9 +465,9 @@
 # population of Xinjiang, typically use "Xinjiang time" which is two
 # hours behind Beijing time, or UTC +0600. The government of the Xinjiang
 # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
-# local governments such as the Urumqi city government use both times in
+# local governments such as the Ürümqi city government use both times in
 # publications, referring to what is popularly called Xinjiang time as
-# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
+# "Ürümqi time." When Uyghurs make an appointment in the Uyghur language
 # they almost invariably use Xinjiang time.
 #
 # (Their ethnic Han compatriots would typically have no clue of its
@@ -469,21 +479,6 @@
 # the province not having dual times but four times in use at the same
 # time. Some areas remained on standard Xinjiang time or Beijing time and
 # others moving their clocks ahead.)
-#
-# ...an example of an official website using of Urumqi time.
-#
-# The first few lines of the Google translation of
-# <a href="http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39">
-# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
-# </a>
-# (retrieved 2009-10-13)
-# > Urumqi fire seven people are missing the alleged losses of at least
-# > 500 million yuan
-# >
-# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
-# > Urumqi City Department of International Plaza Luther Qiantang River
-# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
-# > have worked continuously for 22 hours...
 
 # From Luther Ma (2009-11-19):
 # With the risk of being redundant to previous answers these are the most common
@@ -494,7 +489,7 @@
 # 3. Urumqi...
 # 4. Kashgar...
 # ...
-# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
+# 5. It seems that Uyghurs in Ürümqi has been using Xinjiang since at least the
 # 1960's. I know of one Han, now over 50, who grew up in the surrounding
 # countryside and used Xinjiang time as a child.
 #
@@ -506,10 +501,55 @@
 # Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
 # not be using Beijing time, but some local time.)
 
-Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
-			5:30	-	KAST	1940	 # Kashgar Time
-			5:00	-	KAST	1980 May
+# From David Cochrane (2014-03-26):
+# Just a confirmation that Ürümqi time was implemented in Ürümqi on 1 Feb 1986:
+# http://content.time.com/time/magazine/article/0,9171,960684,00.html
+
+# From Luther Ma (2014-04-22):
+# I have interviewed numerous people of various nationalities and from
+# different localities in Xinjiang and can confirm the information in Guo's
+# report regarding Xinjiang, as well as the Time article reference by David
+# Cochrane.  Whether officially recognized or not (and both are officially
+# recognized), two separate times have been in use in Xinjiang since at least
+# the Cultural Revolution: Xinjiang Time (XJT), aka Ürümqi Time or local time;
+# and Beijing Time.  There is no confusion in Xinjiang as to which name refers
+# to which time. Both are widely used in the province, although in some
+# population groups might be use one to the exclusion of the other.  The only
+# problem is that computers and smart phones list Ürümqi (or Kashgar) as
+# having the same time as Beijing.
+
+# From Paul Eggert (2014-06-30):
+# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
+# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
+# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
+# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
+#
+# Xinjiang Time is well-documented as being officially recognized.  E.g., see
+# "The Working-Calendar for The Xinjiang Uygur Autonomous Region Government"
+# <http://www.sinkiang.gov.cn/service/ourworking/> (2014-04-22).
+# Unfortunately, we have no good records of time in Xinjiang before 1986.
+# During the 20th century parts of Xinjiang were ruled by the Qing dynasty,
+# the Republic of China, various warlords, the First and Second East Turkestan
+# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
+# China, and tracking down all these organizations' timekeeping rules would be
+# quite a trick.  Approximate this lost history by a transition from LMT to
+# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# which happens to be the date given by Shanks & Pottenger (no doubt as a
+# guess) as the transition from LMT.  Ignore the usage of UT+8 before
+# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# that the sort of users who prefer Asia/Urumqi now typically ignored the
+# UT+8 mandate back then.
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Beijing time, used throughout China; represented by Shanghai.
+Zone	Asia/Shanghai	8:05:43	-	LMT	1901
+			8:00	Shang	C%sT	1949
 			8:00	PRC	C%sT
+# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
+# / Wulumuqi.  (Please use Asia/Shanghai if you prefer Beijing time.)
+Zone	Asia/Urumqi	5:50:20	-	LMT	1928
+			6:00	-	XJT
 
 
 # Hong Kong (Xianggang)
@@ -524,15 +564,11 @@
 # and incorrect rules. Although the exact switch over time is missing, I
 # think 3:30 is correct. The official DST record for Hong Kong can be
 # obtained from
-# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# </a>.
 
 # From Arthur David Olson (2009-10-28):
 # Here are the dates given at
-# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# </a>
 # as of 2009-10-28:
 # Year        Period
 # 1941        1 Apr to 30 Sep
@@ -612,35 +648,113 @@
 
 # Taiwan
 
-# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
-# was still controlled by Japan.  This is hard to believe, but we don't
-# have any other information.
-
 # From smallufo (2010-04-03):
-# According to Taiwan's CWB,
-# <a href="http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm">
+# According to Taiwan's CWB [Central Weather Bureau],
 # http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
-# </a>
 # Taipei has DST in 1979 between July 1st and Sep 30.
 
-# From Arthur David Olson (2010-04-07):
-# Here's Google's translation of the table at the bottom of the "summert.htm" page:
-# Decade 	                                                    Name                      Start and end date
-# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
-# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
-# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
-# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
-# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
-# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
-# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
-# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
-# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
-# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
-# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
+# From Yu-Cheng Chuang (2013-07-12):
+# On Dec 28, 1895, the Meiji Emperor announced Ordinance No. 167 of
+# Meiji Year 28 "The clause about standard time", mentioned that
+# Taiwan and Penghu Islands, as well as Yaeyama and Miyako Islands
+# (both in Okinawa) adopt the Western Standard Time which is based on
+# 120E. The adoption began from Jan 1, 1896. The original text can be
+# found on Wikisource:
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+# ... This could be the first adoption of time zone in Taiwan, because
+# during the Qing Dynasty, it seems that there was no time zone
+# declared officially.
+#
+# Later, in the beginning of World War II, on Sep 25, 1937, the Showa
+# Emperor announced Ordinance No. 529 of Showa Year 12 "The clause of
+# revision in the ordinance No. 167 of Meiji year 28 about standard
+# time", in which abolished the adoption of Western Standard Time in
+# western islands (listed above), which means the whole Japan
+# territory, including later occupations, adopt Japan Central Time
+# (UTC+9). The adoption began on Oct 1, 1937. The original text can
+# be found on Wikisource:
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
+#
+# That is, the time zone of Taipei switched to UTC+9 on Oct 1, 1937.
+
+# From Yu-Cheng Chuang (2014-07-02):
+# I've found more evidence about when the time zone was switched from UTC+9
+# back to UTC+8 after WW2.  I believe it was on Sep 21, 1945.  In a document
+# during Japanese era [1] in which the officer told the staff to change time
+# zone back to Western Standard Time (UTC+8) on Sep 21.  And in another
+# history page of National Cheng Kung University [2], on Sep 21 there is a
+# note "from today, switch back to Western Standard Time".  From these two
+# materials, I believe that the time zone change happened on Sep 21.  And
+# today I have found another monthly journal called "The Astronomical Herald"
+# from The Astronomical Society of Japan [3] in which it mentioned the fact
+# that:
+#
+# 1. Standard Time of the Country (Japan) was adopted on Jan 1, 1888, using
+# the time at 135E (GMT+9)
+#
+# 2. Standard Time of the Country was renamed to Central Standard Time, on Jan
+# 1, 1898, and on the same day, the new territories Taiwan and Penghu islands,
+# as well as Yaeyama and Miyako islands, adopted a new time zone called
+# Western Standard Time, which is in GMT+8.
+#
+# 3. Western Standard Time was deprecated on Sep 30, 1937. From then all the
+# territories of Japan adopted the same time zone, which is Central Standard
+# Time.
+#
+# [1] Academica Historica, Taiwan:
+# http://163.29.208.22:8080/govsaleShowImage/connect_img.php?s=00101738900090036&e=00101738900090037
+# [2] Nat'l Cheng Kung University 70th Anniversary Special Site:
+# http://www.ncku.edu.tw/~ncku70/menu/001/01_01.htm
+# [3] Yukio Niimi, The Standard Time in Japan (1997), p.475:
+# http://www.asj.or.jp/geppou/archive_open/1997/pdf/19971001c.pdf
+
+# Yu-Cheng Chuang (2014-07-03):
+# I finally have found the real official gazette about changing back to
+# Western Standard Time on Sep 21 in Taiwan.  It's Taiwan Governor-General
+# Bulletin No. 386 in Showa 20 years (1945), published on Sep 19, 1945. [1] ...
+# [It] abolishes Bulletin No. 207 in Showa 12 years (1937), which is a local
+# bulletin in Taiwan for that Ordinance No. 529. It also mentioned that 1am on
+# Sep 21, 1945 will be 12am on Sep 21.  I think this bulletin is much more
+# official than the one I mentioned in my first mail, because it's from the
+# top-level government in Taiwan. If you're going to quote any resource, this
+# would be a good one.
+# [1] Taiwan Governor-General Gazette, No. 1018, Sep 19, 1945:
+# http://db2.th.gov.tw/db2/view/viewImg.php?imgcode=0072031018a&num=19&bgn=019&end=019&otherImg=&type=gener
+
+# From Yu-Cheng Chuang (2014-07-02):
+# In 1946, DST in Taiwan was from May 15 and ended on Sep 30. The info from
+# Central Weather Bureau website was not correct.
+#
+# Original Bulletin:
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=03502F0AKM1AF
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0350300AKM1B0 (cont.)
+#
+# In 1947, DST in Taiwan was expanded to Oct 31. There is a backup of that
+# telegram announcement from Taiwan Province Government:
+#
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0360310AKZ431
+#
+# Here is a brief translation:
+#
+#   The Summer Time this year is adopted from midnight Apr 15 until Sep 20
+#   midnight. To save (energy?) consumption, we're expanding Summer Time
+#   adoption till Oct 31 midnight.
+#
+# The Central Weather Bureau website didn't mention that, however it can
+# be found from historical government announcement database.
+
+# From Paul Eggert (2014-07-03):
+# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
+# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
-Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
+Rule	Taiwan	1946	only	-	May	15	0:00	1:00	D
+Rule	Taiwan	1946	only	-	Oct	1	0:00	0	S
+Rule	Taiwan	1947	only	-	Apr	15	0:00	1:00	D
+Rule	Taiwan	1947	only	-	Nov	1	0:00	0	S
+Rule	Taiwan	1948	1951	-	May	1	0:00	1:00	D
+Rule	Taiwan	1948	1951	-	Oct	1	0:00	0	S
 Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
 Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
 Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
@@ -648,11 +762,14 @@
 Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
-Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
-Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
+Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
+Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
+# Taipei or Taibei or T'ai-pei
+Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
+			8:00	-	JWST	1937 Oct  1
+			9:00	-	JST	1945 Sep 21  1:00
 			8:00	Taiwan	C%sT
 
 # Macau (Macao, Aomen)
@@ -672,7 +789,7 @@
 Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
 Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Macau	7:34:20 -	LMT	1912
+Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
 			8:00	Macau	MO%sT	1999 Dec 20 # return to China
 			8:00	PRC	C%sT
 
@@ -721,7 +838,7 @@
 # republic has changed its time zone back to that of Moscow.  As a result it
 # is now just four hours ahead of Greenwich Mean Time, rather than five hours
 # ahead.  The switch was decreed by the pro-Western president of Georgia,
-# Mikhail Saakashvili, who said the change was partly prompted by the process
+# Mikheil Saakashvili, who said the change was partly prompted by the process
 # of integration into Europe.
 
 # From Teimuraz Abashidze (2005-11-07):
@@ -734,29 +851,31 @@
 # I don't know what can be done, especially knowing that some years ago our
 # DST rules where changed THREE TIMES during one month.
 
+# Milne 1899 says Tbilisi (Tiflis) time was 2:59:05.7.
+# Byalokoz 1919 says Georgia was 2:59:11.
+# Go with Byalokoz.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
-			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
+Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
+			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
 			3:00	-	TBIT	1957 Mar    # Tbilisi Time
-			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia TBI%sT	1991 Mar 31  2:00s
 			3:00	1:00	TBIST	1991 Apr  9 # independence
-			3:00 RussiaAsia GE%sT	1992 # Georgia Time
+			3:00 RussiaAsia GE%sT	1992        # Georgia Time
 			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
 			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
 			4:00	1:00	GEST	1997 Mar lastSun
 			4:00 E-EurAsia	GE%sT	2004 Jun 27
-			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
+			3:00 RussiaAsia	GE%sT	2005 Mar lastSun  2:00
 			4:00	-	GET
 
 # East Timor
 
 # See Indonesia for the 1945 transition.
 
-# From Joao Carrascalao, brother of the former governor of East Timor, in
-# <a href="http://etan.org/et99c/december/26-31/30ETMAY.htm">
+# From João Carrascalão, brother of the former governor of East Timor, in
 # East Timor may be late for its millennium
-# </a> (1999-12-26/31):
+# <http://etan.org/et99c/december/26-31/30ETMAY.htm> (1999-12-26/31):
 # Portugal tried to change the time forward in 1974 because the sun
 # rises too early but the suggestion raised a lot of problems with the
 # Timorese and I still don't think it would work today because it
@@ -766,25 +885,25 @@
 # We don't have any record of the above attempt.
 # Most likely our records are incomplete, but we have no better data.
 
-# <a href="http://www.hri.org/news/world/undh/last/00-08-16.undh.html">
 # From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
-# (2000-08-16)</a>:
+# http://www.hri.org/news/world/undh/2000/00-08-16.undh.html
+# (2000-08-16):
 # The Cabinet of the East Timor Transition Administration decided
 # today to advance East Timor's time by one hour.  The time change,
 # which will be permanent, with no seasonal adjustment, will happen at
 # midnight on Saturday, September 16.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Dili	8:22:20 -	LMT	1912
+Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
 			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
 			9:00	-	JST	1945 Sep 23
 			9:00	-	TLT	1976 May  3
-			8:00	-	WITA	2000 Sep 17 00:00
+			8:00	-	WITA	2000 Sep 17  0:00
 			9:00	-	TLT
 
 # India
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
+Zone	Asia/Kolkata	5:53:28 -	LMT	1880        # Kolkata
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
 			6:30	-	BURT	1942 May 15 # Burma Time
 			5:30	-	IST	1942 Sep
@@ -798,7 +917,7 @@
 # Indonesia
 #
 # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
-# <http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime>
+# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
 # says that Indonesia's time zones changed on 1988-01-01.  Looking at some
 # time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
 # and Kalimantan Tengah) switching from UTC+8 to UTC+7.
@@ -810,7 +929,7 @@
 # other formal surrender ceremonies were September 9, 11, and 13, plus
 # September 12 for the regional surrender to Mountbatten in Singapore.
 # These would be the earliest possible times for a change.
-# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
+# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
 # Traditionnelles, 1987, Paris) says that Java and Madura switched
 # from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
 # (Hollandia).  For now, assume all Indonesian locations other than Jayapura
@@ -835,7 +954,7 @@
 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
 # but this must be a typo.
 			7:07:12	-	BMT	1923 Dec 31 23:47:12 # Batavia
-			7:20	-	JAVT	1932 Nov	 # Java Time
+			7:20	-	JAVT	1932 Nov    # Java Time
 			7:30	-	WIB	1942 Mar 23
 			9:00	-	JST	1945 Sep 23
 			7:30	-	WIB	1948 May
@@ -861,7 +980,7 @@
 # Maluku Islands, West Papua, Papua
 Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 			9:00	-	WIT	1944 Sep  1
-			9:30	-	CST	1964
+			9:30	-	ACST	1964
 			9:00	-	WIT
 
 # Iran
@@ -927,7 +1046,7 @@
 # Several of my users have reported that Iran will not observe DST anymore:
 # http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
 #
-# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
+# From Reuters (2007-09-16), with a heads-up from Jesper Nørgaard Welen:
 # ... the Guardian Council ... approved a law on Sunday to re-introduce
 # daylight saving time ...
 # http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
@@ -993,7 +1112,7 @@
 Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
-			3:25:44	-	TMT	1946	# Tehran Mean Time
+			3:25:44	-	TMT	1946     # Tehran Mean Time
 			3:30	-	IRST	1977 Nov
 			4:00	Iran	IR%sT	1979
 			3:30	Iran	IR%sT
@@ -1018,17 +1137,11 @@
 # From Steffen Thorsen (2008-03-10):
 # The cabinet in Iraq abolished DST last week, according to the following
 # news sources (in Arabic):
-# <a href="http://www.aljeeran.net/wesima_articles/news-20080305-98602.html">
 # http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
-# </a>
-# <a href="http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10">
 # http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
-# </a>
 #
 # We have published a short article in English about the change:
-# <a href="http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html">
 # http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
@@ -1037,14 +1150,14 @@
 Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
 Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
 Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
-# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the ':01' is a typo.
 # Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
 #
 Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
 Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baghdad	2:57:40	-	LMT	1890
-			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
+			2:57:36	-	BMT	1918     # Baghdad Mean Time?
 			3:00	-	AST	1982 May
 			3:00	Iraq	A%sT
 
@@ -1272,7 +1385,7 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
-			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
+			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
 			2:00	Zion	I%sT
 
 
@@ -1281,15 +1394,15 @@
 
 # Japan
 
-# `9:00' and `JST' is from Guy Harris.
+# '9:00' and 'JST' is from Guy Harris.
 
 # From Paul Eggert (1995-03-06):
 # Today's _Asahi Evening News_ (page 4) reports that Japan had
-# daylight saving between 1948 and 1951, but ``the system was discontinued
-# because the public believed it would lead to longer working hours.''
+# daylight saving between 1948 and 1951, but "the system was discontinued
+# because the public believed it would lead to longer working hours."
 
-# From Mayumi Negishi in the 2005-08-10 Japan Times
-# <http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm>:
+# From Mayumi Negishi in the 2005-08-10 Japan Times:
+# http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm
 # Occupation authorities imposed daylight-saving time on Japan on
 # [1948-05-01]....  But lack of prior debate and the execution of
 # daylight-saving time just three days after the bill was passed generated
@@ -1313,7 +1426,8 @@
 
 # From Hideyuki Suzuki (1998-11-09):
 # 'Tokyo' usually stands for the former location of Tokyo Astronomical
-# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# Observatory: 139 degrees 44' 40.90" E (9h 18m 58.727s),
+# 35 degrees 39' 16.0" N.
 # This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
 # edited by National Astronomical Observatory of Japan....
 # JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
@@ -1321,10 +1435,10 @@
 
 # From Hideyuki Suzuki (1998-11-16):
 # The ordinance No. 51 (1886) established "standard time" in Japan,
-# which stands for the time on E 135 degree.
+# which stands for the time on 135 degrees E.
 # In the ordinance No. 167 (1895), "standard time" was renamed to "central
 # standard time".  And the same ordinance also established "western standard
-# time", which stands for the time on E 120 degree....  But "western standard
+# time", which stands for the time on 120 degrees E....  But "western standard
 # time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
 # 167, there is no mention regarding for what place western standard time is
 # standard....
@@ -1332,27 +1446,33 @@
 # I wrote "ordinance" above, but I don't know how to translate.
 # In Japanese it's "chokurei", which means ordinance from emperor.
 
-# Shanks & Pottenger claim JST in use since 1896, and that a few
-# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
-# ordinances took effect on Jan 1.
+# From Yu-Cheng Chuang (2013-07-12):
+# ...the Meiji Emperor announced Ordinance No. 167 of Meiji Year 28 "The clause
+# about standard time" ... The adoption began from Jan 1, 1896.
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+#
+# ...the Showa Emperor announced Ordinance No. 529 of Showa Year 12 ... which
+# means the whole Japan territory, including later occupations, adopt Japan
+# Central Time (UTC+9). The adoption began on Oct 1, 1937.
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
-			9:00	-	JST	1896
-			9:00	-	CJT	1938
+			9:00	-	JST	1896 Jan  1
+			9:00	-	JCST	1937 Oct  1
 			9:00	Japan	J%sT
 # Since 1938, all Japanese possessions have been like Asia/Tokyo.
 
 # Jordan
 #
-# From <a href="http://star.arabia.com/990701/JO9.html">
-# Jordan Week (1999-07-01) </a> via Steffen Thorsen (1999-09-09):
+# From <http://star.arabia.com/990701/JO9.html>
+# Jordan Week (1999-07-01) via Steffen Thorsen (1999-09-09):
 # Clocks in Jordan were forwarded one hour on Wednesday at midnight,
 # in accordance with the government's decision to implement summer time
 # all year round.
 #
-# From <a href="http://star.arabia.com/990930/JO9.html">
-# Jordan Week (1999-09-30) </a> via Steffen Thorsen (1999-11-09):
+# From <http://star.arabia.com/990930/JO9.html>
+# Jordan Week (1999-09-30) via Steffen Thorsen (1999-11-09):
 # Winter time starts today Thursday, 30 September. Clocks will be turned back
 # by one hour.  This is the latest government decision and it's final!
 # The decision was taken because of the increase in working hours in
@@ -1372,9 +1492,7 @@
 
 # From Steffen Thorsen (2009-04-02):
 # This single one might be good enough, (2009-03-24, Arabic):
-# <a href="http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279">
 # http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
-# </a>
 #
 # Google's translation:
 #
@@ -1465,9 +1583,8 @@
 # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
 # - Oral switched from +5:00 to +4:00 in spring 1989.
 
-# <a href="http://www.kazsociety.org.uk/news/2005/03/30.htm">
-# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
-# </a>
+# From Kazakhstan Embassy's News Bulletin #11
+# <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
 # The Government of Kazakhstan passed a resolution March 15 abolishing
 # daylight saving time citing lack of economic benefits and health
 # complications coupled with a decrease in productivity.
@@ -1500,10 +1617,10 @@
 			6:00	-	KIZT	1982 Apr  1
 			5:00 RussiaAsia	KIZ%sT	1991
 			5:00	-	KIZT	1991 Dec 16 # independence
-			5:00	-	QYZT	1992 Jan 19 2:00
+			5:00	-	QYZT	1992 Jan 19  2:00
 			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
 			6:00	-	QYZT
-# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
+# Aqtobe (aka Aktobe, formerly Aktyubinsk)
 Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
 			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
 			5:00	-	AKTT	1981 Apr  1
@@ -1523,7 +1640,7 @@
 			6:00	-	SHET	1982 Apr  1
 			5:00 RussiaAsia	SHE%sT	1991
 			5:00	-	SHET	1991 Dec 16 # independence
-			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
+			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun  2:00 # Aqtau Time
 			4:00 RussiaAsia	AQT%sT	2005 Mar 15
 			5:00	-	AQTT
 # West Kazakhstan
@@ -1532,7 +1649,7 @@
 			5:00	-	URAT	1981 Apr  1
 			5:00	1:00	URAST	1981 Oct  1
 			6:00	-	URAT	1982 Apr  1
-			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
+			5:00 RussiaAsia	URA%sT	1989 Mar 26  2:00
 			4:00 RussiaAsia	URA%sT	1991
 			4:00	-	URAT	1991 Dec 16 # independence
 			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
@@ -1543,7 +1660,7 @@
 
 # From Paul Eggert (2005-08-15):
 # According to an article dated today in the Kyrgyzstan Development Gateway
-# <http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml>
+# http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml
 # Kyrgyzstan is canceling the daylight saving time system.  I take the article
 # to mean that they will leave their clocks at 6 hours ahead of UTC.
 # From Malik Abdugaliev (2005-09-21):
@@ -1558,17 +1675,17 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
 			5:00	-	FRUT	1930 Jun 21 # Frunze Time
-			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
-			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
-			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
+			6:00 RussiaAsia FRU%sT	1991 Mar 31  2:00s
+			5:00	1:00	FRUST	1991 Aug 31  2:00 # independence
+			5:00	Kyrgyz	KG%sT	2005 Aug 12 # Kyrgyzstan Time
 			6:00	-	KGT
 
 ###############################################################################
 
 # Korea (North and South)
 
-# From Annie I. Bang (2006-07-10) in
-# <http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp>:
+# From Annie I. Bang (2006-07-10):
+# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
 # The Ministry of Commerce, Industry and Energy has already
 # commissioned a research project [to reintroduce DST] and has said
 # the system may begin as early as 2008....  Korea ran a daylight
@@ -1581,19 +1698,29 @@
 Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
 Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
 
+# From Paul Eggert (2014-07-01):
+# The following entries are from Shanks & Pottenger, except that I
+# guessed that time zone abbreviations through 1945 followed the same
+# rules as discussed under Taiwan, with nominal switches from JST to KST
+# when the respective cities were taken over by the Allies after WWII.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Sep  8
 			9:00	-	KST	1954 Mar 21
 			8:00	ROK	K%sT	1961 Aug 10
 			8:30	-	KST	1968 Oct
 			9:00	ROK	K%sT
 Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Aug 24
 			9:00	-	KST	1954 Mar 21
 			8:00	-	KST	1961 Aug 10
 			9:00	-	KST
@@ -1602,21 +1729,13 @@
 
 # Kuwait
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# From the Arab Times (2007-03-14):
-# The Civil Service Commission (CSC) has approved a proposal forwarded
-# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
-# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
-# <http://www.arabtimesonline.com/arabtimes/kuwait/Viewdet.asp?ID=9950>.
-# From Paul Eggert (2007-03-29):
-# We don't know the details, or whether the approval means it'll happen,
-# so for now we assume no DST.
 Zone	Asia/Kuwait	3:11:56 -	LMT	1950
 			3:00	-	AST
 
 # Laos
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9       # or Viangchan
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -1657,8 +1776,8 @@
 Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
 #
 # peninsular Malaysia
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -1670,12 +1789,12 @@
 			7:30	-	MALT	1982 Jan  1
 			8:00	-	MYT	# Malaysia Time
 # Sabah & Sarawak
-# From Paul Eggert (2006-03-22):
-# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
-# transition dates are from Mok Ly Yng.
+# From Paul Eggert (2014-08-12):
+# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
+# and 1982 transition dates are from Mok Ly Yng.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
-			7:30	-	BORT	1933	# Borneo Time
+			7:30	-	BORT	1933        # Borneo Time
 			8:00	NBorneo	BOR%sT	1942 Feb 16
 			9:00	-	JST	1945 Sep 12
 			8:00	-	BORT	1982 Jan  1
@@ -1683,22 +1802,21 @@
 
 # Maldives
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
-			4:54:00	-	MMT	1960	# Male Mean Time
-			5:00	-	MVT		# Maldives Time
+Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Male
+			4:54:00	-	MMT	1960 # Male Mean Time
+			5:00	-	MVT	# Maldives Time
 
 # Mongolia
 
 # Shanks & Pottenger say that Mongolia has three time zones, but
-# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
-# both say that it has just one.
+# The USNO (1995-12-21) and the CIA map Standard Time Zones of the World
+# (2005-03) both say that it has just one.
 
 # From Oscar van Vlijmen (1999-12-11):
-# <a href="http://www.mongoliatourism.gov.mn/general.htm">
 # General Information Mongolia
-# </a> (1999-09)
+# <http://www.mongoliatourism.gov.mn/general.htm> (1999-09)
 # "Time: Mongolia has two time zones. Three westernmost provinces of
-# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# Bayan-Ölgii, Uvs, and Hovd are one hour earlier than the capital city, and
 # the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
 # eight hours."
 
@@ -1709,7 +1827,7 @@
 # of implementation may have been different....
 # Some maps in the past have indicated that there was an additional time
 # zone in the eastern part of Mongolia, including the provinces of Dornod,
-# Suhbaatar, and possibly Khentij.
+# Sükhbaatar, and possibly Khentii.
 
 # From Paul Eggert (1999-12-15):
 # Naming and spelling is tricky in Mongolia.
@@ -1723,10 +1841,10 @@
 # (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
 # there are three time zones.
 #
-# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
-# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
-#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
-# Provinces [at 9:00]: Dornod, Sukhbaatar
+# Provinces [at 7:00]: Bayan-Ölgii, Uvs, Khovd, Zavkhan, Govi-Altai
+# Provinces [at 8:00]: Khövsgöl, Bulgan, Arkhangai, Khentii, Töv,
+#	Bayankhongor, Övörkhangai, Dundgovi, Dornogovi, Ömnögovi
+# Provinces [at 9:00]: Dornod, Sükhbaatar
 #
 # [The province of Selenge is omitted from the above lists.]
 
@@ -1743,16 +1861,16 @@
 # We have wildly conflicting information about Mongolia's time zones.
 # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
 # there is only one time zone and that DST is observed, citing Microsoft
-# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
+# Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
 # travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
 # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
 # Washington, DC says there are two time zones, with DST observed.
 # He also found
-# <http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&>
+# http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&
 # which also says that there is DST, and which has a comment by "Toddius"
 # (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
 # The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
-# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
+# and some Eastern provinces are +9 GMT but Sükhbaatar Aimag is SUHK +8.5 GMT.
 # The SUKH timezone is new this year, it is one of the few things the
 # parliament passed during the tumultuous winter session."
 # For now, let's ignore this information, until we have more confirmation.
@@ -1768,29 +1886,23 @@
 # +08:00 instead. Different sources appear to disagree with the tz
 # database on this, e.g.:
 #
-# <a href="http://www.timeanddate.com/worldclock/city.html?n=1026">
 # http://www.timeanddate.com/worldclock/city.html?n=1026
-# </a>
-# <a href="http://www.worldtimeserver.com/current_time_in_MN.aspx">
 # http://www.worldtimeserver.com/current_time_in_MN.aspx
-# </a>
 #
 # both say GMT+08:00.
 
 # From Steffen Thorsen (2008-03-31):
 # eznis airways, which operates several domestic flights, has a flight
 # schedule here:
-# <a href="http://www.eznis.com/Container.jsp?id=112">
 # http://www.eznis.com/Container.jsp?id=112
-# </a>
 # (click the English flag for English)
 #
-# There it appears that flights between Choibalsan and Ulaanbatar arrive
+# There it appears that flights between Choibalsan and Ulaanbaatar arrive
 # about 1:35 - 1:50 hours later in local clock time, no matter the
-# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
-# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
+# direction, while Ulaanbaatar-Khovd takes 2 hours in the Eastern
+# direction and 3:35 back, which indicates that Ulaanbaatar and Khovd are
 # in different time zones (like we know about), while Choibalsan and
-# Ulaanbatar are in the same time zone (correction needed).
+# Ulaanbaatar are in the same time zone (correction needed).
 
 # From Arthur David Olson (2008-05-19):
 # Assume that Choibalsan is indeed offset by 8:00.
@@ -1806,7 +1918,7 @@
 # (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
 #
 # Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
-# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
+# in Choibalsan (more precisely, in Dornod and Sükhbaatar) took place
 # at 02:00 standard time, not at 00:00 local time as in the rest of
 # the country.  That would be odd, and possibly is a result of their
 # correction of 02:00 (in the previous edition) not being done correctly
@@ -1822,13 +1934,13 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
 Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
-			6:00	-	HOVT	1978	# Hovd Time
+			6:00	-	HOVT	1978     # Hovd Time
 			7:00	Mongol	HOV%sT
 # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
 Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
-			7:00	-	ULAT	1978	# Ulaanbaatar Time
+			7:00	-	ULAT	1978     # Ulaanbaatar Time
 			8:00	Mongol	ULA%sT
-# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
+# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan,
 # Choybalsan, Sanbejse, Tchoibalsan
 Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
 			7:00	-	ULAT	1978
@@ -1860,7 +1972,7 @@
 # 00:01 was to make it clear which day it was on.
 
 # From Paul Eggert (2002-03-15):
-# Jesper Norgaard found this URL:
+# Jesper Nørgaard found this URL:
 # http://www.pak.gov.pk/public/news/app/app06_dec.htm
 # (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
 # advance the clocks by one hour on the night between the first
@@ -1892,43 +2004,30 @@
 # Here is an article that Pakistan plan to introduce Daylight Saving Time
 # on June 1, 2008 for 3 months.
 #
-# "... The federal cabinet on Wednesday announced a new conservation plan to help
-# reduce load shedding by approving the closure of commercial centres at 9pm and
-# moving clocks forward by one hour for the next three months.
-# ...."
+# "... The federal cabinet on Wednesday announced a new conservation plan to
+# help reduce load shedding by approving the closure of commercial centres at
+# 9pm and moving clocks forward by one hour for the next three months. ...."
 #
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html">
 # http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
-# </a>
-# OR
-# <a href="http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4">
 # http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
-# </a>
 
 # From Arthur David Olson (2008-05-19):
 # XXX--midnight transitions is a guess; 2008 only is a guess.
 
 # From Alexander Krivenyshev (2008-08-28):
 # Pakistan government has decided to keep the watches one-hour advanced
-# for another 2 months--plan to return to Standard Time on October 31
+# for another 2 months - plan to return to Standard Time on October 31
 # instead of August 31.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
-# </a>
-# OR
-# <a href="http://dailymailnews.com/200808/28/news/dmbrn03.html">
 # http://dailymailnews.com/200808/28/news/dmbrn03.html
-# </a>
 
 # From Alexander Krivenyshev (2009-04-08):
 # Based on previous media reports that "... proposed plan to
 # advance clocks by one hour from May 1 will cause disturbance
 # to the working schedules rather than bringing discipline in
 # official working."
-# <a href="http://www.thenews.com.pk/daily_detail.asp?id=171280">
 # http://www.thenews.com.pk/daily_detail.asp?id=171280
-# </a>
 #
 # recent news that instead of May 2009 - Pakistan plan to
 # introduce DST from April 15, 2009
@@ -1936,15 +2035,8 @@
 # FYI: Associated Press Of Pakistan
 # April 08, 2009
 # Cabinet okays proposal to advance clocks by one hour from April 15
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
-# </a>
-#
-# or
-#
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
-# </a>
 #
 # ....
 # The Federal Cabinet on Wednesday approved the proposal to
@@ -1957,34 +2049,20 @@
 # clocks backward by one hour from October 1. A formal announcement to
 # this effect will be made after the Prime Minister grants approval in
 # this regard."
-# <a href="http://www.thenews.com.pk/updates.asp?id=87168">
 # http://www.thenews.com.pk/updates.asp?id=87168
-# </a>
 
 # From Alexander Krivenyshev (2009-09-28):
 # According to Associated Press Of Pakistan, it is confirmed that
-# Pakistan clocks across the country would be turned back by an hour from October
-# 1, 2009.
+# Pakistan clocks across the country would be turned back by an hour from
+# October 1, 2009.
 #
 # "Clocks to go back one hour from 1 Oct"
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
-# </a>
-
+#
 # From Steffen Thorsen (2009-09-29):
-# Alexander Krivenyshev wrote:
-# > According to Associated Press Of Pakistan, it is confirmed that
-# > Pakistan clocks across the country would be turned back by an hour from October
-# > 1, 2009.
-#
 # Now they seem to have changed their mind, November 1 is the new date:
-# <a href="http://www.thenews.com.pk/top_story_detail.asp?Id=24742">
 # http://www.thenews.com.pk/top_story_detail.asp?Id=24742
-# </a>
 # "The country's clocks will be reversed by one hour on November 1.
 # Officials of Federal Ministry for Interior told this to Geo News on
 # Monday."
@@ -1996,11 +2074,9 @@
 #
 # We have confirmed this year's end date with both with the Ministry of
 # Water and Power and the Pakistan Electric Power Company:
-# <a href="http://www.timeanddate.com/news/time/pakistan-ends-dst09.html">
 # http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
-# </a>
 
-# From Christoph Goehre (2009-10-01):
+# From Christoph Göhre (2009-10-01):
 # [T]he German Consulate General in Karachi reported me today that Pakistan
 # will go back to standard time on 1st of November.
 
@@ -2016,22 +2092,17 @@
 # Now, it seems that the decision to not observe DST in final:
 #
 # "Govt Withdraws Plan To Advance Clocks"
-# <a href="http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041">
 # http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
-# </a>
 #
 # "People laud PM's announcement to end DST"
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
 Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
 Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
-Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
+Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
 Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
-Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
@@ -2105,10 +2176,9 @@
 # the PA has decided to implement DST in April.
 
 # From Paul Eggert (1999-09-20):
-# Daoud Kuttab writes in
-# <a href="http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html">
-# Holiday havoc
-# </a> (Jerusalem Post, 1999-04-22) that
+# Daoud Kuttab writes in Holiday havoc
+# http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html
+# (Jerusalem Post, 1999-04-22) that
 # the Palestinian National Authority changed to DST on 1999-04-15.
 # I vaguely recall that they switch back in October (sorry, forgot the source).
 # For now, let's assume that the spring switch was at 24:00,
@@ -2121,7 +2191,7 @@
 # A user from Gaza reported that Gaza made the change early because of
 # the Ramadan.  Next year Ramadan will be even earlier, so I think
 # there is a good chance next year's end date will be around two weeks
-# earlier--the same goes for Jordan.
+# earlier - the same goes for Jordan.
 
 # From Steffen Thorsen (2006-08-17):
 # I was informed by a user in Bethlehem that in Bethlehem it started the
@@ -2140,7 +2210,7 @@
 # I guess it is likely that next year's date will be moved as well,
 # because of the Ramadan.
 
-# From Jesper Norgaard Welen (2007-09-18):
+# From Jesper Nørgaard Welen (2007-09-18):
 # According to Steffen Thorsen's web site the Gaza Strip and the rest of the
 # Palestinian territories left DST early on 13.th. of September at 2:00.
 
@@ -2157,16 +2227,9 @@
 # Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
 # the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
 #
-# <a href="http://www.guardian.co.uk/world/feedarticle/7759001">
 # http://www.guardian.co.uk/world/feedarticle/7759001
-# </a>
-# <a href="http://www.abcnews.go.com/International/wireStory?id=5676087">
 # http://www.abcnews.go.com/International/wireStory?id=5676087
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-26):
 # According to the Palestine News Network (arabic.pnn.ps), Palestinian
@@ -2174,24 +2237,17 @@
 # 26 and continue until the night of 27 September 2009.
 #
 # (in Arabic)
-# <a href="http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850">
 # http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
-# </a>
 #
-# or
 # (English translation)
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_westbank01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
-# </a>
 
 # From Steffen Thorsen (2009-08-31):
 # Palestine's Council of Ministers announced that they will revert back to
 # winter time on Friday, 2009-09-04.
 #
 # One news source:
-# <a href="http://www.safa.ps/ara/?action=showdetail&seid=4158">
 # http://www.safa.ps/ara/?action=showdetail&seid=4158
-# </a>
 # (Palestinian press agency, Arabic),
 # Google translate: "Decided that the Palestinian government in Ramallah
 # headed by Salam Fayyad, the start of work in time for the winter of
@@ -2200,9 +2256,7 @@
 #
 # We are not sure if Gaza will do the same, last year they had a different
 # end date, we will keep this page updated:
-# <a href="http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html">
 # http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-09-02):
 # Seems that Gaza Strip will go back to Winter Time same date as West Bank.
@@ -2212,51 +2266,35 @@
 #
 # "Winter time unite the West Bank and Gaza"
 # (from Palestinian National Authority):
-# <a href="http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
 # http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html>
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
-# </a>
 
 # From Alexander Krivenyshev (2010-03-19):
 # According to Voice of Palestine DST will last for 191 days, from March
 # 26, 2010 till "the last Sunday before the tenth day of Tishri
 # (October), each year" (October 03, 2010?)
 #
-# <a href="http://palvoice.org/forums/showthread.php?t=245697">
 # http://palvoice.org/forums/showthread.php?t=245697
-# </a>
 # (in Arabic)
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_westbank03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
-# </a>
 
 # From Steffen Thorsen (2010-03-24):
 # ...Ma'an News Agency reports that Hamas cabinet has decided it will
 # start one day later, at 12:01am. Not sure if they really mean 12:01am or
 # noon though:
 #
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=271178">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
-# </a>
 # (Ma'an News Agency)
 # "At 12:01am Friday, clocks in Israel and the West Bank will change to
 # 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
 
 # From Steffen Thorsen (2010-08-11):
 # According to several sources, including
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=306795">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
-# </a>
 # the clocks were set back one hour at 2010-08-11 00:00:00 local time in
 # Gaza and the West Bank.
 # Some more background info:
-# <a href="http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html">
 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
-# </a>
 
 # From Steffen Thorsen (2011-08-26):
 # Gaza and the West Bank did go back to standard time in the beginning of
@@ -2264,13 +2302,9 @@
 # 00:00 (so two periods of DST in 2011). The pause was because of
 # Ramadan.
 #
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=416217">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
-# </a>
 # Additional info:
-# <a href="http://www.timeanddate.com/news/time/palestine-dst-2011.html">
 # http://www.timeanddate.com/news/time/palestine-dst-2011.html
-# </a>
 
 # From Alexander Krivenyshev (2011-08-27):
 # According to the article in The Jerusalem Post:
@@ -2280,14 +2314,9 @@
 # The Hamas government said on Saturday that it won't observe summertime after
 # the Muslim feast of Id al-Fitr, which begins on Tuesday..."
 # ...
-# <a href="http://www.jpost.com/MiddleEast/Article.aspx?id=235650">
 # http://www.jpost.com/MiddleEast/Article.aspx?id=235650
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
-# </a>
-# The rules for Egypt are stolen from the `africa' file.
+# The rules for Egypt are stolen from the 'africa' file.
 
 # From Steffen Thorsen (2011-09-30):
 # West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
@@ -2295,26 +2324,18 @@
 # So West Bank and Gaza now have the same time again.
 #
 # Many sources, including:
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=424808">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
-# </a>
 
 # From Steffen Thorsen (2012-03-26):
 # Palestinian news sources tell that both Gaza and West Bank will start DST
 # on Friday (Thursday midnight, 2012-03-29 24:00).
 # Some of many sources in Arabic:
-# <a href="http://www.samanews.com/index.php?act=Show&id=122638">
 # http://www.samanews.com/index.php?act=Show&id=122638
-# </a>
 #
-# <a href="http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html">
 # http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
-# </a>
 #
 # Our brief summary:
-# <a href="http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html">
 # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
-# </a>
 
 # From Steffen Thorsen (2013-03-26):
 # The following news sources tells that Palestine will "start daylight saving
@@ -2374,10 +2395,10 @@
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
 			2:00	Zion	I%sT	1996
 			2:00	Jordan	EE%sT	1999
-			2:00 Palestine	EE%sT	2008 Aug 29 0:00
+			2:00 Palestine	EE%sT	2008 Aug 29  0:00
 			2:00	-	EET	2008 Sep
 			2:00 Palestine	EE%sT	2010
-			2:00	-	EET	2010 Mar 27 0:01
+			2:00	-	EET	2010 Mar 27  0:01
 			2:00 Palestine	EE%sT	2011 Aug  1
 			2:00	-	EET	2012
 			2:00 Palestine	EE%sT
@@ -2393,25 +2414,27 @@
 # no information
 
 # Philippines
-# On 1844-08-16, Narciso Claveria, governor-general of the
+# On 1844-08-16, Narciso Clavería, governor-general of the
 # Philippines, issued a proclamation announcing that 1844-12-30 was to
-# be immediately followed by 1845-01-01.  Robert H. van Gent has a
-# transcript of the decree in <http://www.phys.uu.nl/~vgent/idl/idl.htm>.
-# The rest of the data are from Shanks & Pottenger.
+# be immediately followed by 1845-01-01; see R.H. van Gent's
+# History of the International Date Line
+# http://www.staff.science.uu.nl/~gent0113/idl/idl_philippines.htm
+# The rest of the data entries are from Shanks & Pottenger.
 
-# From Paul Eggert (2006-04-25):
-# Tomorrow's Manila Standard reports that the Philippines Department of
-# Trade and Industry is considering adopting DST this June when the
-# rainy season begins.  See
-# <http://www.manilastandardtoday.com/?page=politics02_april26_2006>.
-# For now, we'll ignore this, since it's not definite and we lack details.
-#
-# From Jesper Norgaard Welen (2006-04-26):
+# From Jesper Nørgaard Welen (2006-04-26):
 # ... claims that Philippines had DST last time in 1990:
 # http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
 # [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
 # but no details]
 
+# From Paul Eggert (2014-08-14):
+# The following source says DST may be instituted November-January and again
+# March-June, but this is not definite.  It also says DST was last proclaimed
+# during the Ramos administration (1992-1998); but again, no details.
+# Carcamo D. PNoy urged to declare use of daylight saving time.
+# Philippine Star 2014-08-05
+# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
 Rule	Phil	1937	only	-	Feb	1	0:00	0	-
@@ -2428,18 +2451,39 @@
 
 # Qatar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
+Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
 # Saudi Arabia
+#
+# From Paul Eggert (2014-07-15):
+# Time in Saudi Arabia and other countries in the Arabian peninsula was not
+# standardized until relatively recently; we don't know when, and possibly it
+# has never been made official.  Richard P Hunt, in "Islam city yielding to
+# modern times", New York Times (1961-04-09), p 20, wrote that only airlines
+# observed standard time, and that people in Jeddah mostly observed quasi-solar
+# time, doing so by setting their watches at sunrise to 6 o'clock (or to 12
+# o'clock for "Arab" time).
+#
+# The TZ database cannot represent quasi-solar time; airline time is the best
+# we can do.  The 1946 foreign air news digest of the U.S. Civil Aeronautics
+# Board (OCLC 42299995) reported that the "... Arabian Government, inaugurated
+# a weekly Dhahran-Cairo service, via the Saudi Arabian cities of Riyadh and
+# Jidda, on March 14, 1947".  Shanks & Pottenger guessed 1950; go with the
+# earlier date.
+#
+# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
+# time zones; the other zone, at UTC+4, was in the far eastern part of
+# the country.  Ignore this, as it's before our 1970 cutoff.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Riyadh	3:06:52 -	LMT	1950
+Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
 			3:00	-	AST
 
 # Singapore
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -2465,26 +2509,24 @@
 
 # From Paul Eggert (1996-09-03):
 # "Sri Lanka advances clock by an hour to avoid blackout"
-# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# (<http://www.virtual-pc.com/lankaweb/news/items/240596-2.html>, 1996-05-24,
 # no longer available as of 1999-08-17)
-# reported ``the country's standard time will be put forward by one hour at
-# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
+# reported "the country's standard time will be put forward by one hour at
+# midnight Friday (1830 GMT) 'in the light of the present power crisis'."
 #
 # From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
-# by Shamindra in
-# <a href="news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net">
-# Daily News - Hot News Section (1996-10-26)
-# </a>:
+# by Shamindra in Daily News - Hot News Section
+# <news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net> (1996-10-26):
 # With effect from 12.30 a.m. on 26th October 1996
 # Sri Lanka will be six (06) hours ahead of GMT.
 
-# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
+# From Jesper Nørgaard Welen (2006-04-14), quoting Sri Lanka News Online
 # <http://news.sinhalaya.com/wmview.php?ArtID=11002> (2006-04-13):
 # 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
 # at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
 
 # From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
-# <http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML>
+# http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML
 # [The Tamil Tigers] never accepted the original 1996 time change and simply
 # kept their clocks set five and a half hours ahead of Greenwich Mean
 # Time (GMT), in line with neighbor India.
@@ -2498,7 +2540,7 @@
 # twice in 1996 and probably SL Government or its standardization
 # agencies never declared an abbreviation as a national standard.
 #
-# I recollect before the recent change the government annoucemments
+# I recollect before the recent change the government announcements
 # mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
 # Time and no mention was made about the abbreviation.
 #
@@ -2508,7 +2550,7 @@
 # item....
 #
 # Within Sri Lanka I think LKT is well known among computer users and
-# adminsitrators.  In my opinion SLT may not be a good choice because the
+# administrators.  In my opinion SLT may not be a good choice because the
 # nation's largest telcom / internet operator Sri Lanka Telcom is well
 # known by that abbreviation - simply as SLT (there IP domains are
 # slt.lk and sltnet.lk).
@@ -2523,13 +2565,13 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
-			5:19:32	-	MMT	1906	# Moratuwa Mean Time
+			5:19:32	-	MMT	1906        # Moratuwa Mean Time
 			5:30	-	IST	1942 Jan  5
 			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16 2:00
-			5:30	-	IST	1996 May 25 0:00
-			6:30	-	LKT	1996 Oct 26 0:30
-			6:00	-	LKT	2006 Apr 15 0:30
+			5:30	1:00	IST	1945 Oct 16  2:00
+			5:30	-	IST	1996 May 25  0:00
+			6:30	-	LKT	1996 Oct 26  0:30
+			6:00	-	LKT	2006 Apr 15  0:30
 			5:30	-	IST
 
 # Syria
@@ -2580,7 +2622,7 @@
 # Today the AP reported "Syria will switch to summertime at midnight Thursday."
 # http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
 Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
-# From Jesper Norgard (2007-10-27):
+# From Jesper Nørgaard (2007-10-27):
 # The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
 # not take place 1st November at 0:00 o'clock but 1st November at 24:00 or
 # rather Midnight between Thursday and Friday. This does make more sense than
@@ -2589,7 +2631,7 @@
 # it is implemented at midnight of the last workday before weekend...
 #
 # From Steffen Thorsen (2007-10-27):
-# Jesper Norgaard Welen wrote:
+# Jesper Nørgaard Welen wrote:
 #
 # > "Winter local time in Syria will be observed at midnight of Thursday 1
 # > November 2007, and the clock will be put back 1 hour."
@@ -2605,8 +2647,7 @@
 
 # From Stephen Colebourne (2008-03-17):
 # For everyone's info, I saw an IATA time zone change for [Syria] for
-# this month (March 2008) in the last day or so...This is the data IATA
-# are now using:
+# this month (March 2008) in the last day or so....
 # Country     Time Standard   --- DST Start ---   --- DST End ---  DST
 # Name        Zone Variation   Time    Date        Time    Date
 # Variation
@@ -2618,16 +2659,15 @@
 # From Arthur David Olson (2008-03-17):
 # Here's a link to English-language coverage by the Syrian Arab News
 # Agency (SANA)...
-# <a href="http://www.sana.sy/eng/21/2008/03/11/165173.htm">
 # http://www.sana.sy/eng/21/2008/03/11/165173.htm
-# </a>...which reads (in part) "The Cabinet approved the suggestion of the
+# ...which reads (in part) "The Cabinet approved the suggestion of the
 # Ministry of Electricity to begin daylight savings time on Friday April
 # 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
 # Since Syria is two hours east of UTC, the 2200 and 2100 transition times
 # shown above match up with midnight in Syria.
 
 # From Arthur David Olson (2008-03-18):
-# My buest guess at a Syrian rule is "the Friday nearest April 1";
+# My best guess at a Syrian rule is "the Friday nearest April 1";
 # coding that involves either using a "Mar Fri>=29" construct that old time zone
 # compilers can't handle  or having multiple Rules (a la Israel).
 # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
@@ -2640,37 +2680,27 @@
 # winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
 # clocks back 60 minutes).
 #
-# <a href="http://sana.sy/ara/2/2008/10/07/195459.htm">
 # http://sana.sy/ara/2/2008/10/07/195459.htm
-# </a>
 
 # From Steffen Thorsen (2009-03-19):
 # Syria will start DST on 2009-03-27 00:00 this year according to many sources,
 # two examples:
 #
-# <a href="http://www.sana.sy/eng/21/2009/03/17/217563.htm">
 # http://www.sana.sy/eng/21/2009/03/17/217563.htm
-# </a>
 # (English, Syrian Arab News # Agency)
-# <a href="http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209">
 # http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
-# </a>
 # (Arabic, gov-site)
 #
 # We have not found any sources saying anything about when DST ends this year.
 #
 # Our summary
-# <a href="http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html">
 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
-# </a>
 
 # From Steffen Thorsen (2009-10-27):
 # The Syrian Arab News Network on 2009-09-29 reported that Syria will
 # revert back to winter (standard) time on midnight between Thursday
 # 2009-10-29 and Friday 2009-10-30:
-# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm">
 # http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
-# </a>
 
 # From Arthur David Olson (2009-10-28):
 # We'll see if future DST switching times turn out to be end of the last
@@ -2681,23 +2711,17 @@
 # The "Syrian News Station" reported on 2010-03-16 that the Council of
 # Ministers has decided that Syria will start DST on midnight Thursday
 # 2010-04-01: (midnight between Thursday and Friday):
-# <a href="http://sns.sy/sns/?path=news/read/11421">
 # http://sns.sy/sns/?path=news/read/11421 (Arabic)
-# </a>
 
 # From Steffen Thorsen (2012-03-26):
 # Today, Syria's government announced that they will start DST early on Friday
 # (00:00). This is a bit earlier than the past two years.
 #
 # From Syrian Arab News Agency, in Arabic:
-# <a href="http://www.sana.sy/ara/2/2012/03/26/408215.htm">
 # http://www.sana.sy/ara/2/2012/03/26/408215.htm
-# </a>
 #
 # Our brief summary:
-# <a href="http://www.timeanddate.com/news/time/syria-dst-2012.html">
 # http://www.timeanddate.com/news/time/syria-dst-2012.html
-# </a>
 
 # From Arthur David Olson (2012-03-27):
 # Assume last Friday in March going forward XXX.
@@ -2710,7 +2734,7 @@
 Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
+Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
 			2:00	Syria	EE%sT
 
 # Tajikistan
@@ -2718,9 +2742,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
 			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
-			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
-			5:00	1:00	DUSST	1991 Sep  9 2:00s
-			5:00	-	TJT		    # Tajikistan Time
+			6:00 RussiaAsia DUS%sT	1991 Mar 31  2:00s
+			5:00	1:00	DUSST	1991 Sep  9  2:00s
+			5:00	-	TJT	# Tajikistan Time
 
 # Thailand
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2733,9 +2757,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
 			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
-			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
+			5:00 RussiaAsia	ASH%sT	1991 Mar 31  2:00
 			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
-			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
+			4:00 RussiaAsia	TM%sT	1992 Jan 19  2:00
 			5:00	-	TMT
 
 # United Arab Emirates
@@ -2744,8 +2768,9 @@
 			4:00	-	GST
 
 # Uzbekistan
+# Byalokoz 1919 says Uzbekistan was 4:27:53.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
+Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
 			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
 			5:00	-	SAMT	1981 Apr  1
 			5:00	1:00	SAMST	1981 Oct  1
@@ -2753,9 +2778,10 @@
 			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
-Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
+# Milne says Tashkent was 4:37:10.8; round to nearest.
+Zone	Asia/Tashkent	4:37:11 -	LMT	1924 May  2
 			5:00	-	TAST	1930 Jun 21 # Tashkent Time
-			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
+			6:00 RussiaAsia	TAS%sT	1991 Mar 31  2:00
 			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
@@ -2769,13 +2795,13 @@
 # and Pottenger.
 
 # From Arthur David Olson (2008-03-18):
-# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
-# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
+# The English-language name of Vietnam's most populous city is "Ho Chi Minh
+# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
 
 # From Shanks & Pottenger:
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
--- a/jdk/make/data/tzdata/australasia	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/australasia	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -36,13 +35,13 @@
 # Please see the notes below for the controversy about "EST" versus "AEST" etc.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
-Rule	Aus	1917	only	-	Mar	25	2:00	0	-
-Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
-Rule	Aus	1942	only	-	Mar	29	2:00	0	-
-Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
-Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
-Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
+Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	D
+Rule	Aus	1917	only	-	Mar	25	2:00	0	S
+Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	D
+Rule	Aus	1942	only	-	Mar	29	2:00	0	S
+Rule	Aus	1942	only	-	Sep	27	2:00	1:00	D
+Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	S
+Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	D
 # Go with Whitman and the Australian National Standards Commission, which
 # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
 # 1944/1945 was just like 1943/1944.
@@ -50,26 +49,26 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Northern Territory
 Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
-			 9:00	-	CST	1899 May
-			 9:30	Aus	CST
+			 9:00	-	ACST	1899 May
+			 9:30	Aus	AC%sT
 # Western Australia
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
-Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
-Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
-Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
+Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1991	only	-	Nov	17	2:00s	1:00	D
+Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	D
+Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	S
+Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	D
 Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
-			 8:00	Aus	WST	1943 Jul
-			 8:00	AW	WST
+			 8:00	Aus	AW%sT	1943 Jul
+			 8:00	AW	AW%sT
 Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
-			 8:45	Aus	CWST	1943 Jul
-			 8:45	AW	CWST
+			 8:45	Aus	ACW%sT	1943 Jul
+			 8:45	AW	ACW%sT
 
 # Queensland
 #
@@ -85,150 +84,150 @@
 # so use Lindeman.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
-Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
-Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
+Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	S
+Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	D
+Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	S
 Zone Australia/Brisbane	10:12:08 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT
 Zone Australia/Lindeman  9:55:56 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST	1992 Jul
-			10:00	Holiday	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT	1992 Jul
+			10:00	Holiday	AE%sT
 
 # South Australia
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1972	only	-	Feb	27	2:00s	0	-
-Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AS	1991	only	-	Mar	3	2:00s	0	-
-Rule	AS	1992	only	-	Mar	22	2:00s	0	-
-Rule	AS	1993	only	-	Mar	7	2:00s	0	-
-Rule	AS	1994	only	-	Mar	20	2:00s	0	-
-Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2006	only	-	Apr	2	2:00s	0	-
-Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1972	only	-	Feb	27	2:00s	0	S
+Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AS	1991	only	-	Mar	3	2:00s	0	S
+Rule	AS	1992	only	-	Mar	22	2:00s	0	S
+Rule	AS	1993	only	-	Mar	7	2:00s	0	S
+Rule	AS	1994	only	-	Mar	20	2:00s	0	S
+Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2006	only	-	Apr	2	2:00s	0	S
+Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AS	CST
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AS	AC%sT
 
 # Tasmania
 #
 # From Paul Eggert (2005-08-16):
-# <http://www.bom.gov.au/climate/averages/tables/dst_times.shtml>
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
 # says King Island didn't observe DST from WWII until late 1971.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
-Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
-Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
+Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	S
+Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	D
+Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1967
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT
 Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1971 Jul
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1971 Jul
+			10:00	AT	AE%sT
 
 # Victoria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AV	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AV	AE%sT
 
 # New South Wales
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1972	only	-	Feb	27	2:00s	0	-
-Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
-Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1972	only	-	Feb	27	2:00s	0	S
+Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	S
+Rule	AN	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AN	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AN	AE%sT
 Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
-			10:00	-	EST	1896 Aug 23
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AN	CST	2000
-			9:30	AS	CST
+			10:00	-	AEST	1896 Aug 23
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AN	AC%sT	2000
+			9:30	AS	AC%sT
 
 # Lord Howe Island
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
-Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
-Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
-Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
-Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
-Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
-Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
+Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	D
+Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	S
+Rule	LH	1986	only	-	Oct	19	2:00	0:30	D
+Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	S
+Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	D
+Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2007	only	-	Mar	lastSun	2:00	0	S
+Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	D
 Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
-			10:00	-	EST	1981 Mar
-			10:30	LH	LHST
+			10:00	-	AEST	1981 Mar
+			10:30	LH	LH%sT
 
 # Australian miscellany
 #
@@ -244,8 +243,8 @@
 # Permanent occupation (scientific station) 1911-1915 and since 25 March 1948;
 # sealing and penguin oil station operated Nov 1899 to Apr 1919.  See the
 # Tasmania Parks & Wildlife Service history of sealing at Macquarie Island
-# <http://www.parks.tas.gov.au/index.aspx?base=1828>
-# <http://www.parks.tas.gov.au/index.aspx?base=1831>.
+# http://www.parks.tas.gov.au/index.aspx?base=1828
+# http://www.parks.tas.gov.au/index.aspx?base=1831
 # Guess that it was like Australia/Hobart while inhabited before 2010.
 #
 # From Steffen Thorsen (2010-03-10):
@@ -256,16 +255,16 @@
 #
 # From Arthur David Olson (2013-05-23):
 # The 1919 transition is overspecified below so pre-2013 zics
-# will produce a binary file with an EST-type as the first 32-bit type;
+# will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
 Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1919 Apr 1 0:00s
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1919 Apr  1  0:00s
 			0	-	zzz	1948 Mar 25
-			10:00	Aus	EST	1967
-			10:00	AT	EST	2010 Apr 4 3:00
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
 
 # Christmas
@@ -273,24 +272,14 @@
 Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
 			7:00	-	CXT	# Christmas Island Time
 
-# Cook Is
-# From Shanks & Pottenger:
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
-Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
-Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
-			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
-			-10:00	Cook	CK%sT
-
-# Cocos
+# Cocos (Keeling) Is
 # These islands were ruled by the Ross family from about 1830 to 1978.
 # We don't know when standard time was introduced; for now, we guess 1900.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Cocos	6:27:40	-	LMT	1900
 			6:30	-	CCT	# Cocos Islands Time
 
+
 # Fiji
 
 # Milne gives 11:55:44 for Suva.
@@ -300,20 +289,13 @@
 # from November 29th 2009  to April 25th 2010.
 #
 # "Daylight savings to commence this month"
-# <a href="http://www.radiofiji.com.fj/fullstory.php?id=23719">
 # http://www.radiofiji.com.fj/fullstory.php?id=23719
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
-# </a>
 
 # From Steffen Thorsen (2009-11-10):
 # The Fiji Government has posted some more details about the approved
 # amendments:
-# <a href="http://www.fiji.gov.fj/publish/page_16198.shtml">
 # http://www.fiji.gov.fj/publish/page_16198.shtml
-# </a>
 
 # From Steffen Thorsen (2010-03-03):
 # The Cabinet in Fiji has decided to end DST about a month early, on
@@ -322,35 +304,24 @@
 # 2011 (last Sunday a good guess?).
 #
 # Official source:
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
-# </a>
 #
 # A bit more background info here:
-# <a href="http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html">
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
-# </a>
 
 # From Alexander Krivenyshev (2010-10-24):
 # According to Radio Fiji and Fiji Times online, Fiji will end DST 3
 # weeks earlier than expected - on March 6, 2011, not March 27, 2011...
 # Here is confirmation from Government of the Republic of the Fiji Islands,
 # Ministry of Information (fiji.gov.fj) web site:
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
-# </a>
 
 # From Steffen Thorsen (2011-10-03):
 # Now the dates have been confirmed, and at least our start date
 # assumption was correct (end date was one week wrong).
 #
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155">
-# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
-# </a>
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
 # which says
 # Members of the public are reminded to change their time to one hour in
 # advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
@@ -360,9 +331,7 @@
 # Another change to the Fiji DST end date. In the TZ database the end date for
 # Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
 #
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
-# </a>
 # states:
 #
 # The end of daylight saving scheduled initially for the 26th of February 2012
@@ -400,16 +369,16 @@
 Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
 Rule	Fiji	2014	max	-	Jan	Sun>=18	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26	# Suva
+Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
 
 # French Polynesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
+Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
 			 -9:00	-	GAMT	# Gambier Time
 Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
 			 -9:30	-	MART	# Marquesas Time
-Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
+Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct # Papeete
 			-10:00	-	TAHT	# Tahiti Time
 # Clipperton (near North America) is administered from French Polynesia;
 # it is uninhabited.
@@ -417,14 +386,14 @@
 # Guam
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
-			 9:39:00 -	LMT	1901		# Agana
-			10:00	-	GST	2000 Dec 23	# Guam
+			 9:39:00 -	LMT	1901        # Agana
+			10:00	-	GST	2000 Dec 23 # Guam
 			10:00	-	ChST	# Chamorro Standard Time
 
 # Kiribati
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
-			 12:00	-	GILT		 # Gilbert Is Time
+Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
+			 12:00	-	GILT	# Gilbert Is Time
 Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
 			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
 			-11:00	-	PHOT	1995
@@ -438,7 +407,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
 			 9:43:00 -	LMT	1901
-			 9:00	-	MPT	1969 Oct # N Mariana Is Time
+			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
 			10:00	-	MPT	2000 Dec 23
 			10:00	-	ChST	# Chamorro Standard Time
 
@@ -449,24 +418,24 @@
 			12:00	-	MHT
 Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
 			11:00	-	MHT	1969 Oct
-			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
+			-12:00	-	KWAT	1993 Aug 20 # Kwajalein Time
 			12:00	-	MHT
 
 # Micronesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Chuuk	10:07:08 -	LMT	1901
-			10:00	-	CHUT			# Chuuk Time
-Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
-			11:00	-	PONT			# Pohnpei Time
+			10:00	-	CHUT	# Chuuk Time
+Zone Pacific/Pohnpei	10:32:52 -	LMT	1901 # Kolonia
+			11:00	-	PONT	# Pohnpei Time
 Zone Pacific/Kosrae	10:51:56 -	LMT	1901
-			11:00	-	KOST	1969 Oct	# Kosrae Time
+			11:00	-	KOST	1969 Oct # Kosrae Time
 			12:00	-	KOST	1999
 			11:00	-	KOST
 
 # Nauru
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
-			11:30	-	NRT	1942 Mar 15	# Nauru Time
+Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
+			11:30	-	NRT	1942 Mar 15 # Nauru Time
 			9:00	-	JST	1944 Aug 15
 			11:30	-	NRT	1979 May
 			12:00	-	NRT
@@ -479,7 +448,7 @@
 # Shanks & Pottenger say the following was at 2:00; go with IATA.
 Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
+Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
 			11:00	NC	NC%sT
 
 
@@ -496,7 +465,8 @@
 Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
 Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
 # Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
-# convenient notation for this so we must duplicate the Rule lines.
+# convenient single notation for the date and time of this transition
+# so we must duplicate the Rule lines.
 Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
 Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
 Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
@@ -519,13 +489,14 @@
 Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
 			11:30	NZ	NZ%sT	1946 Jan  1
 			12:00	NZ	NZ%sT
-Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
+Zone Pacific/Chatham	12:13:48 -	LMT	1868 Nov  2
+			12:15	-	CHAST	1946 Jan  1
 			12:45	Chatham	CHA%sT
 
 Link Pacific/Auckland Antarctica/McMurdo
 
 # Auckland Is
-# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers,
 # and scientific personnel have wintered
 
 # Campbell I
@@ -534,48 +505,58 @@
 # previously whalers, sealers, pastoralists, and scientific personnel wintered
 # was probably like Pacific/Auckland
 
+# Cook Is
+# From Shanks & Pottenger:
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
+Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
+Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
+			-10:30	-	CKT	1978 Nov 12 # Cook Is Time
+			-10:00	Cook	CK%sT
+
 ###############################################################################
 
 
 # Niue
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
-			-11:20	-	NUT	1951	# Niue Time
-			-11:30	-	NUT	1978 Oct 1
+Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
+			-11:20	-	NUT	1951        # Niue Time
+			-11:30	-	NUT	1978 Oct  1
 			-11:00	-	NUT
 
 # Norfolk
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
-			11:12	-	NMT	1951	# Norfolk Mean Time
-			11:30	-	NFT		# Norfolk Time
+Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
+			11:12	-	NMT	1951 # Norfolk Mean Time
+			11:30	-	NFT	# Norfolk Time
 
 # Palau (Belau)
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
+Zone Pacific/Palau	8:57:56 -	LMT	1901 # Koror
 			9:00	-	PWT	# Palau Time
 
 # Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
-			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
-			10:00	-	PGT		# Papua New Guinea Time
+			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
+			10:00	-	PGT	# Papua New Guinea Time
 
 # Pitcairn
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
-			-8:30	-	PNT	1998 Apr 27 00:00
+Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
+			-8:30	-	PNT	1998 Apr 27  0:00
 			-8:00	-	PST	# Pitcairn Standard Time
 
 # American Samoa
 Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 			-11:22:48 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
-# Samoa
+# Samoa (formerly and also known as Western Samoa)
 
 # From Steffen Thorsen (2009-10-16):
 # We have been in contact with the government of Samoa again, and received
@@ -586,141 +567,80 @@
 # Sunday of April 2011."
 #
 # Background info:
-# <a href="http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html">
 # http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
-# </a>
 #
 # Samoa's Daylight Saving Time Act 2009 is available here, but does not
 # contain any dates:
-# <a href="http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf">
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
-# </a>
 
 # From Laupue Raymond Hughes (2010-10-07):
 # Please see
-# <a href="http://www.mcil.gov.ws">
 # http://www.mcil.gov.ws
-# </a>,
 # the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
 # September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
 # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
 # backwards from 1:00am to 12:00am"
 
 # From Laupue Raymond Hughes (2011-03-07):
-# I believe this will be posted shortly on the website
-# <a href="http://www.mcil.gov.ws">
-# www.mcil.gov.ws
-# </a>
-#
-# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
+# [http://www.mcil.gov.ws/ftcd/daylight_saving_2011.pdf]
 #
-# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
-# businesses and the general public are hereby advised that daylight
-# saving time is on the first Saturday of April 2011 (02/04/11).
-#
-# The public is therefore advised that when the standard time strikes
-# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
-# then all instruments used to measure standard time are to be
-# adjusted/changed to three oclock (3:00am or 0300Hrs).
-#
-# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
-# INDUSTRY AND LABOUR 28th February 2011
+# ... when the standard time strikes the hour of four o'clock (4.00am
+# or 0400 Hours) on the 2nd April 2011, then all instruments used to
+# measure standard time are to be adjusted/changed to three o'clock
+# (3:00am or 0300Hrs).
 
-# From David Zuelke (2011-05-09):
+# From David Zülke (2011-05-09):
 # Subject: Samoa to move timezone from east to west of international date line
 #
-# <a href="http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963">
 # http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
-# </a>
 
-# From Mark Sim-Smith (2011-08-17):
-# I have been in contact with Leilani Tuala Warren from the Samoa Law
-# Reform Commission, and she has sent me a copy of the Bill that she
-# confirmed has been passed...Most of the sections are about maps rather
-# than the time zone change, but I'll paste the relevant bits below. But
-# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
-# changes from UTC-11 to UTC+13:
-#
-# International Date Line Bill 2011
-#
-# AN ACT to provide for the change to standard time in Samoa and to make
-# consequential amendments to the position of the International Date
-# Line, and for related purposes.
-#
-# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
-# assembled as follows:
-#
-# 1. Short title and commencement-(1) This Act may be cited as the
-# International Date Line Act 2011. (2) Except for section 5(3) this Act
-# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
-# Section 5(3) commences on the date of assent by the Head of State.
-#
-# [snip]
-#
-# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
-# other statute of Samoa which refers to 'Samoa standard time' means the
-# time 13 hours in advance of Co-ordinated Universal Time.
-#
-# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
-# standard time shall be set at 13 hours in advance of Co-ordinated
-# Universal Time for the whole of Samoa. (2) All references to Samoa's
-# time zone and to Samoa standard time in Samoa in all legislation and
-# instruments after the commencement of this Act shall be references to
-# Samoa standard time as provided for in this Act. (3) Nothing in this
-# Act affects the provisions of the Daylight Saving Act 2009, except that
-# it defines Samoa standard time....
+# From Paul Eggert (2014-06-27):
+# The International Date Line Act 2011
+# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
+# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# Thursday 29th December 2011".  The International Date Line was adjusted
+# accordingly.
 
 # From Laupue Raymond Hughes (2011-09-02):
-# <a href="http://www.mcil.gov.ws/mcil_publications.html">
 # http://www.mcil.gov.ws/mcil_publications.html
-# </a>
 #
 # here is the official website publication for Samoa DST and dateline change
 #
 # DST
-# Year	End	Time	Start	Time
-# 2011	- - -	- - -	24 September	3:00am to 4:00am
-# 2012	01 April	4:00am to 3:00am	- - -	- - -
+# Year  End      Time              Start        Time
+# 2011  - - -    - - -             24 September 3:00am to 4:00am
+# 2012  01 April 4:00am to 3:00am  - - -        - - -
 #
 # Dateline Change skip Friday 30th Dec 2011
 # Thursday 29th December 2011	23:59:59 Hours
 # Saturday 31st December 2011	00:00:00 Hours
 #
-# Clarification by Tim Parenti (2012-01-03):
-# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
-# seasons, there is not yet any indication that this trend will continue on
-# a regular basis. For now, we have explicitly listed the transitions below.
-#
-# From Nicky (2012-09-10):
+# From Nicholas Pereira (2012-09-10):
 # Daylight Saving Time commences on Sunday 30th September 2012 and
-# ends on Sunday 7th of April 2013.
-#
-# Please find link below for more information.
+# ends on Sunday 7th of April 2013....
 # http://www.mcil.gov.ws/mcil_publications.html
 #
-# That publication also includes dates for Summer of 2013/4 as well
-# which give the impression of a pattern in selecting dates for the
-# future, so for now, we will guess this will continue.
+# From Paul Eggert (2014-07-08):
+# That web page currently lists transitions for 2012/3 and 2013/4.
+# Assume the pattern instituted in 2012 will continue indefinitely.
 
-# Western Samoa
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	WS	2010	only	-	Sep	lastSun	0:00	1	D
+Rule	WS	2011	only	-	Apr	Sat>=1	4:00	0	S
+Rule	WS	2011	only	-	Sep	lastSat	3:00	1	D
+Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	S
 Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
-Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 2 4:00
-			-11:00	-	WST	2011 Sep 24 3:00
-			-11:00	1:00	WSDT	2011 Dec 30
-			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
+			-11:30	-	WSST	1950
+			-11:00	WS	S%sT	2011 Dec 29 24:00 # S=Samoa
 			 13:00	WS	WS%sT
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
+Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
 			11:00	-	SBT	# Solomon Is Time
 
 # Tokelau Is
@@ -744,7 +664,7 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
-			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
+			-11:00	-	TKT	2011 Dec 30 # Tokelau Time
 			13:00	-	TKT
 
 # Tonga
@@ -804,8 +724,8 @@
 # time from Operation Newsreel (Hardtack I/Teak shot, 1958-08-01) to the last
 # Operation Fishbowl shot (Tightrope, 1962-11-04).... [See] Herman Hoerlin,
 # "The United States High-Altitude Test Experience: A Review Emphasizing the
-# Impact on the Environment", Los Alamos LA-6405, Oct 1976
-# <http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf>.
+# Impact on the Environment", Los Alamos LA-6405, Oct 1976.
+# http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf
 # See the table on page 4 where he lists GMT and local times for the tests; a
 # footnote for the JI tests reads that local time is "JI time = Hawaii Time
 # Minus One Hour".
@@ -820,7 +740,7 @@
 # From Mark Brader (2005-01-23):
 # [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
 # published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
-# reproduced a Pan American Airways timeables from 1936, for their weekly
+# reproduced a Pan American Airways timetable from 1936, for their weekly
 # "Orient Express" flights between San Francisco and Manila, and connecting
 # flights to Chicago and the US East Coast.  As it uses some time zone
 # designations that I've never seen before:....
@@ -830,9 +750,9 @@
 Zone Pacific/Midway	-11:49:28 -	LMT	1901
 			-11:00	-	NST	1956 Jun  3
 			-11:00	1:00	NDT	1956 Sep  2
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
 # Palmyra
 # uninhabited since World War II; was probably like Pacific/Kiritimati
@@ -852,7 +772,7 @@
 Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
 Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
+Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
 			11:00	Vanuatu	VU%sT	# Vanuatu Time
 
 # Wallis and Futuna
@@ -864,9 +784,10 @@
 
 # NOTES
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 # A good source for time zone historical data outside the U.S. is
@@ -887,165 +808,188 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
-#		std dst
-#		LMT	Local Mean Time
-#	  8:00	WST WST	Western Australia
-#	  8:45	CWST CWST Central Western Australia*
-#	  9:00	JST	Japan
-#	  9:30	CST CST	Central Australia
-#	 10:00	EST EST	Eastern Australia
-#	 10:00	ChST	Chamorro
-#	 10:30	LHST LHST Lord Howe*
-#	 11:30	NZMT NZST New Zealand through 1945
-#	 12:00	NZST NZDT New Zealand 1946-present
-#	 12:45	CHAST CHADT Chatham*
-#	-11:00	SST	Samoa
-#	-10:00	HST	Hawaii
-#	- 8:00	PST	Pitcairn*
+#		std	dst
+#		LMT		Local Mean Time
+#	  8:00	AWST	AWDT	Western Australia
+#	  8:45	ACWST	ACWDT	Central Western Australia*
+#	  9:00	JST		Japan
+#	  9:30	ACST	ACDT	Central Australia
+#	 10:00	AEST	AEDT	Eastern Australia
+#	 10:00	ChST		Chamorro
+#	 10:30	LHST	LHDT	Lord Howe*
+#	 11:30	NZMT	NZST	New Zealand through 1945
+#	 12:00	NZST	NZDT	New Zealand 1946-present
+#	 12:15	CHAST		Chatham through 1945*
+#	 12:45	CHAST	CHADT	Chatham 1946-present*
+#	 13:00	WSST	WSDT	(western) Samoa 2011-present*
+#	-11:30	WSST		Western Samoa through 1950*
+#	-11:00	SST		Samoa
+#	-10:00	HST		Hawaii
+#	- 8:00	PST		Pitcairn*
 #
-# See the `northamerica' file for Hawaii.
-# See the `southamerica' file for Easter I and the Galapagos Is.
+# See the 'northamerica' file for Hawaii.
+# See the 'southamerica' file for Easter I and the Galápagos Is.
 
 ###############################################################################
 
 # Australia
 
+# From Paul Eggert (2014-06-30):
+# Daylight saving time has long been controversial in Australia, pitting
+# region against region, rural against urban, and local against global.
+# For example, in her review of Graeme Davison's _The Unforgiving
+# Minute: how Australians learned to tell the time_ (1993), Perth native
+# Phillipa J Martyr wrote, "The section entitled 'Saving Daylight' was
+# very informative, but was (as can, sadly, only be expected from a
+# Melbourne-based study) replete with the usual chuckleheaded
+# Queenslanders and straw-chewing yokels from the West prattling fables
+# about fading curtains and crazed farm animals."
+# Electronic Journal of Australian and New Zealand History (1997-03-03)
+# http://www.jcu.edu.au/aff/history/reviews/davison.htm
+
 # From Paul Eggert (2005-12-08):
-# <a href="http://www.bom.gov.au/climate/averages/tables/dst_times.shtml">
 # Implementation Dates of Daylight Saving Time within Australia
-# </a> summarizes daylight saving issues in Australia.
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
+# summarizes daylight saving issues in Australia.
 
 # From Arthur David Olson (2005-12-12):
-# <a href="http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving">
 # Lawlink NSW:Daylight Saving in New South Wales
-# </a> covers New South Wales in particular.
+# http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving
+# covers New South Wales in particular.
 
 # From John Mackin (1991-03-06):
-# We in Australia have _never_ referred to DST as `daylight' time.
-# It is called `summer' time.  Now by a happy coincidence, `summer'
-# and `standard' happen to start with the same letter; hence, the
+# We in Australia have _never_ referred to DST as 'daylight' time.
+# It is called 'summer' time.  Now by a happy coincidence, 'summer'
+# and 'standard' happen to start with the same letter; hence, the
 # abbreviation does _not_ change...
 # The legislation does not actually define abbreviations, at least
 # in this State, but the abbreviation is just commonly taken to be the
 # initials of the phrase, and the legislation here uniformly uses
-# the phrase `summer time' and does not use the phrase `daylight
+# the phrase 'summer time' and does not use the phrase 'daylight
 # time'.
 # Announcers on the Commonwealth radio network, the ABC (for Australian
-# Broadcasting Commission), use the phrases `Eastern Standard Time'
-# or `Eastern Summer Time'.  (Note, though, that as I say in the
+# Broadcasting Commission), use the phrases 'Eastern Standard Time'
+# or 'Eastern Summer Time'.  (Note, though, that as I say in the
 # current australasia file, there is really no such thing.)  Announcers
 # on its overseas service, Radio Australia, use the same phrases
-# prefixed by the word `Australian' when referring to local times;
+# prefixed by the word 'Australian' when referring to local times;
 # time announcements on that service, naturally enough, are made in UTC.
 
-# From Arthur David Olson (1992-03-08):
-# Given the above, what's chosen for year-round use is:
-#	CST	for any place operating at a GMTOFF of 9:30
-#	WST	for any place operating at a GMTOFF of 8:00
-#	EST	for any place operating at a GMTOFF of 10:00
-
-# From Chuck Soper (2006-06-01):
-# I recently found this Australian government web page on time zones:
-# <http://www.australia.gov.au/about-australia-13time>
-# And this government web page lists time zone names and abbreviations:
-# <http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml>
-
-# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
-# versus "AEST" etc.:
+# From Paul Eggert (2014-06-30):
 #
-# I see the following points of dispute:
-#
-# * How important are unique time zone abbreviations?
+# Inspired by Mackin's remarks quoted above, earlier versions of this
+# file used "EST" for both Eastern Standard Time and Eastern Summer
+# Time in Australia, and similarly for "CST", "CWST", and "WST".
+# However, these abbreviations were confusing and were not common
+# practice among Australians, and there were justifiable complaints
+# about them, so I attempted to survey current Australian usage.
+# For the tz database, the full English phrase is not that important;
+# what matters is the abbreviation.  It's difficult to survey the web
+# directly for abbreviation usage, as there are so many false hits for
+# strings like "EST" and "EDT", so I looked for pages that defined an
+# abbreviation for eastern or central DST in Australia, and got the
+# following numbers of unique hits for the listed Google queries:
 #
-#   Here I tend to agree with the point (most recently made by Chris
-#   Newman) that unique abbreviations should not be essential for proper
-#   operation of software.  We have other instances of ambiguity
-#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
-#   Standard Time"), and they are not likely to go away any time soon.
-#   In the old days, some software mistakenly relied on unique
-#   abbreviations, but this is becoming less true with time, and I don't
-#   think it's that important to cater to such software these days.
+#   10 "Eastern Daylight Time AEST" site:au [some are false hits]
+#   10 "Eastern Summer Time AEST" site:au
+#   10 "Summer Time AEDT" site:au
+#   13 "EDST Eastern Daylight Saving Time" site:au
+#   18 "Summer Time ESST" site:au
+#   28 "Eastern Daylight Saving Time EDST" site:au
+#   39 "EDT Eastern Daylight Time" site:au [some are false hits]
+#   53 "Eastern Daylight Time EDT" site:au [some are false hits]
+#   54 "AEDT Australian Eastern Daylight Time" site:au
+#  182 "Eastern Daylight Time AEDT" site:au
+#
+#   17 "Central Daylight Time CDT" site:au [some are false hits]
+#   46 "Central Daylight Time ACDT" site:au
 #
-#   On the other hand, there is another motivation for unambiguous
-#   abbreviations: it cuts down on human confusion.  This is
-#   particularly true for Australia, where "EST" can mean one thing for
-#   time T and a different thing for time T plus 1 second.
+# I tried several other variants (e.g., "Eastern Summer Time EST") but
+# they all returned fewer than 10 unique hits.  I also looked for pages
+# mentioning both "western standard time" and an abbreviation, since
+# there is no WST in the US to generate false hits, and found:
 #
-# * Does the relevant legislation indicate which abbreviations should be used?
+#  156 "western standard time" AWST site:au
+#  226 "western standard time" WST site:au
 #
-#   Here I tend to think that things are a mess, just as they are in
-#   many other countries.  We Americans are currently disagreeing about
-#   which abbreviation to use for the newly legislated Chamorro Standard
-#   Time, for example.
-#
-#   Personally, I would prefer to use common practice; I would like to
-#   refer to legislation only for examples of common practice, or as a
-#   tiebreaker.
+# I then surveyed the top ten newspapers in Australia by circulation as
+# listed in Wikipedia, using Google queries like "AEDT site:heraldsun.com.au"
+# and obtaining estimated counts from the initial page of search results.
+# All ten papers greatly preferred "AEDT" to "EDT".  The papers
+# surveyed were the Herald Sun, The Daily Telegraph, The Courier-Mail,
+# The Sydney Morning Herald, The West Australian, The Age, The Advertiser,
+# The Australian, The Financial Review, and The Herald (Newcastle).
 #
-# * Do Australians more often use "Eastern Daylight Time" or "Eastern
-#   Summer Time"?  Do they typically prefix the time zone names with
-#   the word "Australian"?
-#
-#   My own impression is that both "Daylight Time" and "Summer Time" are
-#   common and are widely understood, but that "Summer Time" is more
-#   popular; and that the leading "A" is also common but is omitted more
-#   often than not.  I just used AltaVista advanced search and got the
-#   following count of page hits:
+# I also searched for historical usage, to see whether abbreviations
+# like "AEDT" are new.  A Trove search <http://trove.nla.gov.au/>
+# found only one newspaper (The Canberra Times) with a house style
+# dating back to the 1970s, I expect because other newspapers weren't
+# fully indexed.  The Canberra Times strongly preferred abbreviations
+# like "AEDT".  The first occurrence of "AEDT" was a World Weather
+# column (1971-11-17, page 24), and of "ACDT" was a Scoreboard column
+# (1993-01-24, p 16).  The style was the typical usage but was not
+# strictly enforced; for example, "Welcome to the twilight zones ..."
+# (1994-10-29, p 1) uses the abbreviations AEST/AEDT, CST/CDT, and
+# WST, and goes on to say, "The confusion and frustration some feel
+# about the lack of uniformity among Australia's six states and two
+# territories has prompted one group to form its very own political
+# party -- the Sydney-based Daylight Saving Extension Party."
 #
-#     1,103 "Eastern Summer Time" AND domain:au
-#       971 "Australian Eastern Summer Time" AND domain:au
-#       613 "Eastern Daylight Time" AND domain:au
-#       127 "Australian Eastern Daylight Time" AND domain:au
+# I also surveyed federal government sources.  They did not agree:
 #
-#   Here "Summer" seems quite a bit more popular than "Daylight",
-#   particularly when we know the time zone is Australian and not US,
-#   say.  The "Australian" prefix seems to be popular for Eastern Summer
-#   Time, but unpopular for Eastern Daylight Time.
+#   The Australian Government (2014-03-26)
+#   http://australia.gov.au/about-australia/our-country/time
+#   (This document was produced by the Department of Finance.)
+#   AEST ACST AWST AEDT ACDT
+#
+#   Bureau of Meteorology (2012-11-08)
+#   http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml
+#   EST CST WST EDT CDT
 #
-#   For abbreviations, tools like AltaVista are less useful because of
-#   ambiguity.  Many hits are not really time zones, unfortunately, and
-#   many hits denote US time zones and not Australian ones.  But here
-#   are the hit counts anyway:
+#   Civil Aviation Safety Authority (undated)
+#   http://services.casa.gov.au/outnback/inc/pages/episode3/episode-3_time_zones.shtml
+#   EST CST WST (no abbreviations given for DST)
 #
-#     161,304 "EST" and domain:au
-#      25,156 "EDT" and domain:au
-#      18,263 "AEST" and domain:au
-#      10,416 "AEDT" and domain:au
+#   Geoscience Australia (2011-11-24)
+#   http://www.ga.gov.au/geodesy/astro/sunrise.jsp
+#   AEST ACST AWST AEDT ACDT
+#
+#   Parliamentary Library (2008-11-10)
+#   http://www.aph.gov.au/binaries/library/pubs/rp/2008-09/09rp14.pdf
+#   EST CST WST preferred for standard time; AEST AEDT ACST ACDT also used
 #
-#      14,538 "CST" and domain:au
-#       5,728 "CDT" and domain:au
-#         176 "ACST" and domain:au
-#          29 "ACDT" and domain:au
-#
-#       7,539 "WST" and domain:au
-#          68 "AWST" and domain:au
+#   The Transport Safety Bureau has an extensive series of accident reports,
+#   and investigators seem to use whatever abbreviation they like.
+#   Googling site:atsb.gov.au found the following number of unique hits:
+#   311 "ESuT", 195 "EDT", 26 "AEDT", 83 "CSuT", 46 "CDT".
+#   "_SuT" tended to appear in older reports, and "A_DT" tended to
+#   appear in reports of events with international implications.
 #
-#   This data suggest that Australians tend to omit the "A" prefix in
-#   practice.  The situation for "ST" versus "DT" is less clear, given
-#   the ambiguities involved.
-#
-# * How do Australians feel about the abbreviations in the tz database?
-#
-#   If you just count Australians on this list, I count 2 in favor and 3
-#   against.  One of the "against" votes (David Keegel) counseled delay,
-#   saying that both AEST/AEDT and EST/EST are widely used and
-#   understood in Australia.
+# From the above it appears that there is a working consensus in
+# Australia to use trailing "DT" for daylight saving time; although
+# some sources use trailing "SST" or "ST" or "SuT" they are by far in
+# the minority.  The case for leading "A" is weaker, but since it
+# seems to be preferred in the overall web and is preferred in all
+# the leading newspaper websites and in many government departments,
+# it has a stronger case than omitting the leading "A".  The current
+# version of the database therefore uses abbreviations like "AEST" and
+# "AEDT" for Australian time zones.
 
 # From Paul Eggert (1995-12-19):
 # Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
 # Mark Prior writes that his newspaper
 # reports that NSW's fall 1995 change will occur at 2:00,
 # but Robert Elz says it's been 3:00 in Victoria since 1970
-# and perhaps the newspaper's `2:00' is referring to standard time.
+# and perhaps the newspaper's '2:00' is referring to standard time.
 # For now we'll continue to assume 2:00s for changes since 1960.
 
 # From Eric Ulevik (1998-01-05):
@@ -1055,17 +999,14 @@
 # relevant entries in this database.
 #
 # NSW (including LHI and Broken Hill):
-# <a href="http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html">
 # Standard Time Act 1987 (updated 1995-04-04)
-# </a>
+# http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html
 # ACT
-# <a href="http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html">
 # Standard Time and Summer Time Act 1972
-# </a>
+# http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html
 # SA
-# <a href="http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html">
 # Standard Time Act, 1898
-# </a>
+# http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html
 
 # From David Grosz (2005-06-13):
 # It was announced last week that Daylight Saving would be extended by
@@ -1083,7 +1024,7 @@
 # Victoria: I wasn't able to find anything separate, but the other articles
 # allude to it.
 # But not Queensland
-# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
+# http://www.news.com.au/story/0,10117,15564030-1248,00.html
 
 # Northern Territory
 
@@ -1130,9 +1071,9 @@
 # The 1992 ending date used in the rules is a best guess;
 # it matches what was used in the past.
 
-# <a href="http://www.bom.gov.au/faq/faqgen.htm">
 # The Australian Bureau of Meteorology FAQ
-# </a> (1999-09-27) writes that Giles Meteorological Station uses
+# http://www.bom.gov.au/faq/faqgen.htm
+# (1999-09-27) writes that Giles Meteorological Station uses
 # South Australian time even though it's located in Western Australia.
 
 # Queensland
@@ -1173,9 +1114,9 @@
 # The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
 
 # From Christopher Hunt (2006-11-21), after an advance warning
-# from Jesper Norgaard Welen (2006-11-01):
+# from Jesper Nørgaard Welen (2006-11-01):
 # WA are trialing DST for three years.
-# <http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf>
+# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf
 
 # From Rives McDow (2002-04-09):
 # The most interesting region I have found consists of three towns on the
@@ -1189,7 +1130,7 @@
 # From Paul Eggert (2002-04-09):
 # This is confirmed by the section entitled
 # "What's the deal with time zones???" in
-# <http://www.earthsci.unimelb.edu.au/~awatkins/null.html>.
+# http://www.earthsci.unimelb.edu.au/~awatkins/null.html
 #
 # From Alex Livingston (2006-12-07):
 # ... it was just on four years ago that I drove along the Eyre Highway,
@@ -1337,7 +1278,7 @@
 # Based on law library research by John Mackin,
 # who notes:
 #	In Australia, time is not legislated federally, but rather by the
-#	individual states.  Thus, while such terms as ``Eastern Standard Time''
+#	individual states.  Thus, while such terms as "Eastern Standard Time"
 #	[I mean, of course, Australian EST, not any other kind] are in common
 #	use, _they have NO REAL MEANING_, as they are not defined in the
 #	legislation.  This is very important to understand.
@@ -1345,48 +1286,42 @@
 
 # From Eric Ulevik (1999-05-26):
 # DST will start in NSW on the last Sunday of August, rather than the usual
-# October in 2000.  [See: Matthew Moore,
-# <a href="http://www.smh.com.au/news/9905/26/pageone/pageone4.html">
-# Two months more daylight saving
-# </a>
-# Sydney Morning Herald (1999-05-26).]
+# October in 2000.  See: Matthew Moore,
+# Two months more daylight saving, Sydney Morning Herald (1999-05-26).
+# http://www.smh.com.au/news/9905/26/pageone/pageone4.html
 
 # From Paul Eggert (1999-09-27):
 # See the following official NSW source:
-# <a href="http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ">
 # Daylight Saving in New South Wales.
-# </a>
+# http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ
 #
 # Narrabri Shire (NSW) council has announced it will ignore the extension of
 # daylight saving next year.  See:
-# <a href="http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm">
 # Narrabri Council to ignore daylight saving
-# </a> (1999-07-22).  For now, we'll wait to see if this really happens.
+# http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm
+# (1999-07-22).  For now, we'll wait to see if this really happens.
 #
 # Victoria will following NSW.  See:
-# <a href="http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm">
-# Vic to extend daylight saving
-# </a> (1999-07-28).
+# Vic to extend daylight saving (1999-07-28)
+# http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm
 #
 # However, South Australia rejected the DST request.  See:
-# <a href="http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm">
-# South Australia rejects Olympics daylight savings request
-# </a> (1999-07-19).
+# South Australia rejects Olympics daylight savings request (1999-07-19)
+# http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm
 #
 # Queensland also will not observe DST for the Olympics.  See:
-# <a href="http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm">
 # Qld says no to daylight savings for Olympics
-# </a> (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
-# ``Look you've got to remember in my family when this came up last time
+# http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm
+# (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# "Look you've got to remember in my family when this came up last time
 # I voted for it, my wife voted against it and she said to me it's all very
 # well for you, you don't have to worry about getting the children out of
 # bed, getting them to school, getting them to sleep at night.
-# I've been through all this argument domestically...my wife rules.''
+# I've been through all this argument domestically...my wife rules."
 #
 # Broken Hill will stick with South Australian time in 2000.  See:
-# <a href="http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm">
-# Broken Hill to be behind the times
-# </a> (1999-07-21).
+# Broken Hill to be behind the times (1999-07-21)
+# http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm
 
 # IATA SSIM (1998-09) says that the spring 2000 change for Australian
 # Capital Territory, New South Wales except Lord Howe Island and Broken
@@ -1402,7 +1337,7 @@
 # Yancowinna
 
 # From John Mackin (1989-01-04):
-# `Broken Hill' means the County of Yancowinna.
+# 'Broken Hill' means the County of Yancowinna.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
@@ -1459,9 +1394,7 @@
 # summer (southern hemisphere).
 #
 # From
-# <a href="http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf">
 # http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
-# </a>
 # The extended daylight saving period that South Australia has been trialling
 # for over the last year is now set to be ongoing.
 # Daylight saving will continue to start on the first Sunday in October each
@@ -1471,9 +1404,7 @@
 # the ACT for all 52 weeks of the year...
 #
 # We have a wrap-up here:
-# <a href="http://www.timeanddate.com/news/time/south-australia-extends-dst.html">
 # http://www.timeanddate.com/news/time/south-australia-extends-dst.html
-# </a>
 ###############################################################################
 
 # New Zealand
@@ -1482,7 +1413,7 @@
 # the 1989/90 year was a trial of an extended "daylight saving" period.
 # This trial was deemed successful and the extended period adopted for
 # subsequent years (with the addition of a further week at the start).
-# source -- phone call to Ministry of Internal Affairs Head Office.
+# source - phone call to Ministry of Internal Affairs Head Office.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # The Country of New Zealand   (Australia's east island -) Gee they hate that!
@@ -1524,6 +1455,19 @@
 # that DST will begin on 2007-09-30 2008-04-06.
 # http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
 
+# From Paul Eggert (2014-07-14):
+# Chatham Island time was formally standardized on 1957-01-01 by
+# New Zealand's Standard Time Amendment Act 1956 (1956-10-26).
+# http://www.austlii.edu.au/nz/legis/hist_act/staa19561956n100244.pdf
+# According to Google Books snippet view, a speaker in the New Zealand
+# parliamentary debates in 1956 said "Clause 78 makes provision for standard
+# time in the Chatham Islands.  The time there is 45 minutes in advance of New
+# Zealand time.  I understand that is the time they keep locally, anyhow."
+# For now, assume this practice goes back to the introduction of standard time
+# in New Zealand, as this would make Chatham Islands time almost exactly match
+# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# not observe New Zealand's prewar DST.
+
 ###############################################################################
 
 
@@ -1543,7 +1487,7 @@
 
 # From the BBC World Service in
 # http://news.bbc.co.uk/2/hi/asia-pacific/205226.stm (1998-10-31 16:03 UTC):
-# The Fijiian government says the main reasons for the time change is to
+# The Fijian government says the main reasons for the time change is to
 # improve productivity and reduce road accidents.... [T]he move is also
 # intended to boost Fiji's ability to attract tourists to witness the dawning
 # of the new millennium.
@@ -1551,16 +1495,12 @@
 # http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
 # reports that Fiji has discontinued DST.
 
-# Johnston
-
-# Johnston data is from usno1995.
-
 
 # Kiribati
 
 # From Paul Eggert (1996-01-22):
 # Today's _Wall Street Journal_ (page 1) reports that Kiribati
-# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
+# "declared it the same day [throughout] the country as of Jan. 1, 1995"
 # as part of the competition to be first into the 21st century.
 
 
@@ -1575,8 +1515,8 @@
 
 # N Mariana Is, Guam
 
-# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
-# Philippines and the Ladrones from America,'' and implies that the Ladrones
+# Howse writes (p 153) "The Spaniards, on the other hand, reached the
+# Philippines and the Ladrones from America," and implies that the Ladrones
 # (now called the Marianas) kept American date for quite some time.
 # For now, we assume the Ladrones switched at the same time as the Philippines;
 # see Asia/Manila.
@@ -1590,17 +1530,16 @@
 # Micronesia
 
 # Alan Eugene Davis writes (1996-03-16),
-# ``I am certain, having lived there for the past decade, that "Truk"
-# (now properly known as Chuuk) ... is in the time zone GMT+10.''
+# "I am certain, having lived there for the past decade, that 'Truk'
+# (now properly known as Chuuk) ... is in the time zone GMT+10."
 #
 # Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
 # on 1978-10-01; ignore this for now.
 
 # From Paul Eggert (1999-10-29):
 # The Federated States of Micronesia Visitors Board writes in
-# <a href="http://www.fsmgov.org/info/clocks.html">
-# The Federated States of Micronesia - Visitor Information
-# </a> (1999-01-26)
+# The Federated States of Micronesia - Visitor Information (1999-01-26)
+# http://www.fsmgov.org/info/clocks.html
 # that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
 # We don't know when Kosrae switched from UTC+12; assume January 1 for now.
 
@@ -1646,27 +1585,34 @@
 # Sacramento but it was changed a couple of years ago.
 
 
-# Samoa
+# (Western) Samoa and American Samoa
 
 # Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
 # that in 1879 the King of Samoa decided to change
-# ``the date in his kingdom from the Antipodean to the American system,
-# ordaining -- by a masterpiece of diplomatic flattery -- that
-# the Fourth of July should be celebrated twice in that year.''
+# "the date in his kingdom from the Antipodean to the American system,
+# ordaining - by a masterpiece of diplomatic flattery - that
+# the Fourth of July should be celebrated twice in that year."
 
+# Although Shanks & Pottenger says they both switched to UTC-11:30
+# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# for American Samoa, e.g., the US National Bureau of Standards
+# circular "Standard Time Throughout the World", 1932.
+# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# and that after 1950 they agreed until (western) Samoa skipped a
+# day in 2011.  Assume also that the Samoas follow the US and New
+# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
 
 # Tonga
 
 # From Paul Eggert (1996-01-22):
-# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
-# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
+# Today's _Wall Street Journal_ (p 1) reports that "Tonga has been plotting
+# to sneak ahead of [New Zealanders] by introducing daylight-saving time."
 # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
 
 # Don Mundell writes in the 1997-02-20 Tonga Chronicle
-# <a href="http://www.tongatapu.net.to/tonga/homeland/timebegins.htm">
-# How Tonga became `The Land where Time Begins'
-# </a>:
-
+# How Tonga became 'The Land where Time Begins':
+# http://www.tongatapu.net.to/tonga/homeland/timebegins.htm
+#
 # Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
 # 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
 # standard time in 1940s, Tonga had the choice of subtracting from its
@@ -1674,8 +1620,8 @@
 # advancing its time to maintain the differential of 13 degrees
 # (approximately 50 minutes ahead of New Zealand time).
 #
-# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
-# Tungi, preferred to ensure Tonga's title as the land where time
+# Because His Majesty King Tāufaʻāhau Tupou IV, then Crown Prince
+# Tungī, preferred to ensure Tonga's title as the land where time
 # begins, the Legislative Assembly approved the latter change.
 #
 # But some of the older, more conservative members from the outer
@@ -1701,9 +1647,7 @@
 # * Tonga will introduce DST in November
 #
 # I was given this link by John Letts:
-# <a href="http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm">
 # http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
-# </a>
 #
 # I have not been able to find exact dates for the transition in November
 # yet. By reading this article it seems like Fiji will be 14 hours ahead
@@ -1711,9 +1655,7 @@
 # (12 + 1 hour DST).
 
 # From Arthur David Olson (1999-09-20):
-# According to <a href="http://www.tongaonline.com/news/sept1799.html">
-# http://www.tongaonline.com/news/sept1799.html
-# </a>:
+# According to <http://www.tongaonline.com/news/sept1799.html>:
 # "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
 # and annually thereafter from the first Saturday in October through the
 # third Saturday of April.  Under the system approved by Privy Council on
@@ -1731,7 +1673,7 @@
 # instead of the original reported date April 16. Unfortunately, the article
 # is no longer available on the site, and I did not make a copy of the
 # text, and I have forgotten to report it here.
-# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+# (Original URL was <http://www.tongaonline.com/news/march162000.htm>)
 
 # From Rives McDow (2000-12-01):
 # Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
@@ -1751,7 +1693,7 @@
 # From Vernice Anderson, Personal Secretary to Philip Jessup,
 # US Ambassador At Large (oral history interview, 1971-02-02):
 #
-# Saturday, the 14th [of October, 1950] -- ...  The time was all the
+# Saturday, the 14th [of October, 1950] - ...  The time was all the
 # more confusing at that point, because we had crossed the
 # International Date Line, thus getting two Sundays.  Furthermore, we
 # discovered that Wake Island had two hours of daylight saving time
@@ -1796,7 +1738,7 @@
 # on the high seas.  Whenever a ship was within the territorial waters of any
 # nation it would use that nation's standard time.  The captain was permitted
 # to change his ship's clocks at a time of his choice following his ship's
-# entry into another zone time--he often chose midnight.  These zones were
+# entry into another zone time - he often chose midnight.  These zones were
 # adopted by all major fleets between 1920 and 1925 but not by many
 # independent merchant ships until World War II.
 
@@ -1804,6 +1746,6 @@
 # (2005-03-20):
 #
 # The American Practical Navigator (2002)
-# <http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187>
+# http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187
 # talks only about the 180-degree meridian with respect to ships in
 # international waters; it ignores the international date line.
--- a/jdk/make/data/tzdata/backward	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/backward	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
 
+# Link	TARGET			LINK-NAME
 Link	Africa/Asmara		Africa/Asmera
-Link	Africa/Bamako		Africa/Timbuktu
+Link	Africa/Abidjan		Africa/Timbuktu
 Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
 Link	America/Adak		America/Atka
 Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
@@ -50,8 +50,11 @@
 Link	Pacific/Auckland	Antarctica/South_Pole
 Link	Asia/Ashgabat		Asia/Ashkhabad
 Link	Asia/Kolkata		Asia/Calcutta
-Link	Asia/Chongqing		Asia/Chungking
+Link	Asia/Shanghai		Asia/Chongqing
+Link	Asia/Shanghai		Asia/Chungking
 Link	Asia/Dhaka		Asia/Dacca
+Link	Asia/Shanghai		Asia/Harbin
+Link	Asia/Urumqi		Asia/Kashgar
 Link	Asia/Kathmandu		Asia/Katmandu
 Link	Asia/Macau		Asia/Macao
 Link	Asia/Ho_Chi_Minh	Asia/Saigon
--- a/jdk/make/data/tzdata/etcetera	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/etcetera	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -37,7 +36,7 @@
 Zone	Etc/UCT		0	-	UCT
 
 # The following link uses older naming conventions,
-# but it belongs here, not in the file `backward',
+# but it belongs here, not in the file 'backward',
 # as functions like gmtime load the "GMT" file to handle leap seconds properly.
 # We want this to work even on installations that omit the other older names.
 Link	Etc/GMT				GMT
--- a/jdk/make/data/tzdata/europe	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/europe	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2014-05-31):
 # A good source for time zone historical data outside the U.S. is
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
 # San Diego: ACS Publications, Inc. (2003).
@@ -40,6 +40,9 @@
 # published semiannually.  Law sent in several helpful summaries
 # of the IATA's data after 1990.
 #
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
 # Except where otherwise noted, Shanks & Pottenger is the source for
 # entries through 1991, and IATA SSIM is the source for entries afterwards.
 #
@@ -49,9 +52,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	<a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
 #	William Willett, The Waste of Daylight, 19th edition
-#	</a> (1914-03)
+#	<http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	<http://www.jstor.org/stable/1774359>.  He writes:
@@ -59,10 +62,20 @@
 #	may be sent to Mr. John Milne, Royal Geographical Society,
 #	Savile Row, London."  Nowadays please email them to tz@iana.org.
 #
-#	Brazil's Departamento Servico da Hora (DSH),
-#	<a href="http://pcdsh01.on.br/HISTHV.htm">
+#	Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+#	This Russian-language source was consulted by Vladimir Karpinsky; see
+#	http://mm.icann.org/pipermail/tz/2014-August/021320.html
+#	The full Russian citation is:
+#	Бялокоз, Евгений Людвигович. Новый счет времени в течении суток
+#	введенный декретом Совета народных комиссаров для всей России с 1-го
+#	июля 1919 г. / Изд. 2-е Междуведомственной комиссии. - Петроград:
+#	Десятая гос. тип., 1919.
+#	http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf
+#
+#	Brazil's Divisão Serviço da Hora (DSHO),
 #	History of Summer Time
-#	</a> (1998-09-21, in Portuguese)
+#	<http://pcdsh01.on.br/HISTHV.htm>
+#	(1998-09-21, in Portuguese)
 
 #
 # I invented the abbreviations marked '*' in the following table;
@@ -81,10 +94,8 @@
 #        1:00       CET CEST CEMT Central Europe
 #        1:00:14    SET           Swedish (1879-1899)*
 #        2:00       EET EEST      Eastern Europe
-#        3:00       MSK MSD       Moscow
-#
-# A reliable and entertaining source about time zones, especially in Britain,
-# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#        3:00       FET           Further-eastern Europe*
+#        3:00       MSK MSD  MSM* Moscow
 
 # From Peter Ilieve (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -128,7 +139,7 @@
 # along the towpath within a few yards of it.'
 #
 # I have a one inch to one mile map of London and my estimate of the stone's
-# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# position is 51 degrees 28' 30" N, 0 degrees 18' 45" W. The longitude should
 # be within about +-2". The Ordnance Survey grid reference is TQ172761.
 #
 # [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
@@ -160,8 +171,22 @@
 # transition date for London, namely 1847-12-01.  We don't know as much
 # about Dublin, so we use 1880-08-02, the legal transition time.
 
-# From Paul Eggert (2003-09-27):
-# Summer Time was first seriously proposed by William Willett (1857-1915),
+# From Paul Eggert (2014-07-19):
+# The ancients had no need for daylight saving, as they kept time
+# informally or via hours whose length depended on the time of year.
+# Daylight saving time in its modern sense was invented by the
+# New Zealand entomologist George Vernon Hudson (1867-1946),
+# whose day job as a postal clerk led him to value
+# after-hours daylight in which to pursue his research.
+# In 1895 he presented a paper to the Wellington Philosophical Society
+# that proposed a two-hour daylight-saving shift.  See:
+# Hudson GV. On seasonal time-adjustment in countries south of lat. 30 deg.
+# Transactions and Proceedings of the New Zealand Institute. 1895;28:734
+# http://rsnz.natlib.govt.nz/volume/rsnz_28/rsnz_28_00_006110.html
+# Although some interest was expressed in New Zealand, his proposal
+# did not find its way into law and eventually it was almost forgotten.
+#
+# In England, DST was independently reinvented by William Willett (1857-1915),
 # a London builder and member of the Royal Astronomical Society
 # who circulated a pamphlet "The Waste of Daylight" (1907)
 # that proposed advancing clocks 20 minutes on each of four Sundays in April,
@@ -174,7 +199,7 @@
 # A monument to Willett was unveiled on 1927-05-21, in an open space in
 # a 45-acre wood near Chislehurst, Kent that was purchased by popular
 # subscription and open to the public.  On the south face of the monolith,
-# designed by G. W. Miller, is the...William Willett Memorial Sundial,
+# designed by G. W. Miller, is the William Willett Memorial Sundial,
 # which is permanently set to Summer Time.
 
 # From Winston Churchill (1934-04-28):
@@ -183,9 +208,9 @@
 # between 160 and 170 hours more daylight leisure, to a war which
 # plunged Europe into darkness for four years, and shook the
 # foundations of civilization throughout the world.
-#	-- <a href="http://www.winstonchurchill.org/fh114willett.htm">
-#	"A Silent Toast to William Willett", Pictorial Weekly
-#	</a>
+#	-- "A Silent Toast to William Willett", Pictorial Weekly;
+#	republished in Finest Hour (Spring 2002) 1(114):26
+#	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
 
 # From Paul Eggert (1996-09-03):
 # The OED Supplement says that the English originally said "Daylight Saving"
@@ -194,7 +219,6 @@
 # proponents (who eventually won the argument) are quoted as using "Summer".
 
 # From Arthur David Olson (1989-01-19):
-#
 # A source at the British Information Office in New York avers that it's
 # known as "British" Summer Time in all parts of the United Kingdom.
 
@@ -221,8 +245,8 @@
 # official designation; the reply of the 21st was that there wasn't
 # but he couldn't think of anything better than the "Double British
 # Summer Time" that the BBC had been using informally.
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+# http://www.polyomino.org.uk/british-time/bbc-19410418.png
+# http://www.polyomino.org.uk/british-time/ho-19410421.png
 
 # From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
 # [N]o official designation has as far as I know been adopted for the time
@@ -239,23 +263,14 @@
 # the history of summer time legislation in the United Kingdom.
 # Since 1998 Joseph S. Myers has been updating
 # and extending this list, which can be found in
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/
-# <a href="http://www.polyomino.org.uk/british-time/">
-# History of legal time in Britain
-# </a>
-# Rob Crowther (2012-01-04) reports that that URL no longer
-# exists, and the article can now be found at:
-# <a href="http://www.polyomino.org.uk/british-time/">
 # http://www.polyomino.org.uk/british-time/
-# </a>
 
 # From Joseph S. Myers (1998-01-06):
 #
 # The legal time in the UK outside of summer time is definitely GMT, not UTC;
 # see Lord Tanlaw's speech
-# <a href="http://www.parliament.the-stationery-office.co.uk/pa/ld199697/ldhansrd/pdvn/lds97/text/70611-20.htm#70611-20_head0">
-# (Lords Hansard 11 June 1997 columns 964 to 976)
-# </a>.
+# http://www.publications.parliament.uk/pa/ld199798/ldhansrd/vo970611/text/70611-10.htm#70611-10_head0
+# (Lords Hansard 11 June 1997 columns 964 to 976).
 
 # From Paul Eggert (2006-03-22):
 #
@@ -295,8 +310,8 @@
 #   -- James Joyce, Ulysses
 
 # From Joseph S. Myers (2005-01-26):
-# Irish laws are available online at www.irishstatutebook.ie.  These include
-# various relating to legal time, for example:
+# Irish laws are available online at <http://www.irishstatutebook.ie>.
+# These include various relating to legal time, for example:
 #
 # ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
 #
@@ -458,25 +473,27 @@
 # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
+Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
 			 0:00	GB-Eire	%s	1968 Oct 27
-			 1:00	-	BST	1971 Oct 31 2:00u
+			 1:00	-	BST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	%s	1996
 			 0:00	EU	GMT/BST
 Link	Europe/London	Europe/Jersey
 Link	Europe/London	Europe/Guernsey
 Link	Europe/London	Europe/Isle_of_Man
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
-			-0:25:21 -	DMT	1916 May 21 2:00
-			-0:25:21 1:00	IST	1916 Oct  1 2:00s
+			-0:25:21 -	DMT	1916 May 21  2:00
+			-0:25:21 1:00	IST	1916 Oct  1  2:00s
 			 0:00	GB-Eire	%s	1921 Dec  6 # independence
-			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
-			 0:00	1:00	IST	1946 Oct  6 2:00
-			 0:00	-	GMT	1947 Mar 16 2:00
-			 0:00	1:00	IST	1947 Nov  2 2:00
-			 0:00	-	GMT	1948 Apr 18 2:00
+			 0:00	GB-Eire	GMT/IST	1940 Feb 25  2:00
+			 0:00	1:00	IST	1946 Oct  6  2:00
+			 0:00	-	GMT	1947 Mar 16  2:00
+			 0:00	1:00	IST	1947 Nov  2  2:00
+			 0:00	-	GMT	1948 Apr 18  2:00
 			 0:00	GB-Eire	GMT/IST	1968 Oct 27
-			 1:00	-	IST	1971 Oct 31 2:00u
+			 1:00	-	IST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	GMT/IST	1996
 			 0:00	EU	GMT/IST
 
@@ -495,10 +512,9 @@
 Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
 # The most recent directive covers the years starting in 2002.  See:
-# <a="http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT">
 # Directive 2000/84/EC of the European Parliament and of the Council
 # of 19 January 2001 on summer-time arrangements.
-# </a>
+# http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT
 
 # W-Eur differs from EU only in that W-Eur uses standard time.
 Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
@@ -521,18 +537,18 @@
 Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
 # Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
 Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
-# From Jesper Norgaard Welen (2008-07-13):
+# From Jesper Nørgaard Welen (2008-07-13):
 #
 # I found what is probably a typo of 2:00 which should perhaps be 2:00s
 # in the C-Eur rule from tz database version 2008d (this part was
-# corrected in version 2008d). The circumstancial evidence is simply the
+# corrected in version 2008d). The circumstantial evidence is simply the
 # tz database itself, as seen below:
 #
 # Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
 #    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
-#    0:00 France WE%sT 1945 Sep 16 3:00
+#    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Belgrade 1:22:00 - LMT 1884
 #    1:00 1:00 CEST 1945 Sep 16  2:00s
@@ -576,16 +592,16 @@
 Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
-Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
-Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
+Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST  # Moscow Summer Time
+Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT  # Moscow Mean Time
+Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST # Moscow Double Summer Time
 Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
 Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
-Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
-Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
-Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
-Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
-Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
+Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	MSD
+Rule	Russia	1919	only	-	Aug	16	 0:00	0	MSK
+Rule	Russia	1921	only	-	Feb	14	23:00	1:00	MSD
+Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
+Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
 Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
 # Act No.925 of the Council of Ministers of the USSR (1980-10-24):
 Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
@@ -607,14 +623,10 @@
 # According to the law Russia is abolishing daylight saving time.
 #
 # Medvedev signed a law "On the Calculation of Time" (in russian):
-# <a href="http://bmockbe.ru/events/?ID=7583">
 # http://bmockbe.ru/events/?ID=7583
-# </a>
 #
 # Medvedev signed a law on the calculation of the time (in russian):
-# <a href="http://www.regnum.ru/news/polit/1413906.html">
 # http://www.regnum.ru/news/polit/1413906.html
-# </a>
 
 # From Arthur David Olson (2011-06-15):
 # Take "abolishing daylight saving time" to mean that time is now considered
@@ -634,10 +646,10 @@
 # From Markus Kuhn (1996-07-12):
 # The official German names ... are
 #
-#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
-#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
+#	Mitteleuropäische Zeit (MEZ)         = UTC+01:00
+#	Mitteleuropäische Sommerzeit (MESZ)  = UTC+02:00
 #
-# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# as defined in the German Time Act (Gesetz über die Zeitbestimmung (ZeitG),
 # 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
 # I wrote ... to the German Federal Physical-Technical Institution
 #
@@ -692,7 +704,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Andorra	0:06:04 -	LMT	1901
 			0:00	-	WET	1946 Sep 30
-			1:00	-	CET	1985 Mar 31 2:00
+			1:00	-	CET	1985 Mar 31  2:00
 			1:00	EU	CE%sT
 
 # Austria
@@ -718,9 +730,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1920
-			1:00	Austria	CE%sT	1940 Apr  1 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
-			1:00	1:00	CEST	1945 Apr 12 2:00s
+			1:00	Austria	CE%sT	1940 Apr  1  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
+			1:00	1:00	CEST	1945 Apr 12  2:00s
 			1:00	-	CET	1946
 			1:00	Austria	CE%sT	1981
 			1:00	EU	CE%sT
@@ -731,38 +743,29 @@
 # GMT+3 without DST (was GMT+2 with DST).
 #
 # Sources (Russian language):
-# 1.
-# <a href="http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html">
 # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
-# </a>
-# 2.
-# <a href="http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/">
 # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
-# </a>
-# 3.
-# <a href="http://news.tut.by/society/250578.html">
 # http://news.tut.by/society/250578.html
-# </a>
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
-			1:50	-	MMT	1924 May 2 # Minsk Mean Time
+			1:50	-	MMT	1924 May  2 # Minsk Mean Time
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Jun 28
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
-			2:00	-	EET	1992 Mar 29 0:00s
-			2:00	1:00	EEST	1992 Sep 27 0:00s
-			2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			3:00	-	FET # Further-eastern European Time
+			3:00	-	MSK	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
+			2:00	-	EET	1992 Mar 29  0:00s
+			2:00	1:00	EEST	1992 Sep 27  0:00s
+			2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			3:00	-	FET
 
 # Belgium
 #
 # From Paul Eggert (1997-07-02):
 # Entries from 1918 through 1991 are taken from:
 #	Annuaire de L'Observatoire Royal de Belgique,
-#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
 #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
 #	pp 8-9.
 # LMT before 1892 was 0:17:30, according to the official journal of Belgium:
@@ -812,7 +815,7 @@
 Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Brussels	0:17:30 -	LMT	1880
-			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
+			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
 			0:00	-	WET	1914 Nov  8
 			1:00	-	CET	1916 May  1  0:00
 			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
@@ -828,8 +831,8 @@
 #
 # From Plamen Simenov via Steffen Thorsen (1999-09-09):
 # A document of Government of Bulgaria (No.94/1997) says:
-# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
-# EETDST --> EET is in 04:00 Local time in last Sunday of October
+# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST -> EET is in 04:00 Local time in last Sunday of October
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
@@ -842,7 +845,7 @@
 			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
 			2:00	-	EET	1942 Nov  2  3:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 Apr 2 3:00
+			1:00	-	CET	1945 Apr  2  3:00
 			2:00	-	EET	1979 Mar 31 23:00
 			2:00	Bulg	EE%sT	1982 Sep 26  2:00
 			2:00	C-Eur	EE%sT	1991
@@ -866,15 +869,15 @@
 Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Prague	0:57:44 -	LMT	1850
-			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
-			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
+			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
+			1:00	C-Eur	CE%sT	1944 Sep 17  2:00s
 			1:00	Czech	CE%sT	1979
 			1:00	EU	CE%sT
 # Use Europe/Prague also for Slovakia.
 
 # Denmark, Faroe Islands, and Greenland
 
-# From Jesper Norgaard Welen (2005-04-26):
+# From Jesper Nørgaard Welen (2005-04-26):
 # http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
 # [introducing standard time] was in effect from 1894-01-01....
 # The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
@@ -884,7 +887,7 @@
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
 #
 # This provoked a new law from 1974 to make possible summer time changes
-# in subsequenet decrees with the law
+# in subsequent decrees with the law
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
 #
 # It seems however that no decree was set forward until 1980.  I have
@@ -899,7 +902,7 @@
 # was suspended on that night):
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
 
-# From Jesper Norgaard Welen (2005-06-11):
+# From Jesper Nørgaard Welen (2005-06-11):
 # The Herning Folkeblad (1980-09-26) reported that the night between
 # Saturday and Sunday the clock is set back from three to two.
 
@@ -923,11 +926,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
 			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
-			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
-			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
+			 1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			 1:00	Denmark	CE%sT	1980
 			 1:00	EU	CE%sT
-Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
+Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11 # Tórshavn
 			 0:00	-	WET	1981
 			 0:00	EU	WE%sT
 #
@@ -939,11 +942,11 @@
 # From Paul Eggert (2006-03-22):
 # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
 # and left the EU on 1985-02-01.  It therefore should have been using EU
-# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
+# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthåb
 # used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
 # rules since at least 1991.  Assume EU rules since 1980.
 
-# From Gwillin Law (2001-06-06), citing
+# From Gwillim Law (2001-06-06), citing
 # <http://www.statkart.no/efs/efshefter/2001/efs5-2001.pdf> (2001-03-15),
 # and with translations corrected by Steffen Thorsen:
 #
@@ -978,16 +981,16 @@
 # DPC research station at Zackenberg.
 #
 # Scoresbysund and two small villages nearby keep time UTC-1 and use
-# the same daylight savings time period as in West Greenland (Godthab).
+# the same daylight savings time period as in West Greenland (Godthåb).
 #
-# The rest of Greenland, including Godthab (this area, although it
+# The rest of Greenland, including Godthåb (this area, although it
 # includes central Greenland, is known as west Greenland), keeps time
 # UTC-3, with daylight savings methods according to European rules.
 #
 # It is common procedure to use UTC 0 in the wilderness of East and
 # North Greenland, because it is mainly Icelandic aircraft operators
 # maintaining traffic in these areas.  However, the official status of
-# this area is that it sticks with Godthab time.  This area might be
+# this area is that it sticks with Godthåb time.  This area might be
 # considered a dual time zone in some respects because of this.
 
 # From Rives McDow (2001-11-19):
@@ -996,8 +999,8 @@
 
 # From Paul Eggert (2006-03-22):
 # From 1997 on the CIA map shows Danmarkshavn on GMT;
-# the 1995 map as like Godthab.
-# For lack of better info, assume they were like Godthab before 1996.
+# the 1995 map as like Godthåb.
+# For lack of better info, assume they were like Godthåb before 1996.
 # startkart.no says Thule does not observe DST, but this is clearly an error,
 # so go with Shanks & Pottenger for Thule transitions until this year.
 # For 2007 on assume Thule will stay in sync with US DST rules.
@@ -1012,15 +1015,15 @@
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT	1996
 			0:00	-	GMT
 Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
-			-2:00	-	CGT	1980 Apr  6 2:00
+			-2:00	-	CGT	1980 Apr  6  2:00
 			-2:00	C-Eur	CG%sT	1981 Mar 29
 			-1:00	EU	EG%sT
 Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT
 Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 			-4:00	Thule	A%sT
@@ -1042,17 +1045,16 @@
 # summer time next spring."
 
 # From Peter Ilieve (1998-11-04), heavily edited:
-# <a href="http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390">
 # The 1998-09-22 Estonian time law
-# </a>
+# http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390
 # refers to the Eighth Directive and cites the association agreement between
-# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22-27, 120).
 #
 # I also asked [my relative] whether they use any standard abbreviation
 # for their standard and summer times. He says no, they use "suveaeg"
 # (summer time) and "talveaeg" (winter time).
 
-# From <a href="http://www.baltictimes.com/">The Baltic Times</a> (1999-09-09)
+# From The Baltic Times <http://www.baltictimes.com/> (1999-09-09)
 # via Steffen Thorsen:
 # This year will mark the last time Estonia shifts to summer time,
 # a council of the ruling coalition announced Sept. 6....
@@ -1070,19 +1072,19 @@
 # The Estonian government has changed once again timezone politics.
 # Now we are using again EU rules.
 #
-# From Urmet Jaanes (2002-03-28):
+# From Urmet Jänes (2002-03-28):
 # The legislative reference is Government decree No. 84 on 2002-02-21.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tallinn	1:39:00	-	LMT	1880
-			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
+			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
 			1:00	C-Eur	CE%sT	1919 Jul
 			1:39:00	-	TMT	1921 May
 			2:00	-	EET	1940 Aug  6
 			3:00	-	MSK	1941 Sep 15
 			1:00	C-Eur	CE%sT	1944 Sep 22
-			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
-			2:00	1:00	EEST	1989 Sep 24 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
+			2:00	1:00	EEST	1989 Sep 24  2:00s
 			2:00	C-Eur	EE%sT	1998 Sep 22
 			2:00	EU	EE%sT	1999 Nov  1
 			2:00	-	EET	2002 Feb 21
@@ -1104,35 +1106,45 @@
 # This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
 # Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
 # Finnish) at
-#
-# <a href="http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf">
 # http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
-# </a>
 #
 # Page 105 (56 in PDF version) has a handy table of all past daylight savings
 # transitions. It is easy enough to interpret without Finnish skills.
 #
 # This is also confirmed by Finnish Broadcasting Company's archive at:
-#
-# <a href="http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401">
 # http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
-# </a>
 #
 # The news clip from 1981 says that "the time between 2 and 3 o'clock does not
 # exist tonight."
 
+# From Konstantin Hyppönen (2014-06-13):
+# [Heikki Oja's book Aikakirja 2013]
+# http://almanakka.helsinki.fi/images/aikakirja/Aikakirja2013kokonaan.pdf
+# pages 104-105, including a scan from a newspaper published on Apr 2 1942
+# say that ... [o]n Apr 2 1942, 24 o'clock (which means Apr 3 1942,
+# 00:00), clocks were moved one hour forward. The newspaper
+# mentions "on the night from Thursday to Friday"....
+# On Oct 4 1942, clocks were moved at 1:00 one hour backwards.
+#
+# From Paul Eggert (2014-06-14):
+# Go with Oja over Shanks.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
-Rule	Finland	1942	only	-	Oct	3	0:00	0	-
+Rule	Finland	1942	only	-	Apr	2	24:00	1:00	S
+Rule	Finland	1942	only	-	Oct	4	1:00	0	-
 Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
 Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
+
+# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
+# round to nearest.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
-			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
+Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
+			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
 			2:00	Finland	EE%sT	1983
 			2:00	EU	EE%sT
 
-# Aaland Is
+# Åland Is
 Link	Europe/Helsinki	Europe/Mariehamn
 
 
@@ -1140,14 +1152,14 @@
 
 # From Ciro Discepolo (2000-12-20):
 #
-# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Henri Le Corre, Régimes horaires pour le monde entier, Éditions
 # Traditionnelles - Paris 2 books, 1993
 #
-# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Gabriel, Traité de l'heure dans le monde, Guy Trédaniel,
 # Paris, 1991
 #
-# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
-# Guy tredaniel, Paris 1987
+# Françoise Gauquelin, Problèmes de l'heure résolus en astrologie,
+# Guy Trédaniel, Paris 1987
 
 
 #
@@ -1188,16 +1200,16 @@
 Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
 # The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
 # write that they were used in Monaco and in many French locations.
-# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
-# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
-# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
+# Le Corre writes that the upper limit of the free zone was Arnéguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamothe-Montravel, Marœuil, La
+# Rochefoucauld, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
 # Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
-# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Paray-le-Monial, Montceau-les-Mines, Chalon-sur-Saône, Arbois,
 # Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
 Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
 # Shanks & Pottenger say this transition occurred at Oct 6 1:00,
 # but go with Denis Excoffier (1997-12-12),
-# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# who quotes the Ephémérides astronomiques for 1998 from Bureau des Longitudes
 # as saying 5/10/41 22hUT.
 Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
 Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
@@ -1218,7 +1230,7 @@
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
-			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
+			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
 # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
 			0:00	France	WE%sT	1940 Jun 14 23:00
 # Le Corre says Paris stuck with occupied-France time after the liberation;
@@ -1235,15 +1247,13 @@
 # Bundesanstalt contains DST information back to 1916.
 # [See tz-link.htm for the URL.]
 
-# From Joerg Schilling (2002-10-23):
+# From Jörg Schilling (2002-10-23):
 # In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
-# <a href="http://www.dhm.de/lemo/html/biografien/BersarinNikolai/">
-# General [Nikolai] Bersarin</a>.
+# http://www.dhm.de/lemo/html/biografien/BersarinNikolai/
+# General [Nikolai] Bersarin.
 
 # From Paul Eggert (2003-03-08):
-# <a href="http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf">
 # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
-# </a>
 # says that Bersarin issued an order to use Moscow time on May 20.
 # However, Moscow did not observe daylight saving in 1945, so
 # this was equivalent to CEMT (GMT+3), not GMT+4.
@@ -1268,23 +1278,23 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
-			1:00	C-Eur	CE%sT	1945 May 24 2:00
+			1:00	C-Eur	CE%sT	1945 May 24  2:00
 			1:00 SovietZone	CE%sT	1946
 			1:00	Germany	CE%sT	1980
 			1:00	EU	CE%sT
 
 # From Tobias Conradi (2011-09-12):
-# Busingen <http://www.buesingen.de>, surrounded by the Swiss canton
+# Büsingen <http://www.buesingen.de>, surrounded by the Swiss canton
 # Schaffhausen, did not start observing DST in 1980 as the rest of DE
 # (West Germany at that time) and DD (East Germany at that time) did.
 # DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
 # which in turn is covered by the zone Europe/Berlin.
 #
-# Source for the time in Busingen 1980:
+# Source for the time in Büsingen 1980:
 # http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
 
 # From Arthur David Olson (2012-03-03):
-# Busingen and Zurich have shared clocks since 1970.
+# Büsingen and Zurich have shared clocks since 1970.
 
 Link	Europe/Zurich	Europe/Busingen
 
@@ -1295,8 +1305,8 @@
 
 # Gibraltar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
-			0:00	GB-Eire	%s	1957 Apr 14 2:00
+Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
+			0:00	GB-Eire	%s	1957 Apr 14  2:00
 			1:00	-	CET	1982
 			1:00	EU	CE%sT
 
@@ -1327,7 +1337,7 @@
 Rule	Greece	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
-			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
+			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
 			2:00	Greece	EE%sT	1941 Apr 30
 			1:00	Greece	CE%sT	1944 Apr  4
 			2:00	Greece	EE%sT	1981
@@ -1336,15 +1346,20 @@
 			2:00	EU	EE%sT
 
 # Hungary
+# From Paul Eggert (2014-07-15):
+# Dates for 1916-1945 are taken from:
+# Oross A. Jelen a múlt jövője: a nyári időszámítás Magyarországon 1916-1945.
+# National Archives of Hungary (2012-10-29).
+# http://mnl.gov.hu/a_het_dokumentuma/a_nyari_idoszamitas_magyarorszagon_19161945.html
+# This source does not always give times, which are taken from Shanks
+# & Pottenger (which disagree about the dates).
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
-Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
+Rule	Hungary	1918	only	-	Sep	16	 3:00	0	-
 Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
-Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
-Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
-Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
+Rule	Hungary	1919	only	-	Nov	24	 3:00	0	-
 Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
-Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
+Rule	Hungary	1945	only	-	Nov	 1	 0:00	0	-
 Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
 Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
 Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
@@ -1360,7 +1375,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
 			1:00	C-Eur	CE%sT	1918
-			1:00	Hungary	CE%sT	1941 Apr  6  2:00
+			1:00	Hungary	CE%sT	1941 Apr  8
 			1:00	C-Eur	CE%sT	1945
 			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
 			1:00	EU	CE%sT
@@ -1423,7 +1438,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
-			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
+			-1:00	Iceland	IS%sT	1968 Apr  7  1:00s
 			 0:00	-	GMT
 
 # Italy
@@ -1438,9 +1453,8 @@
 # From Paul Eggert (2006-03-22):
 # For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
 # F. Pollastri
-# <a href="http://toi.iriti.cnr.it/uk/ienitlt.html">
 # Day-light Saving Time in Italy (2006-02-03)
-# </a>
+# http://toi.iriti.cnr.it/uk/ienitlt.html
 # ('FP' below), taken from an Italian National Electrotechnical Institute
 # publication. When the three sources disagree, guess who's right, as follows:
 #
@@ -1500,8 +1514,8 @@
 Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
-			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
+			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
 			1:00	C-Eur	CE%sT	1944 Jul
 			1:00	Italy	CE%sT	1980
 			1:00	EU	CE%sT
@@ -1548,18 +1562,18 @@
 
 # From Andrei Ivanov (2000-03-06):
 # This year Latvia will not switch to Daylight Savings Time (as specified in
-# <a href="http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm">
 # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79)</a>, in Latvian for subscribers only).
+# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
+# in Latvian for subscribers only).
 
-# <a href="http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html">
-# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
-# </a>
+# From RFE/RL Newsline
+# http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html
+# (2001-01-03), noted after a heads-up by Rives McDow:
 # The Latvian government on 2 January decided that the country will
 # institute daylight-saving time this spring, LETA reported.
 # Last February the three Baltic states decided not to turn back their
 # clocks one hour in the spring....
-# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# Minister of Economy Aigars Kalvītis noted that Latvia had too few
 # daylight hours and thus decided to comply with a draft European
 # Commission directive that provides for instituting daylight-saving
 # time in EU countries between 2002 and 2006. The Latvian government
@@ -1569,18 +1583,23 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
+
+# Milne 1899 says Riga was 1:36:28 (Polytechnique House time).
+# Byalokoz 1919 says Latvia was 1:36:34.
+# Go with Byalokoz.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Riga	1:36:24	-	LMT	1880
-			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
-			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
-			1:36:24	-	RMT	1919 Apr  1 2:00
-			1:36:24	1:00	LST	1919 May 22 3:00
-			1:36:24	-	RMT	1926 May 11
+Zone	Europe/Riga	1:36:34	-	LMT	1880
+			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
+			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
+			1:36:34	-	RMT	1919 Apr  1  2:00
+			1:36:34	1:00	LST	1919 May 22  3:00
+			1:36:34	-	RMT	1926 May 11
 			2:00	-	EET	1940 Aug  5
 			3:00	-	MSK	1941 Jul
 			1:00	C-Eur	CE%sT	1944 Oct 13
-			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
-			2:00	1:00	EEST	1989 Sep lastSun 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar lastSun  2:00s
+			2:00	1:00	EEST	1989 Sep lastSun  2:00s
 			2:00	Latvia	EE%sT	1997 Jan 21
 			2:00	EU	EE%sT	2000 Feb 29
 			2:00	-	EET	2001 Jan  2
@@ -1614,7 +1633,7 @@
 # I would like to inform that in this year Lithuanian time zone
 # (Europe/Vilnius) was changed.
 
-# From <a href="http://www.elta.lt/">ELTA</a> No. 972 (2582) (1999-09-29),
+# From ELTA No. 972 (2582) (1999-09-29) <http://www.elta.lt/>,
 # via Steffen Thorsen:
 # Lithuania has shifted back to the second time zone (GMT plus two hours)
 # to be valid here starting from October 31,
@@ -1623,9 +1642,9 @@
 # motion to give up shifting to summer time in spring, as it was
 # already done by Estonia.
 
-# From the <a href="http://www.tourism.lt/informa/ff.htm">
-# Fact File, Lithuanian State Department of Tourism
-# </a> (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+# From the Fact File, Lithuanian State Department of Tourism
+# <http://www.tourism.lt/informa/ff.htm> (2000-03-27):
+# Local time is GMT+2 hours ..., no daylight saving.
 
 # From a user via Klaus Marten (2003-02-07):
 # As a candidate for membership of the European Union, Lithuania will
@@ -1638,18 +1657,18 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vilnius	1:41:16	-	LMT	1880
-			1:24:00	-	WMT	1917	    # Warsaw Mean Time
+			1:24:00	-	WMT	1917        # Warsaw Mean Time
 			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
 			1:00	-	CET	1920 Jul 12
 			2:00	-	EET	1920 Oct  9
 			1:00	-	CET	1940 Aug  3
 			3:00	-	MSK	1941 Jun 24
 			1:00	C-Eur	CE%sT	1944 Aug
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
 			2:00	C-Eur	EE%sT	1998
-			2:00	-	EET	1998 Mar 29 1:00u
-			1:00	EU	CE%sT	1999 Oct 31 1:00u
+			2:00	-	EET	1998 Mar 29  1:00u
+			1:00	EU	CE%sT	1999 Oct 31  1:00u
 			2:00	-	EET	2003 Jan  1
 			2:00	EU	EE%sT
 
@@ -1683,9 +1702,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 			1:00	Lux	CE%sT	1918 Nov 25
-			0:00	Lux	WE%sT	1929 Oct  6 2:00s
-			0:00	Belgium	WE%sT	1940 May 14 3:00
-			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
+			0:00	Lux	WE%sT	1929 Oct  6  2:00s
+			0:00	Belgium	WE%sT	1940 May 14  3:00
+			1:00	C-Eur	WE%sT	1944 Sep 18  3:00
 			1:00	Belgium	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1702,9 +1721,9 @@
 Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
+Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
 			1:00	EU	CE%sT
@@ -1719,7 +1738,7 @@
 # In early 1992 there was large-scale interethnic violence in the area
 # and it's possible that some Russophones continued to observe Moscow time.
 # But [two people] separately reported via
-# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# Jesper Nørgaard that as of 2001-01-24 Tiraspol was like Chisinau.
 # The Tiraspol entry has therefore been removed for now.
 #
 # From Alexander Krivenyshev (2011-10-17):
@@ -1728,13 +1747,8 @@
 # to the Winter Time).
 #
 # News (in Russian):
-# <a href="http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html">
 # http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
-# </a>
-#
-# <a href="http://www.allmoldova.com/moldova-news/1249064116.html">
 # http://www.allmoldova.com/moldova-news/1249064116.html
-# </a>
 #
 # The substance of this change (reinstatement of the Tiraspol entry)
 # is from a patch from Petr Machata (2011-10-17)
@@ -1752,9 +1766,7 @@
 # Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
 # Tiraspol will go back to winter time on October 30, 2011.
 # News from Moldova (in russian):
-# <a href="http://ru.publika.md/link_317061.html">
 # http://ru.publika.md/link_317061.html
-# </a>
 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1777,8 +1789,8 @@
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	France	WE%sT	1945 Sep 16 3:00
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	France	WE%sT	1945 Sep 16  3:00
 			1:00	France	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1822,8 +1834,8 @@
 # was not until 1866 when they were all required by law to observe
 # Amsterdam mean time.
 
-# The data before 1945 are taken from
-# <http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm>.
+# The data entries before 1945 are taken from
+# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -1854,8 +1866,8 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Amsterdam	0:19:32 -	LMT	1835
 			0:19:32	Neth	%s	1937 Jul  1
-			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			0:20	Neth	NE%sT	1940 May 16  0:00 # Dutch Time
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			1:00	Neth	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1885,14 +1897,14 @@
 # time they were declared as parts of Norway.  Svalbard was declared
 # as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
 # Mayen by law of 1930-02-27 no 2, section 2. (From
-# http://www.lovdata.no/all/nl-19250717-011.html and
-# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
+# <http://www.lovdata.no/all/nl-19250717-011.html> and
+# <http://www.lovdata.no/all/nl-19300227-002.html>).  The law/regulation
 # for normal/standard time in Norway is from 1894-06-29 no 1 (came
 # into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
 # part of this law since 1925/1930. (From
-# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
+# <http://www.lovdata.no/all/nl-18940629-001.html>) I have not been
 # able to find if Jan Mayen used a different time zone (e.g. -0100)
-# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
+# before 1930. Jan Mayen has only been "inhabited" since 1921 by
 # Norwegian meteorologists and maybe used the same time as Norway ever
 # since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
 # before 1895, and therefore probably changed the local time somewhere
@@ -1907,7 +1919,7 @@
 # <http://home.no.net/janmayen/history.htm> says that the meteorologists
 # burned down their station in 1940 and left the island, but returned in
 # 1941 with a small Norwegian garrison and continued operations despite
-# frequent air ttacks from Germans.  In 1943 the Americans established a
+# frequent air attacks from Germans.  In 1943 the Americans established a
 # radiolocating station on the island, called "Atlantic City".  Possibly
 # the UT offset changed during the war, but I think it unlikely that
 # Jan Mayen used German daylight-saving rules.
@@ -1918,7 +1930,7 @@
 # <http://www.svalbard.com/SvalbardFAQ.html> says that the Germans were
 # expelled on 1942-05-14.  However, small parties of Germans did return,
 # and according to Wilhelm Dege's book "War North of 80" (1954)
-# <http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html>
+# http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html
 # the German armed forces at the Svalbard weather station code-named
 # Haudegen did not surrender to the Allies until September 1945.
 #
@@ -1927,6 +1939,10 @@
 Link	Europe/Oslo	Arctic/Longyearbyen
 
 # Poland
+
+# The 1919 dates and times can be found in Tygodnik Urzędowy nr 1 (1919-03-20),
+# <http://www.wbc.poznan.pl/publication/32156> pp 1-2.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
 Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
@@ -1937,9 +1953,9 @@
 Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
 Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
 # For 1946 on the source is Kazimierz Borkowski,
-# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
-# <http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1>
-# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
+# Toruń Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
+# http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1
+# Thanks to Przemysław Augustyniak (2005-05-28) for this reference.
 # He also gives these further references:
 # Mon Pol nr 13, poz 162 (1995) <http://www.abc.com.pl/serwis/mp/1995/0162.htm>
 # Druk nr 2180 (2003) <http://www.senat.gov.pl/k5/dok/sejm/053/2180.pdf>
@@ -1959,10 +1975,10 @@
 Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Warsaw	1:24:00 -	LMT	1880
-			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
-			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
+			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
+			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
 			2:00	Poland	EE%sT	1922 Jun
-			1:00	Poland	CE%sT	1940 Jun 23 2:00
+			1:00	Poland	CE%sT	1940 Jun 23  2:00
 			1:00	C-Eur	CE%sT	1944 Oct
 			1:00	Poland	CE%sT	1977
 			1:00	W-Eur	CE%sT	1988
@@ -1970,6 +1986,14 @@
 
 # Portugal
 #
+# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
+# According to a Portuguese decree (1911-05-26)
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00.
+# Round the old offset to -0:36:45.  This agrees with Willett but disagrees
+# with Shanks, who says the transition occurred on 1911-05-24 at 00:00 for
+# Europe/Lisbon, Atlantic/Azores, and Atlantic/Madeira.
+#
 # From Rui Pedro Salgueiro (1992-11-12):
 # Portugal has recently (September, 27) changed timezone
 # (from WET to MET or CET) to harmonize with EEC.
@@ -2049,35 +2073,34 @@
 Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
 Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
-# Willett says 1912-01-01.  Go with Willett.
-Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
-			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
-			 0:00	Port	WE%sT	1966 Apr  3 2:00
-			 1:00	-	CET	1976 Sep 26 1:00
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
-			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
-			 1:00	EU	CE%sT	1996 Mar 31 1:00u
+Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
+			-0:36:45 -	LMT	1912 Jan  1 # Lisbon Mean Time
+			 0:00	Port	WE%sT	1966 Apr  3  2:00
+			 1:00	-	CET	1976 Sep 26  1:00
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
+			 0:00	W-Eur	WE%sT	1992 Sep 27  1:00s
+			 1:00	EU	CE%sT	1996 Mar 31  1:00u
 			 0:00	EU	WE%sT
-Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
-			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
-			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
-			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
-			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
-			 0:00	EU	WE%sT	1993 Mar 28 1:00u
+Zone Atlantic/Azores	-1:42:40 -	LMT	1884        # Ponta Delgada
+			-1:54:32 -	HMT	1912 Jan  1 # Horta Mean Time
+			-2:00	Port	AZO%sT	1966 Apr  3  2:00  # Azores Time
+			-1:00	Port	AZO%sT	1983 Sep 25  1:00s
+			-1:00	W-Eur	AZO%sT	1992 Sep 27  1:00s
+			 0:00	EU	WE%sT	1993 Mar 28  1:00u
 			-1:00	EU	AZO%sT
-Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
-			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
-			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
+Zone Atlantic/Madeira	-1:07:36 -	LMT	1884        # Funchal
+			-1:07:36 -	FMT	1912 Jan  1 # Funchal Mean Time
+			-1:00	Port	MAD%sT	1966 Apr  3  2:00 # Madeira Time
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
 			 0:00	EU	WE%sT
 
 # Romania
 #
 # From Paul Eggert (1999-10-07):
-# <a href="http://www.nineoclock.ro/POL/1778pol.html">
-# Nine O'clock</a> (1998-10-23) reports that the switch occurred at
+# Nine O'clock <http://www.nineoclock.ro/POL/1778pol.html>
+# (1998-10-23) reports that the switch occurred at
 # 04:00 local time in fall 1998.  For lack of better info,
 # assume that Romania and Moldova switched to EU rules in 1997,
 # the same year as Bulgaria.
@@ -2094,32 +2117,28 @@
 Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
-			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
-			2:00	Romania	EE%sT	1981 Mar 29 2:00s
+			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
+			2:00	Romania	EE%sT	1981 Mar 29  2:00s
 			2:00	C-Eur	EE%sT	1991
 			2:00	Romania	EE%sT	1994
 			2:00	E-Eur	EE%sT	1997
 			2:00	EU	EE%sT
 
+
 # Russia
 
 # From Alexander Krivenyshev (2011-09-15):
 # Based on last Russian Government Decree # 725 on August 31, 2011
 # (Government document
-# <a href="http://www.government.ru/gov/results/16355/print/">
 # http://www.government.ru/gov/results/16355/print/
-# </a>
 # in Russian)
 # there are few corrections have to be made for some Russian time zones...
 # All updated Russian Time Zones were placed in table and translated to English
 # by WorldTimeZone.com at the link below:
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia36.htm">
 # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
-# </a>
 
 # From Sanjeev Gupta (2011-09-27):
 # Scans of [Decree #23 of January 8, 1992] are available at:
-# <a href="http://government.consultant.ru/page.aspx?1223966">
 # http://government.consultant.ru/page.aspx?1223966
 # They are in Cyrillic letters (presumably Russian).
 
@@ -2128,16 +2147,12 @@
 # changed in September 2011:
 #
 # One source is
-# < a href="http://government.ru/gov/results/16355/>
 # http://government.ru/gov/results/16355/
-# </a>
 # which, according to translate.google.com, begins "Decree of August 31,
 # 2011 No 725" and contains no other dates or "effective date" information.
 #
 # Another source is
-# <a href="http://www.rg.ru/2011/09/06/chas-zona-dok.html">
 # http://www.rg.ru/2011/09/06/chas-zona-dok.html
-# </a>
 # which, according to translate.google.com, begins "Resolution of the
 # Government of the Russian Federation on August 31, 2011 N 725" and also
 # contains "Date first official publication: September 6, 2011 Posted on:
@@ -2145,28 +2160,45 @@
 # does not contain any "effective date" information.
 #
 # Another source is
-# <a href="http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7">
 # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# </a>
 # which, in note 8, contains "Resolution #725 of August 31, 2011...
 # Effective as of after 7 days following the day of the official publication"
 # but which does not contain any reference to September 6, 2011.
 #
 # The Wikipedia article refers to
-# <a href="http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896">
 # http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896
-# </a>
 # which seems to copy the text of the government.ru page.
 #
 # Tobias Conradi combines Wikipedia's
 # "as of after 7 days following the day of the official publication"
-# with www.rg.ru's "Date of first official publication: September 6, 2011" to get
-# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes).
+# with www.rg.ru's "Date of first official publication: September 6, 2011" to
+# get September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias
+# Conradi notes).
 #
 # None of the sources indicates a time of day for changing clocks.
 #
 # Go with 2011-09-13 0:00s.
 
+# From Alexander Krivenyshev (2014-07-01):
+# According to the Russian news (ITAR-TASS News Agency)
+# http://en.itar-tass.com/russia/738562
+# the State Duma has approved ... the draft bill on returning to
+# winter time standard and return Russia 11 time zones.  The new
+# regulations will come into effect on October 26, 2014 at 02:00 ...
+# http://asozd2.duma.gov.ru/main.nsf/%28Spravka%29?OpenAgent&RN=431985-6&02
+# Here is a link where we put together table (based on approved Bill N
+# 431985-6) with proposed 11 Russian time zones and corresponding
+# areas/cities/administrative centers in the Russian Federation (in English):
+# http://www.worldtimezone.com/dst_news/dst_news_russia65.html
+#
+# From Alexander Krivenyshev (2014-07-22):
+# Putin signed the Federal Law 431985-6 ... (in Russian)
+# http://itar-tass.com/obschestvo/1333711
+# http://www.pravo.gov.ru:8080/page.aspx?111660
+# http://www.kremlin.ru/acts/46279
+# From October 26, 2014 the new Russian time zone map will looks like this:
+# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
+
 # From Paul Eggert (2006-03-22):
 # Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
 # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
@@ -2193,9 +2225,9 @@
 #
 # For Grozny, Chechnya, we have the following story from
 # John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
-# News--often false--is spread by word of mouth.  A rumor that it was
+# News - often false - is spread by word of mouth.  A rumor that it was
 # time to move the clocks back put this whole city out of sync with
-# the rest of Russia for two weeks--even soldiers stationed here began
+# the rest of Russia for two weeks - even soldiers stationed here began
 # enforcing curfew at the wrong time.
 #
 # From Gwillim Law (2001-06-05):
@@ -2206,107 +2238,265 @@
 # since September 1997....  Although the Kuril Islands are
 # administratively part of Sakhalin oblast', they appear to have
 # remained on UTC+11 along with Magadan.
-#
+
+# From Tim Parenti (2014-07-06):
+# The comments detailing the coverage of each Russian zone are meant to assist
+# with maintenance only and represent our best guesses as to which regions
+# are covered by each zone.  They are not meant to be taken as an authoritative
+# listing.  The region codes listed come from
+# http://en.wikipedia.org/w/?title=Federal_subjects_of_Russia&oldid=611810498
+# and are used for convenience only; no guarantees are made regarding their
+# future stability.  ISO 3166-2:RU codes are also listed for first-level
+# divisions where available.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-#
-# Kaliningradskaya oblast'.
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Kaliningrad covers...
+# 39	RU-KGD	Kaliningrad Oblast
+
 Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
 			 1:00	C-Eur	CE%sT	1945
 			 2:00	Poland	CE%sT	1946
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			 3:00	-	FET # Further-eastern European Time
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			 3:00	-	FET	2014 Oct 26  2:00s
+			 2:00	-	EET
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Moscow covers...
+# 01	RU-AD	Adygea, Republic of
+# 05	RU-DA	Dagestan, Republic of
+# 06	RU-IN	Ingushetia, Republic of
+# 07	RU-KB	Kabardino-Balkar Republic
+# 08	RU-KL	Kalmykia, Republic of
+# 09	RU-KC	Karachay-Cherkess Republic
+# 10	RU-KR	Karelia, Republic of
+# 11	RU-KO	Komi Republic
+# 12	RU-ME	Mari El Republic
+# 13	RU-MO	Mordovia, Republic of
+# 15	RU-SE	North Ossetia-Alania, Republic of
+# 16	RU-TA	Tatarstan, Republic of
+# 20	RU-CE	Chechen Republic
+# 21	RU-CU	Chuvash Republic
+# 23	RU-KDA	Krasnodar Krai
+# 26	RU-STA	Stavropol Krai
+# 29	RU-ARK	Arkhangelsk Oblast
+# 31	RU-BEL	Belgorod Oblast
+# 32	RU-BRY	Bryansk Oblast
+# 33	RU-VLA	Vladimir Oblast
+# 35	RU-VLG	Vologda Oblast
+# 36	RU-VOR	Voronezh Oblast
+# 37	RU-IVA	Ivanovo Oblast
+# 40	RU-KLU	Kaluga Oblast
+# 44	RU-KOS	Kostroma Oblast
+# 46	RU-KRS	Kursk Oblast
+# 47	RU-LEN	Leningrad Oblast
+# 48	RU-LIP	Lipetsk Oblast
+# 50	RU-MOS	Moscow Oblast
+# 51	RU-MUR	Murmansk Oblast
+# 52	RU-NIZ	Nizhny Novgorod Oblast
+# 53	RU-NGR	Novgorod Oblast
+# 57	RU-ORL	Oryol Oblast
+# 58	RU-PNZ	Penza Oblast
+# 60	RU-PSK	Pskov Oblast
+# 61	RU-ROS	Rostov Oblast
+# 62	RU-RYA	Ryazan Oblast
+# 67	RU-SMO	Smolensk Oblast
+# 68	RU-TAM	Tambov Oblast
+# 69	RU-TVE	Tver Oblast
+# 71	RU-TUL	Tula Oblast
+# 73	RU-ULY	Ulyanovsk Oblast
+# 76	RU-YAR	Yaroslavl Oblast
+# 77	RU-MOW	Moscow
+# 78	RU-SPE	Saint Petersburg
+# 83	RU-NEN	Nenets Autonomous Okrug
+
+# From Vladimir Karpinsky (2014-07-08):
+# LMT in Moscow (before Jul 3, 1916) is 2:30:17, that was defined by Moscow
+# Observatory (coordinates: 55 deg. 45'29.70", 37 deg. 34'05.30")....
+# LMT in Moscow since Jul 3, 1916 is 2:31:01 as a result of new standard.
+# (The info is from the book by Byalokoz ... p. 18.)
+# The time in St. Petersburg as capital of Russia was defined by
+# Pulkov observatory, near St. Petersburg.  In 1916 LMT Moscow
+# was synchronized with LMT St. Petersburg (+30 minutes), (Pulkov observatory
+# coordinates: 59 deg. 46'18.70", 30 deg. 19'40.70") so 30 deg. 19'40.70" >
+# 2h01m18.7s = 2:01:19.  LMT Moscow = LMT St.Petersburg + 30m 2:01:19 + 0:30 =
+# 2:31:19 ...
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Adygeya, Arkhangel'skaya oblast',
-# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
-# Vologodskaya oblast', Voronezhskaya oblast',
-# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
-# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
-# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
-# Respublika Kareliya, Respublika Komi,
-# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
-# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
-# Respublika Mordoviya, Moskva, Moskovskaya oblast',
-# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
-# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
-# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
-# Ryazanskaya oblast', Sankt-Peterburg,
-# Respublika Severnaya Osetiya, Smolenskaya oblast',
-# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
-# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
-# Chechenskaya Respublika, Chuvashskaya oblast',
-# Yaroslavskaya oblast'
-Zone Europe/Moscow	 2:30:20 -	LMT	1880
-			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
-			 2:30:48 Russia	%s	1919 Jul  1 2:00
+# From Paul Eggert (2014-07-08):
+# Milne does not list Moscow, but suggests that its time might be listed in
+# Résumés mensuels et annuels des observations météorologiques (1895).
+# Presumably this is OCLC 85825704, a journal published with parallel text in
+# Russian and French.  This source has not been located; go with Karpinsky.
+
+Zone Europe/Moscow	 2:30:17 -	LMT	1880
+			 2:30:17 -	MMT	1916 Jul  3 # Moscow Mean Time
+			 2:31:19 Russia	%s	1919 Jul  1  2:00
+			 3:00	Russia	%s	1921 Oct
 			 3:00	Russia	MSK/MSD	1922 Oct
 			 2:00	-	EET	1930 Jun 21
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
-			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
-			 4:00	-	MSK
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1992 Jan 19  2:00s
+			 3:00	Russia	MSK/MSD	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Simferopol covers...
+# **	****	Crimea, Republic of
+# **	****	Sevastopol
+
+Zone Europe/Simferopol	 2:16:24 -	LMT	1880
+			 2:16	-	SMT	1924 May  2 # Simferopol Mean T
+			 2:00	-	EET	1930 Jun 21
+			 3:00	-	MSK	1941 Nov
+			 1:00	C-Eur	CE%sT	1944 Apr 13
+			 3:00	Russia	MSK/MSD	1990
+			 3:00	-	MSK	1990 Jul  1  2:00
+			 2:00	-	EET	1992
+# Central Crimea used Moscow time 1994/1997.
 #
-# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
-# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
-# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
-# others?  But we have no data.
+# From Paul Eggert (2006-03-22):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
+# from Kiev to Moscow time sometime after the January 1994 elections.
+# Shanks (1999) says "date of change uncertain", but implies that it happened
+# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
+# 1994-09-25 03:00, but that can't be right.  For now, guess it
+# changed in May.
+			 2:00	E-Eur	EE%sT	1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
+			 3:00	1:00	MSD	1996 Oct 27  3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+			 3:00	Russia	MSK/MSD	1997
+			 3:00	-	MSK	1997 Mar lastSun  1:00u
+# From Alexander Krivenyshev (2014-03-17):
+# time change at 2:00 (2am) on March 30, 2014
+# http://vz.ru/news/2014/3/17/677464.html
+# From Paul Eggert (2014-03-30):
+# Simferopol and Sevastopol reportedly changed their central town clocks
+# late the previous day, but this appears to have been ceremonial
+# and the discrepancies are small enough to not worry about.
+			 2:00	EU	EE%sT	2014 Mar 30  2:00
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Volgograd covers...
+# 30	RU-AST	Astrakhan Oblast
+# 34	RU-VGG	Volgograd Oblast
+# 43	RU-KIR	Kirov Oblast
+# 64	RU-SAR	Saratov Oblast
+
+# From Paul Eggert (2006-05-09):
+# Shanks & Pottenger say Kirov is still at +0400 but Wikipedia says +0300.
+# Perhaps it switched after the others?  But we have no data.
+
 Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
 			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
 			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
 			 4:00	-	STAT	1961 Nov 11
-			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
-			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
-			 4:00	-	VOLT	1992 Mar 29 2:00s
-			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
-			 4:00	-	VOLT
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Samarskaya oblast', Udmyrtskaya respublika
-Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
+			 4:00	Russia	VOL%sT	1989 Mar 26  2:00s # Volgograd T
+			 3:00	Russia	VOL%sT	1991 Mar 31  2:00s
+			 4:00	-	VOLT	1992 Mar 29  2:00s
+			 3:00	Russia	MSK	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Samara covers...
+# 18	RU-UD	Udmurt Republic
+# 63	RU-SAM	Samara Oblast
+
+# Byalokoz 1919 says Samara was 3:20:20.
+
+Zone Europe/Samara	 3:20:20 -	LMT	1919 Jul  1  2:00
 			 3:00	-	SAMT	1930 Jun 21
 			 4:00	-	SAMT	1935 Jan 27
-			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
-			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
-			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
-			 3:00	-	KUYT	1991 Oct 20 3:00
-			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
-			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
+			 4:00	Russia	KUY%sT	1989 Mar 26  2:00s # Kuybyshev
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1991 Sep 29  2:00s
+			 3:00	-	KUYT	1991 Oct 20  3:00
+			 4:00	Russia	SAM%sT	2010 Mar 28  2:00s # Samara Time
+			 3:00	Russia	SAM%sT	2011 Mar 27  2:00s
 			 4:00	-	SAMT
 
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Yekaterinburg covers...
+# 02	RU-BA	Bashkortostan, Republic of
+# 90	RU-PER	Perm Krai
+# 45	RU-KGN	Kurgan Oblast
+# 56	RU-ORE	Orenburg Oblast
+# 66	RU-SVE	Sverdlovsk Oblast
+# 72	RU-TYU	Tyumen Oblast
+# 74	RU-CHE	Chelyabinsk Oblast
+# 86	RU-KHM	Khanty-Mansi Autonomous Okrug - Yugra
+# 89	RU-YAN	Yamalo-Nenets Autonomous Okrug
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
-# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
-# Sverdlovskaya oblast', Tyumenskaya oblast',
-# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
-# Yamalo-Nenetskij avtonomnyj okrug.
-Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
+# Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak
+# Autonomous Okrug merged to form (90, RU-PER) Perm Krai.
+
+# Milne says Yekaterinburg was 4:02:32.9; round to nearest.
+# Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05.
+# Assume it switched on 1916-07-03, the time of the new standard.
+# The 1919 and 1930 transitions are from Shanks.
+
+Zone Asia/Yekaterinburg	 4:02:33 -	LMT	1916 Jul  3
+			 3:45:05 -	PMT	1919 Jul 15  4:00
 			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
-			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
-			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
-			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
-			 6:00	-	YEKT	# Yekaterinburg Time
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
-Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
-			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
-			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
-			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
-			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
-			 7:00	-	OMST
-#
+			 5:00	Russia	SVE%sT	1991 Mar 31  2:00s
+			 4:00	Russia	SVE%sT	1992 Jan 19  2:00s
+			 5:00	Russia	YEK%sT	2011 Mar 27  2:00s
+			 6:00	-	YEKT	2014 Oct 26  2:00s
+			 5:00	-	YEKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Omsk covers...
+# 04	RU-AL	Altai Republic
+# 22	RU-ALT	Altai Krai
+# 55	RU-OMS	Omsk Oblast
+
+# Byalokoz 1919 says Omsk was 4:53:30.
+
+Zone Asia/Omsk		 4:53:30 -	LMT	1919 Nov 14
+			 5:00	-	OMST	1930 Jun 21 # Omsk Time
+			 6:00	Russia	OMS%sT	1991 Mar 31  2:00s
+			 5:00	Russia	OMS%sT	1992 Jan 19  2:00s
+			 6:00	Russia	OMS%sT	2011 Mar 27  2:00s
+			 7:00	-	OMST	2014 Oct 26  2:00s
+			 6:00	-	OMST
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novosibirsk covers...
+# 54	RU-NVS	Novosibirsk Oblast
+# 70	RU-TOM	Tomsk Oblast
+
 # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
 # not clear when it switched from +7 to +6.
-# Novosibirskaya oblast', Tomskaya oblast'.
-Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
+
+Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
 			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
+			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
+			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 6:00	-	NOVT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novokuznetsk covers...
+# 42	RU-KEM	Kemerovo Oblast
 
 # From Alexander Krivenyshev (2009-10-13):
 # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
@@ -2319,14 +2509,10 @@
 # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
 #
 # Russian Government web site (Russian language)
-# <a href="http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archiv">
 # http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
-# </a>
 # or Russian-English translation by WorldTimeZone.com with reference
 # map to local region and new Russia Time Zone map after March 28, 2010
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_russia03.html
-# </a>
 #
 # Thus, when Russia will switch to DST on the night of March 28, 2010
 # Kemerovo region (Kemerovo oblast') will not change the clock.
@@ -2334,152 +2520,319 @@
 # As a result, Kemerovo oblast' will be in the same time zone as
 # Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
 
+# From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
+# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
+# realigning itself with KRAT.
+
 Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 7:00	-	KRAT	# Krasnoyarsk Time
+
 
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Krasnoyarsk covers...
+# 17	RU-TY	Tuva Republic
+# 19	RU-KK	Khakassia, Republic of
+# 24	RU-KYA	Krasnoyarsk Krai
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Krasnoyarskij kraj,
-# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
-# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
-Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
+# Note: Effective 2007-01-01, (88) Evenk Autonomous Okrug and (84) Taymyr
+# Autonomous Okrug were merged into (24, RU-KYA) Krasnoyarsk Krai.
+
+# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
+
+Zone Asia/Krasnoyarsk	 6:11:26 -	LMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
-			 8:00	-	KRAT
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2011 Mar 27  2:00s
+			 8:00	-	KRAT	2014 Oct 26  2:00s
+			 7:00	-	KRAT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Irkutsk covers...
+# 03	RU-BU	Buryatia, Republic of
+# 38	RU-IRK	Irkutsk Oblast
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Buryatiya, Irkutskaya oblast',
-# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
-Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
-			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
+# Note: Effective 2008-01-01, (85) Ust-Orda Buryat Autonomous Okrug was
+# merged into (38, RU-IRK) Irkutsk Oblast.
+
+# Milne 1899 says Irkutsk was 6:57:15.
+# Byalokoz 1919 says Irkutsk was 6:57:05.
+# Go with Byalokoz.
+
+Zone Asia/Irkutsk	 6:57:05 -	LMT	1880
+			 6:57:05 -	IMT	1920 Jan 25 # Irkutsk Mean Time
 			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
-			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
-			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
-			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
-			 9:00	-	IRKT
+			 8:00	Russia	IRK%sT	1991 Mar 31  2:00s
+			 7:00	Russia	IRK%sT	1992 Jan 19  2:00s
+			 8:00	Russia	IRK%sT	2011 Mar 27  2:00s
+			 9:00	-	IRKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Chita covers...
+# 92	RU-ZAB	Zabaykalsky Krai
 #
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
-# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
+# Note: Effective 2008-03-01, (75) Chita Oblast and (80) Agin-Buryat
+# Autonomous Okrug merged to form (92, RU-ZAB) Zabaykalsky Krai.
+
+Zone Asia/Chita	 7:33:52 -	LMT	1919 Dec 15
+			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
 
-# From Oscar van Vlijmen (2009-11-29):
-# ...some regions of [Russia] were merged with others since 2005...
-# Some names were changed, no big deal, except for one instance: a new name.
-# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Yakutsk covers...
+# 28	RU-AMU	Amur Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-02	****	Aldansky District
+# 14-04	****	Amginsky District
+# 14-05	****	Anabarsky District
+# 14-06	****	Bulunsky District
+# 14-07	****	Verkhnevilyuysky District
+# 14-10	****	Vilyuysky District
+# 14-11	****	Gorny District
+# 14-12	****	Zhigansky District
+# 14-13	****	Kobyaysky District
+# 14-14	****	Lensky District
+# 14-15	****	Megino-Kangalassky District
+# 14-16	****	Mirninsky District
+# 14-18	****	Namsky District
+# 14-19	****	Neryungrinsky District
+# 14-21	****	Nyurbinsky District
+# 14-23	****	Olenyoksky District
+# 14-24	****	Olyokminsky District
+# 14-26	****	Suntarsky District
+# 14-27	****	Tattinsky District
+# 14-29	****	Ust-Aldansky District
+# 14-32	****	Khangalassky District
+# 14-33	****	Churapchinsky District
+# 14-34	****	Eveno-Bytantaysky National District
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
-# Verkhnevilyujskij, Vilyujskij, Gornyj,
-# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
-# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
-# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
-# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
+# From Tim Parenti (2014-07-03):
+# Our commentary seems to have lost mention of (14-19) Neryungrinsky District.
+# Since the surrounding districts of Sakha are all YAKT, assume this is, too.
+# Also assume its history has been the same as the rest of Asia/Yakutsk.
 
-Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
+# Byalokoz 1919 says Yakutsk was 8:38:58.
+
+Zone Asia/Yakutsk	 8:38:58 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
-			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
-			 10:00	-	YAKT
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Vladivostok covers...
+# 25	RU-PRI	Primorsky Krai
+# 27	RU-KHA	Khabarovsk Krai
+# 79	RU-YEV	Jewish Autonomous Oblast
 #
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
-# [parts of] Respublika Sakha (Yakutiya).
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-09	****	Verkhoyansky District
+# 14-31	****	Ust-Yansky District
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
-Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
+# Milne 1899 says Vladivostok was 8:47:33.5.
+# Byalokoz 1919 says Vladivostok was 8:47:31.
+# Go with Byalokoz.
+
+Zone Asia/Vladivostok	 8:47:31 -	LMT	1922 Nov 15
 			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
-			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
-			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT
+			10:00	Russia	VLA%sT	1991 Mar 31  2:00s
+			 9:00	Russia	VLA%sT	1992 Jan 19  2:00s
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Khandyga covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-28	****	Tomponsky District
+# 14-30	****	Ust-Maysky District
 
 # From Arthur David Olson (2012-05-09):
 # Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time
 # in 2011.
-#
+
 # From Paul Eggert (2012-11-25):
 # Shanks and Pottenger (2003) has Khandyga on Yakutsk time.
 # Make a wild guess that it switched to Vladivostok time in 2004.
 # This transition is no doubt wrong, but we have no better info.
-#
+
 Zone Asia/Khandyga	 9:02:13 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
 			 9:00	Russia	YAK%sT	2004
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT	2011 Sep 13 0:00s # Decree 725?
-			10:00	-	YAKT
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2011 Sep 13  0:00s # Decree 725?
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
 
-#
-# Sakhalinskaya oblast'.
-# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
+# From Tim Parenti (2014-07-03):
+# Asia/Sakhalin covers...
+# 65	RU-SAK	Sakhalin Oblast
+# ...with the exception of:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
 Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
-			 9:00	-	CJT	1938
+			 9:00	-	JCST	1937 Oct  1
 			 9:00	-	JST	1945 Aug 25
-			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
-			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
-			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
-			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
-			11:00	-	SAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Magadanskaya oblast', Respublika Sakha (Yakutiya).
-# Probably also: Kuril Islands.
+			11:00	Russia	SAK%sT	1991 Mar 31  2:00s # Sakhalin T
+			10:00	Russia	SAK%sT	1992 Jan 19  2:00s
+			11:00	Russia	SAK%sT	1997 Mar lastSun  2:00s
+			10:00	Russia	SAK%sT	2011 Mar 27  2:00s
+			11:00	-	SAKT	2014 Oct 26  2:00s
+			10:00	-	SAKT
+
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, ... Srednekolymskij.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Magadan covers...
+# 49	RU-MAG	Magadan Oblast
+
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# Magadan Oblast is moving from UTC+12 to UTC+10 on 2014-10-26; however,
+# several districts of Sakha Republic as well as Severo-Kurilsky District of
+# the Sakhalin Oblast (also known as the North Kuril Islands), represented
+# until now by Asia/Magadan, will instead move to UTC+11.  These regions will
+# need their own zone.
+
 Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
 			10:00	-	MAGT	1930 Jun 21 # Magadan Time
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			10:00	-	MAGT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Srednekolymsk covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-01	****	Abyysky District
+# 14-03	****	Allaikhovsky District
+# 14-08	****	Verkhnekolymsky District
+# 14-17	****	Momsky District
+# 14-20	****	Nizhnekolymsky District
+# 14-25	****	Srednekolymsky District
+#
+# ...and parts of (65, RU-SAK) Sakhalin Oblast:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# From Tim Parenti (2014-07-02):
+# Oymyakonsky District of Sakha Republic (represented by Ust-Nera), along with
+# most of Sakhalin Oblast (represented by Sakhalin) will be moving to UTC+10 on
+# 2014-10-26 to stay aligned with VLAT/SAKT; however, Severo-Kurilsky District
+# of the Sakhalin Oblast (also known as the North Kuril Islands, represented by
+# Severo-Kurilsk) will remain on UTC+11.
+
+# From Tim Parenti (2014-07-06):
+# Assume North Kuril Islands have history like Magadan before 2011-03-27.
+# There is a decent chance this is wrong, in which case a new zone
+# Asia/Severo-Kurilsk would become necessary.
+#
+# Srednekolymsk and Zyryanka are the most populous places amongst these
+# districts, but have very similar populations.  In fact, Wikipedia currently
+# lists them both as having 3528 people, exactly 1668 males and 1860 females
+# each!  (Yikes!)
+# http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
+# http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
+# Assume this is a mistake, albeit an amusing one.
+#
+# Looking at censuses, the populations of the two municipalities seem to have
+# fluctuated recently.  Zyryanka was more populous than Srednekolymsk in the
+# 1989 and 2002 censuses, but Srednekolymsk was more populous in the most
+# recent (2010) census, 3525 to 3170.  (See pages 195 and 197 of
+# http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf
+# in Russian.)  In addition, Srednekolymsk appears to be a much older
+# settlement and the population of Zyryanka seems to be declining.
+# Go with Srednekolymsk.
+#
+# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
+# as the abbreviation.  Use SRET instead.
+
+Zone Asia/Srednekolymsk	10:14:52 -	LMT	1924 May  2
+			10:00	-	MAGT	1930 Jun 21 # Magadan Time
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			11:00	-	SRET	# Srednekolymsk Time
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-22	****	Oymyakonsky District
 
 # From Arthur David Olson (2012-05-09):
-# Ojmyakonskij and the Kuril Islands switched from
+# Ojmyakonskij [and the Kuril Islands] switched from
 # Magadan time to Vladivostok time in 2011.
+#
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# It's unlikely that any of the Kuril Islands were involved in such a switch,
+# as the South and Middle Kurils have been on UTC+11 (SAKT) with the rest of
+# Sakhalin Oblast since at least 2011-09, and the North Kurils have been on
+# UTC+12 since at least then, too.
+
 Zone Asia/Ust-Nera	 9:32:54 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
 			 9:00	Russia	YAKT	1981 Apr  1
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT	2011 Sep 13 0:00s # Decree 725?
-			11:00	-	VLAT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2011 Sep 13  0:00s # Decree 725?
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
 
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Kamchatka covers...
+# 91	RU-KAM	Kamchatka Krai
 #
-# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
+# Note: Effective 2007-07-01, (41) Kamchatka Oblast and (82) Koryak
+# Autonomous Okrug merged to form (91, RU-KAM) Kamchatka Krai.
+
+# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
+# Asia/Petropavlovsk-Kamchatsky, but these are too long.
 Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
 			11:00	-	PETT	1930 Jun 21 # P-K Time
-			12:00	Russia	PET%sT	1991 Mar 31 2:00s
-			11:00	Russia	PET%sT	1992 Jan 19 2:00s
-			12:00	Russia	PET%sT	2010 Mar 28 2:00s
-			11:00	Russia	PET%sT	2011 Mar 27 2:00s
+			12:00	Russia	PET%sT	1991 Mar 31  2:00s
+			11:00	Russia	PET%sT	1992 Jan 19  2:00s
+			12:00	Russia	PET%sT	2010 Mar 28  2:00s
+			11:00	Russia	PET%sT	2011 Mar 27  2:00s
 			12:00	-	PETT
-#
-# Chukotskij avtonomnyj okrug
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Anadyr covers...
+# 87	RU-CHU	Chukotka Autonomous Okrug
+
 Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
-			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
-			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
-			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
-			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
-			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
+			13:00	Russia	ANA%sT	1982 Apr  1  0:00s
+			12:00	Russia	ANA%sT	1991 Mar 31  2:00s
+			11:00	Russia	ANA%sT	1992 Jan 19  2:00s
+			12:00	Russia	ANA%sT	2010 Mar 28  2:00s
+			11:00	Russia	ANA%sT	2011 Mar 27  2:00s
 			12:00	-	ANAT
 
+
 # San Marino
 # See Europe/Rome.
 
@@ -2488,11 +2841,11 @@
 Zone	Europe/Belgrade	1:22:00	-	LMT	1884
 			1:00	-	CET	1941 Apr 18 23:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 May 8 2:00s
+			1:00	-	CET	1945 May  8  2:00s
 			1:00	1:00	CEST	1945 Sep 16  2:00s
-# Metod Kozelj reports that the legal date of
+# Metod Koželj reports that the legal date of
 # transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
-# Shanks & Pottenger don't give as much detail, so go with Kozelj.
+# Shanks & Pottenger don't give as much detail, so go with Koželj.
 			1:00	-	CET	1982 Nov 27
 			1:00	EU	CE%sT
 Link Europe/Belgrade Europe/Ljubljana	# Slovenia
@@ -2568,13 +2921,13 @@
 			 0:00	1:00	WEST	1918 Oct  7 23:00
 			 0:00	-	WET	1924
 			 0:00	Spain	WE%sT	1929
-			 0:00 SpainAfrica WE%sT 1984 Mar 16
+			 0:00 SpainAfrica WE%sT	1984 Mar 16
 			 1:00	-	CET	1986
 			 1:00	EU	CE%sT
 Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
-			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
-			 0:00	-	WET	1980 Apr  6 0:00s
-			 0:00	1:00	WEST	1980 Sep 28 0:00s
+			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
+			 0:00	-	WET	1980 Apr  6  0:00s
+			 0:00	1:00	WEST	1980 Sep 28  0:00s
 			 0:00	EU	WE%sT
 # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
 # Ignore this for now, as the Canaries are part of the EU.
@@ -2583,7 +2936,7 @@
 
 # From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
 #
-# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
+# The law "Svensk författningssamling 1878, no 14" about standard time in 1879:
 # From the beginning of 1879 (that is 01-01 00:00) the time for all
 # places in the country is "the mean solar time for the meridian at
 # three degrees, or twelve minutes of time, to the west of the
@@ -2594,7 +2947,7 @@
 # national standard time as 01:00:14 ahead of GMT....
 #
 # About the beginning of CET in Sweden. The lawtext ("Svensk
-# forfattningssamling 1899, no 44") states, that "from the beginning
+# författningssamling 1899, no 44") states, that "from the beginning
 # of 1900... ... the same as the mean solar time for the meridian at
 # the distance of one hour of time from the meridian of the English
 # observatory at Greenwich, or at 12 minutes 14 seconds to the west
@@ -2602,7 +2955,7 @@
 # 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
 # in Sweden is 01:00:00 ahead of GMT.
 #
-# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
+# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states
 # that "1916-05-15 is considered to begin one hour earlier". It is
 # pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
 # Further the law says, that "1916-09-30 is considered to end one hour later".
@@ -2612,7 +2965,7 @@
 # not available on the site (to my knowledge they are only available
 # in Swedish): <http://www.riksdagen.se/english/work/sfst.asp> (type
 # "sommartid" without the quotes in the field "Fritext" and then click
-# the Sok-button).
+# the Sök-button).
 #
 # (2001-05-13):
 #
@@ -2627,9 +2980,9 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
-			1:00:14	-	SET	1900 Jan  1	# Swedish Time
+			1:00:14	-	SET	1900 Jan  1 # Swedish Time
 			1:00	-	CET	1916 May 14 23:00
-			1:00	1:00	CEST	1916 Oct  1 01:00
+			1:00	1:00	CEST	1916 Oct  1  1:00
 			1:00	-	CET	1980
 			1:00	EU	CE%sT
 
@@ -2637,7 +2990,7 @@
 # From Howse:
 # By the end of the 18th century clocks and watches became commonplace
 # and their performance improved enormously.  Communities began to keep
-# mean time in preference to apparent time -- Geneva from 1780 ....
+# mean time in preference to apparent time - Geneva from 1780 ....
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 # From Whitman (who writes "Midnight?"):
 # Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
@@ -2653,7 +3006,7 @@
 # to be wrong. This is now verified.
 #
 # I have found copies of the original ruling by the Swiss Federal
-# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
+# government, in 'Eidgenössische Gesetzessammlung 1941 and 1942' (Swiss
 # federal law collection)...
 #
 # DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
@@ -2672,7 +3025,7 @@
 # night as an absolute novelty, because this was the first time that such
 # a thing had happened in Switzerland.
 #
-# I have also checked 1916, because one book source (Gabriel, Traite de
+# I have also checked 1916, because one book source (Gabriel, Traité de
 # l'heure dans le monde) claims that Switzerland had DST in 1916. This is
 # false, no official document could be found. Probably Gabriel got misled
 # by references to Germany, which introduced DST in 1916 for the first time.
@@ -2686,19 +3039,19 @@
 # One further detail for Switzerland, which is probably out of scope for
 # most users of tzdata: The [Europe/Zurich zone] ...
 # describes all of Switzerland correctly, with the exception of
-# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
+# the Canton de Genève (Geneva, Genf). Between 1848 and 1894 Geneva did not
 # follow Bern Mean Time but kept its own local mean time.
 # To represent this, an extra zone would be needed.
 #
 # From Alois Treindl (2013-09-11):
 # The Federal regulations say
 # http://www.admin.ch/opc/de/classified-compilation/20071096/index.html
-# ... the meridian for Bern mean time ... is 7 degrees 26'22.50".
+# ... the meridian for Bern mean time ... is 7 degrees 26' 22.50".
 # Expressed in time, it is 0h29m45.5s.
 
 # From Pierre-Yves Berger (2013-09-11):
-# the "Circulaire du conseil federal" (December 11 1893)
-# <http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353> ...
+# the "Circulaire du conseil fédéral" (December 11 1893)
+# http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353
 # clearly states that the [1894-06-01] change should be done at midnight
 # but if no one is present after 11 at night, could be postponed until one
 # hour before the beginning of service.
@@ -2709,14 +3062,14 @@
 # We can find no reliable source for Shanks's assertion that all of Switzerland
 # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12.  This book:
 #
-#	Jakob Messerli. Gleichmassig, punktlich, schnell: Zeiteinteilung und
+#	Jakob Messerli. Gleichmässig, pünktlich, schnell. Zeiteinteilung und
 #	Zeitgebrauch in der Schweiz im 19. Jahrhundert. Chronos, Zurich 1995,
 #	ISBN 3-905311-68-2, OCLC 717570797.
 #
 # suggests that the transition was more gradual, and that the Swiss did not
 # agree about civil time during the transition.  The timekeeping it gives the
 # most detail for is postal and telegraph time: here, federal legislation (the
-# "Bundesgesetz uber die Erstellung von elektrischen Telegraphen") passed on
+# "Bundesgesetz über die Erstellung von elektrischen Telegraphen") passed on
 # 1851-11-23, and an official implementation notice was published 1853-07-16
 # (Bundesblatt 1853, Bd. II, S. 859).  On p 72 Messerli writes that in
 # practice since July 1853 Bernese time was used in "all postal and telegraph
@@ -2730,7 +3083,7 @@
 Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
-			0:29:46	-	BMT	1894 Jun # Bern Mean Time
+			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
 			1:00	Swiss	CE%sT	1981
 			1:00	EU	CE%sT
 
@@ -2738,7 +3091,7 @@
 
 # From Amar Devegowda (2007-01-03):
 # The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at -
+# ... The latest rules are available at:
 # http://www.timeanddate.com/worldclock/timezone.html?n=107
 # From Steffen Thorsen (2007-01-03):
 # I have been able to find press records back to 1996 which all say that
@@ -2763,8 +3116,7 @@
 # (on a non-government server though) describing dates between 2002 and 2006:
 # http://www.alomaliye.com/bkk_2002_3769.htm
 
-# From G&ouml;kdeniz Karada&#x011f; (2011-03-10):
-#
+# From Gökdeniz Karadağ (2011-03-10):
 # According to the articles linked below, Turkey will change into summer
 # time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
 # This change is due to a nationwide exam on 27th.
@@ -2777,9 +3129,16 @@
 # Turkish Local election....
 # http://www.sabah.com.tr/Ekonomi/2014/02/12/yaz-saatinde-onemli-degisiklik
 # ... so Turkey will move clocks forward one hour on March 31 at 3:00 a.m.
-# From Paul Eggert (2014-02-17):
-# Here is an English-language source:
-# http://www.worldbulletin.net/turkey/129016/turkey-switches-to-daylight-saving-time-march-31
+# From Randal L. Schwartz (2014-04-15):
+# Having landed on a flight from the states to Istanbul (via AMS) on March 31,
+# I can tell you that NOBODY (even the airlines) respected this timezone DST
+# change delay.  Maybe the word just didn't get out in time.
+# From Paul Eggert (2014-06-15):
+# The press reported massive confusion, as election officials obeyed the rule
+# change but cell phones (and airline baggage systems) did not.  See:
+# Kostidis M. Eventful elections in Turkey. Balkan News Agency
+# http://www.balkaneu.com/eventful-elections-turkey/ 2014-03-30.
+# I guess the best we can do is document the official time.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
@@ -2846,10 +3205,10 @@
 			2:00	Turkey	EE%sT	1978 Oct 15
 			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
 			2:00	Turkey	EE%sT	2007
-			2:00	EU	EE%sT	2011 Mar 27 1:00u
-			2:00	-	EET	2011 Mar 28 1:00u
-			2:00	EU	EE%sT	2014 Mar 30 1:00u
-			2:00	-	EET	2014 Mar 31 1:00u
+			2:00	EU	EE%sT	2011 Mar 27  1:00u
+			2:00	-	EET	2011 Mar 28  1:00u
+			2:00	EU	EE%sT	2014 Mar 30  1:00u
+			2:00	-	EET	2014 Mar 31  1:00u
 			2:00	EU	EE%sT
 Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 
@@ -2870,7 +3229,7 @@
 # Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
 # approval from 266 deputies.
 #
-# Ukraine abolishes transter back to the winter time (in Russian)
+# Ukraine abolishes transfer back to the winter time (in Russian)
 # http://news.mail.ru/politics/6861560/
 #
 # The Ukrainians will no longer change the clock (in Russian)
@@ -2931,12 +3290,12 @@
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Sep 20
 			1:00	C-Eur	CE%sT	1943 Nov  6
-			3:00	Russia	MSK/MSD	1990 Jul  1 2:00
-			2:00	1:00	EEST	1991 Sep 29 3:00
+			3:00	Russia	MSK/MSD	1990 Jul  1  2:00
+			2:00	1:00	EEST	1991 Sep 29  3:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
 # Ruthenia used CET 1990/1991.
-# "Uzhhorod" is the transliteration of the Ukrainian name, but
+# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
 # "Uzhgorod" is more common in English.
 Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	-	CET	1940
@@ -2944,8 +3303,8 @@
 			1:00	1:00	CEST	1944 Oct 26
 			1:00	-	CET	1945 Jun 29
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			1:00	-	CET	1991 Mar 31 3:00
+			3:00	-	MSK	1990 Jul  1  2:00
+			1:00	-	CET	1991 Mar 31  3:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
@@ -2959,42 +3318,9 @@
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Aug 25
 			1:00	C-Eur	CE%sT	1943 Oct 25
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
-# Central Crimea used Moscow time 1994/1997.
-Zone Europe/Simferopol	2:16:24 -	LMT	1880
-			2:16	-	SMT	1924 May  2 # Simferopol Mean T
-			2:00	-	EET	1930 Jun 21
-			3:00	-	MSK	1941 Nov
-			1:00	C-Eur	CE%sT	1944 Apr 13
-			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			2:00	-	EET	1992
-# From Paul Eggert (2006-03-22):
-# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
-# from Kiev to Moscow time sometime after the January 1994 elections.
-# Shanks (1999) says "date of change uncertain", but implies that it happened
-# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
-# 1994-09-25 03:00, but that can't be right.  For now, guess it
-# changed in May.
-			2:00	E-Eur	EE%sT	1994 May
-# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
-			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
-			3:00	1:00	MSD	1996 Oct 27 3:00s
-# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
-# Assume it happened in March by not changing the clocks.
-			3:00	Russia	MSK/MSD	1997
-			3:00	-	MSK	1997 Mar lastSun 1:00u
-# From Alexander Krivenyshev (2014-03-17):
-# time change at 2:00 (2am) on March 30, 2014
-# http://vz.ru/news/2014/3/17/677464.html
-# From Paul Eggert (2014-03-30):
-# Simferopol and Sevastopol reportedly changed their central town clocks
-# late the previous day, but this appears to have been ceremonial
-# and the discrepancies are small enough to not worry about.
-			2:00	EU	EE%sT	2014 Mar 30 2:00
-			4:00	-	MSK
 
 # Vatican City
 # See Europe/Rome.
@@ -3018,7 +3344,7 @@
 # ...
 #
 # ...the European time rules are...standardized since 1981, when
-# most European coun[tr]ies started DST.  Before that year, only
+# most European countries started DST.  Before that year, only
 # a few countries (UK, France, Italy) had DST, each according
 # to own national rules.  In 1981, however, DST started on
 # 'Apr firstSun', and not on 'Mar lastSun' as in the following
@@ -3026,7 +3352,7 @@
 # But also since 1981 there are some more national exceptions
 # than listed in 'europe': Switzerland, for example, joined DST
 # one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
-# lastSun' in 1981---I don't know how they handle now.
+# lastSun' in 1981 - I don't know how they handle now.
 #
 # Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
 # Soviet Union (as far as I know).
--- a/jdk/make/data/tzdata/factory	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/factory	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/make/data/tzdata/iso3166.tab	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/iso3166.tab	Wed Jul 05 20:00:59 2017 +0200
@@ -26,21 +26,21 @@
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-05-27):
+# From Paul Eggert (2014-07-18):
+# This file contains a table of two-letter country codes.  Columns are
+# separated by a single tab.  Lines beginning with '#' are comments.
+# Although all text currently uses ASCII encoding, this is planned to
+# change to UTF-8 soon.  The columns of the table are as follows:
 #
-# This file contains a table with the following columns:
 # 1.  ISO 3166-1 alpha-2 country code, current as of
-#     ISO 3166-1 Newsletter VI-15 (2013-05-10).  See: Updates on ISO 3166
+#     ISO 3166-1 Newsletter VI-16 (2013-07-11).  See: Updates on ISO 3166
 #   http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
 #
-# Columns are separated by a single tab.
 # The table is sorted by country code.
 #
-# Lines beginning with `#' are comments.
-#
 # This table is intended as an aid for users, to help them select time
 # zone data appropriate for their practical needs.  It is not intended
 # to take or endorse any position on legal or territorial claims.
--- a/jdk/make/data/tzdata/leapseconds	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/leapseconds	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,7 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# Allowance for leapseconds added to each timezone file.
+# Allowance for leap seconds added to each time zone file.
 
 # This file is in the public domain.
 
@@ -31,7 +31,7 @@
 # you should be able to pick up leap-seconds.list from a secondary NIST server.
 # For more about leap-seconds.list, please see
 # The NTP Timescale and Leap Seconds
-# <http://www.eecis.udel.edu/~mills/leap.html>.
+# http://www.eecis.udel.edu/~mills/leap.html
 
 # The International Earth Rotation Service periodically uses leap seconds
 # to keep UTC to within 0.9 s of UT1
--- a/jdk/make/data/tzdata/northamerica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/northamerica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # also includes Central America and the Caribbean
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (1999-03-22):
 # A reliable and entertaining source about time zones is
@@ -78,13 +78,13 @@
 #	to push people into bed earlier, and get them up earlier, to make
 #	them healthy, wealthy and wise in spite of themselves.
 #
-#	-- Robertson Davies, The diary of Samuel Marchbanks,
+#	 -- Robertson Davies, The diary of Samuel Marchbanks,
 #	   Clarke, Irwin (1947), XIX, Sunday
 #
 # For more about the first ten years of DST in the United States, see
-# Robert Garland's <a href="http://www.clpgh.org/exhibit/dst.html">
-# Ten years of daylight saving from the Pittsburgh standpoint
-# (Carnegie Library of Pittsburgh, 1927)</a>.
+# Robert Garland, Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927).
+# http://www.clpgh.org/exhibit/dst.html
 #
 # Shanks says that DST was called "War Time" in the US in 1918 and 1919.
 # However, DST was imposed by the Standard Time Act of 1918, which
@@ -103,11 +103,11 @@
 # From Arthur David Olson (2000-09-25):
 # Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
 # In the introduction, Oboler spoke of "Eastern Peace Time."
-# An AltaVista search turned up
-# <a href="http://rowayton.org/rhs/hstaug45.html">:
+# An AltaVista search turned up:
+# http://rowayton.org/rhs/hstaug45.html
 # "When the time is announced over the radio now, it is 'Eastern Peace
 # Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
-# </a> (August 1945) by way of confirmation.
+# (August 1945) by way of confirmation.
 
 # From Joseph Gallant citing
 # George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
@@ -205,7 +205,7 @@
 # USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
 # USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
 # USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
-# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
+# USA    "           9 H  BEHIND UTC    APR 3 - OCT 30
 # USA  HAWAII       10 H  BEHIND UTC
 # USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
 
@@ -258,19 +258,19 @@
 # The following was signed into law on 2005-08-08.
 #
 # H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
-#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
+#   (a) Amendment.--Section 3(a) of the Uniform Time Act of 1966 (15
 #   U.S.C. 260a(a)) is amended--
-#     (1) by striking 'first Sunday of April' and inserting 'second
-#     Sunday of March'; and
-#     (2) by striking 'last Sunday of October' and inserting 'first
+#     (1) by striking "first Sunday of April" and inserting "second
+#     Sunday of March"; and
+#     (2) by striking "last Sunday of October" and inserting "first
 #     Sunday of November'.
-#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
+#   (b) Effective Date.--Subsection (a) shall take effect 1 year after the
 #   date of enactment of this Act or March 1, 2007, whichever is later.
-#   (c) Report to Congress- Not later than 9 months after the effective
+#   (c) Report to Congress.--Not later than 9 months after the effective
 #   date stated in subsection (b), the Secretary shall report to Congress
 #   on the impact of this section on energy consumption in the United
 #   States.
-#   (d) Right to Revert- Congress retains the right to revert the
+#   (d) Right to Revert.--Congress retains the right to revert the
 #   Daylight Saving Time back to the 2005 time schedules once the
 #   Department study is complete.
 
@@ -292,7 +292,7 @@
 
 # From Paul Eggert (2005-08-26):
 # According to today's Huntsville Times
-# <http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1>
+# http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1
 # a few towns on Alabama's "eastern border with Georgia, such as Phenix City
 # in Russell County, Lanett in Chambers County and some towns in Lee County,
 # set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
@@ -347,15 +347,15 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
 			-6:00	US	C%sT	1920
-			-6:00	Chicago	C%sT	1936 Mar  1 2:00
-			-5:00	-	EST	1936 Nov 15 2:00
+			-6:00	Chicago	C%sT	1936 Mar  1  2:00
+			-5:00	-	EST	1936 Nov 15  2:00
 			-6:00	Chicago	C%sT	1942
 			-6:00	US	C%sT	1946
 			-6:00	Chicago	C%sT	1967
 			-6:00	US	C%sT
 # Oliver County, ND switched from mountain to central time on 1992-10-25.
 Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
-			-7:00	US	M%sT	1992 Oct 25 02:00
+			-7:00	US	M%sT	1992 Oct 25  2:00
 			-6:00	US	C%sT
 # Morton County, ND, switched from mountain to central time on
 # 2003-10-26, except for the area around Mandan which was already central time.
@@ -364,29 +364,26 @@
 # Jones, Mellette, and Todd Counties in South Dakota;
 # but in practice these other counties were already observing central time.
 # See <http://www.epa.gov/fedrgstr/EPA-IMPACT/2003/October/Day-28/i27056.htm>.
-Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
-			-7:00	US	M%sT	2003 Oct 26 02:00
+Zone America/North_Dakota/New_Salem -6:45:39 - LMT	1883 Nov 18 12:14:21
+			-7:00	US	M%sT	2003 Oct 26  2:00
 			-6:00	US	C%sT
 
 # From Josh Findley (2011-01-21):
 # ...it appears that Mercer County, North Dakota, changed from the
 # mountain time zone to the central time zone at the last transition from
 # daylight-saving to standard time (on Nov. 7, 2010):
-# <a href="http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm">
 # http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
-# </a>
-# <a href="http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html">
 # http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
-# </a>
 
 # From Andy Lipscomb (2011-01-24):
 # ...according to the Census Bureau, the largest city is Beulah (although
 # it's commonly referred to as Beulah-Hazen, with Hazen being the next
 # largest city in Mercer County).  Google Maps places Beulah's city hall
-# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
+# at 47 degrees 15' 51" N, 101 degrees 46' 40" W, which yields an offset
+# of 6h47'07".
 
-Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
-			-7:00	US	M%sT	2010 Nov  7 2:00
+Zone America/North_Dakota/Beulah -6:47:07 - LMT	1883 Nov 18 12:12:53
+			-7:00	US	M%sT	2010 Nov  7  2:00
 			-6:00	US	C%sT
 
 # US mountain time, represented by Denver
@@ -448,15 +445,18 @@
 # was destroyed in 1805 by a Yakutat-kon war party.)  However, there
 # were nearby inhabitants in some cases and for our purposes perhaps
 # it's best to simply use the official transition.
+
+# From Paul Eggert (2014-07-18):
+# One opinion of the early-1980s turmoil in Alaska over time zones and
+# daylight saving time appeared as graffiti on a Juneau airport wall:
+# "Welcome to Juneau.  Please turn your watch back to the 19th century."
+# See: Turner W. Alaska's four time zones now two. NY Times 1983-11-01.
+# http://www.nytimes.com/1983/11/01/us/alaska-s-four-time-zones-now-two.html
 #
-
-# From Steve Ferguson (2011-01-31):
-# The author lives in Alaska and many of the references listed are only
-# available to Alaskan residents.
-#
-# <a href="http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98">
-# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
-# </a>
+# Steve Ferguson (2011-01-31) referred to the following source:
+# Norris F. Keeping time in Alaska: national directives, local response.
+# Alaska History 2001;16(1-2).
+# http://alaskahistoricalsociety.org/discover-alaska/glimpses-of-the-past/keeping-time-in-alaska/
 
 # From Arthur David Olson (2011-02-01):
 # Here's database-relevant material from the 2001 "Alaska History" article:
@@ -482,12 +482,10 @@
 # From Arthur David Olson (2011-02-09):
 # I just spoke by phone with a staff member at the Metlakatla Indian
 # Community office (using contact information available at
-# <a href="http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla">
 # http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
-# </a>).
 # It's shortly after 1:00 here on the east coast of the United States;
 # the staffer said it was shortly after 10:00 there. When I asked whether
-# that meant they were on Pacific time, they said no--they were on their
+# that meant they were on Pacific time, they said no - they were on their
 # own time. I asked about daylight saving; they said it wasn't used. I
 # did not inquire about practices in the past.
 
@@ -501,9 +499,9 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1980 Apr 27 2:00
-			 -9:00	US	Y%sT	1980 Oct 26 2:00
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1980 Apr 27  2:00
+			 -9:00	US	Y%sT	1980 Oct 26  2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
@@ -511,7 +509,7 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
@@ -519,8 +517,8 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
-			 -8:00	-	MeST
+			 -8:00	US	P%sT	1983 Oct 30  2:00
+			 -8:00	-	PST
 Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
 			 -9:18:55 -	LMT	1900 Aug 20 12:00
 			 -9:00	-	YST	1942
@@ -535,7 +533,7 @@
 			-10:00	US	CAT/CAPT 1946 # Peace
 			-10:00	-	CAT	1967 Apr
 			-10:00	-	AHST	1969
-			-10:00	US	AH%sT	1983 Oct 30 2:00
+			-10:00	US	AH%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
@@ -544,7 +542,7 @@
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
@@ -553,7 +551,7 @@
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			-10:00	US	AH%sT	1983 Nov 30
 			-10:00	US	HA%sT
 # The following switches don't quite make our 1970 cutoff.
@@ -571,7 +569,7 @@
 #  Minutes of the Unalaska City Council Meeting, January 10, 1967:
 #  "Except for St. Paul and Akutan, Unalaska is the only important
 #  location not on Alaska Standard Time.  The following resolution was
-#  made by William Robinson and seconded by Henry Swanson:  Be it
+#  made by William Robinson and seconded by Henry Swanson: Be it
 #  resolved that the City of Unalaska hereby goes to Alaska Standard
 #  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
 #  January 14, Alaska Standard Time.)  This resolution was passed with
@@ -583,9 +581,7 @@
 # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
 # of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
 # the article is available at
-# <a href="http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf">
 # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
-# </a>
 # and indicates that standard time was adopted effective noon, January
 # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
 # saving for the period between the last Sunday of each April and the
@@ -606,7 +602,7 @@
 # year, the standard time of this Territory shall be advanced one
 # hour...This Act shall take effect upon its approval. Approved this 26th
 # day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
-# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
+# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is
 # hereby repealed...This Act shall take effect upon its approval, upon
 # which date the standard time of this Territory shall be restored to
 # that existing immediately prior to the taking effect of said Act 90.
@@ -616,14 +612,14 @@
 # Note that 1933-05-21 was a Sunday.
 # We're left to guess the time of day when Act 163 was approved; guess noon.
 
-Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
-			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
-			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
-			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
-			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
-			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
+			-10:30	-	HST	1933 Apr 30  2:00
+			-10:30	1:00	HDT	1933 May 21 12:00
+			-10:30	-	HST	1942 Feb  9  2:00
+			-10:30	1:00	HDT	1945 Sep 30  2:00
+			-10:30	-	HST	1947 Jun  8  2:00
 			-10:00	-	HST
-
 Link Pacific/Honolulu Pacific/Johnston
 
 # Now we turn to US areas that have diverged from the consensus since 1970.
@@ -633,9 +629,9 @@
 # From Paul Eggert (2002-10-20):
 #
 # The information in the rest of this paragraph is derived from the
-# <a href="http://www.dlapr.lib.az.us/links/daylight.htm">
-# Daylight Saving Time web page (2002-01-23)</a> maintained by the
-# Arizona State Library, Archives and Public Records.
+# Daylight Saving Time web page
+# <http://www.dlapr.lib.az.us/links/daylight.htm> (2002-01-23)
+# maintained by the Arizona State Library, Archives and Public Records.
 # Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
 # time, but by federal law railroads, airlines, bus lines, military
 # personnel, and some engaged in interstate commerce continued to
@@ -649,10 +645,11 @@
 # Shanks says the 1944 experiment came to an end on 1944-03-17.
 # Go with the Arizona State Library instead.
 
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
-			-7:00	US	M%sT	1944 Jan  1 00:01
-			-7:00	-	MST	1944 Apr  1 00:01
-			-7:00	US	M%sT	1944 Oct  1 00:01
+			-7:00	US	M%sT	1944 Jan  1  0:01
+			-7:00	-	MST	1944 Apr  1  0:01
+			-7:00	US	M%sT	1944 Oct  1  0:01
 			-7:00	-	MST	1967
 			-7:00	US	M%sT	1968 Mar 21
 			-7:00	-	MST
@@ -676,24 +673,22 @@
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
-			-8:00	US	P%sT	1923 May 13 2:00
+			-8:00	US	P%sT	1923 May 13  2:00
 			-7:00	US	M%sT	1974
-			-7:00	-	MST	1974 Feb  3 2:00
+			-7:00	-	MST	1974 Feb  3  2:00
 			-7:00	US	M%sT
 
 # Indiana
 #
 # For a map of Indiana's time zone regions, see:
-# <a href="http://www.mccsc.edu/time.html">
-# What time is it in Indiana?
-# </a> (2006-03-01)
+# http://en.wikipedia.org/wiki/Time_in_Indiana
 #
 # From Paul Eggert (2007-08-17):
 # Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
 # with the following exceptions:
 #
 # - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
-#   Vandenburgh, and Warrick counties have been like America/Chicago.
+#   Vanderburgh, and Warrick counties have been like America/Chicago.
 #
 # - Dearborn and Ohio counties have been like America/New_York.
 #
@@ -712,22 +707,16 @@
 # that they would be ambiguous if we left them at the 'America' level.
 # So we reluctantly put them all in a subdirectory 'America/Indiana'.
 
-# From Paul Eggert (2005-08-16):
-# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
-
-# From Nathan Stratton Treadway (2006-03-30):
-# http://www.dot.gov/affairs/dot0406.htm [3705 B]
-# From Deborah Goldsmith (2006-01-18):
-# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
-# From Paul Eggert (2006-01-20):
-# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
+# From Paul Eggert (2014-06-26):
+# https://www.federalregister.gov/articles/2006/01/20/06-563/standard-time-zone-boundary-in-the-state-of-indiana
+# says "DOT is relocating the time zone boundary in Indiana to move Starke,
 # Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
 # Eastern Time Zone to the Central Time Zone.... The effective date of
-# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
+# this rule is 2 a.m. EST Sunday, April 2, 2006, which is the
 # changeover date from standard time to Daylight Saving Time."
-# Strictly speaking, this means the affected counties will change their
-# clocks twice that night, but this obviously is in error.  The intent
-# is that 01:59:59 EST be followed by 02:00:00 CDT.
+# Strictly speaking, this meant the affected counties changed their
+# clocks twice that night, but this obviously was in error.  The intent
+# was that 01:59:59 EST be followed by 02:00:00 CDT.
 
 # From Gwillim Law (2007-02-10):
 # The Associated Press has been reporting that Pulaski County, Indiana is
@@ -739,13 +728,13 @@
 Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
 Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
+Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
 			-6:00	US	C%sT	1920
 			-6:00 Indianapolis C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
-			-5:00	-	EST	1957 Sep 29 2:00
-			-6:00	-	CST	1958 Apr 27 2:00
+			-6:00 Indianapolis C%sT	1955 Apr 24  2:00
+			-5:00	-	EST	1957 Sep 29  2:00
+			-6:00	-	CST	1958 Apr 27  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
 			-5:00	-	EST	2006
@@ -761,10 +750,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
 			-6:00	US	C%sT	1951
-			-6:00	Marengo	C%sT	1961 Apr 30 2:00
+			-6:00	Marengo	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT	1976
 			-5:00	-	EST	2006
 			-5:00	US	E%sT
@@ -785,11 +774,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
 			-6:00	US	C%sT	1946
-			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
+			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Perry County, Indiana, switched from eastern to central time in April 2006.
@@ -806,10 +795,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
 			-6:00	US	C%sT	1946
-			-6:00 Perry	C%sT	1964 Apr 26 2:00
+			-6:00 Perry	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pike County, Indiana moved from central to eastern time in 1977,
@@ -822,11 +811,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
 			-6:00	US	C%sT	1955
-			-6:00	Pike	C%sT	1965 Apr 25 2:00
-			-5:00	-	EST	1966 Oct 30 2:00
-			-6:00	US	C%sT	1977 Oct 30 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-6:00	Pike	C%sT	1965 Apr 25  2:00
+			-5:00	-	EST	1966 Oct 30  2:00
+			-6:00	US	C%sT	1977 Oct 30  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Starke County, Indiana moved from central to eastern time in 1991,
@@ -844,10 +833,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
 			-6:00	US	C%sT	1947
-			-6:00	Starke	C%sT	1962 Apr 29 2:00
-			-5:00	-	EST	1963 Oct 27 2:00
-			-6:00	US	C%sT	1991 Oct 27 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
+			-6:00	Starke	C%sT	1962 Apr 29  2:00
+			-5:00	-	EST	1963 Oct 27  2:00
+			-6:00	US	C%sT	1991 Oct 27  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pulaski County, Indiana, switched from eastern to central time in
@@ -860,17 +849,17 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
 			-6:00	US	C%sT	1946
-			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
+			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Mar 11 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Mar 11  2:00
 			-5:00	US	E%sT
 #
 # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
-			-6:00	US	C%sT	1954 Apr 25 2:00
+			-6:00	US	C%sT	1954 Apr 25  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1973
 			-5:00	-	EST	2006
@@ -891,18 +880,17 @@
 			-6:00	US	C%sT	1921
 			-6:00 Louisville C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Louisville C%sT	1961 Jul 23 2:00
+			-6:00 Louisville C%sT	1961 Jul 23  2:00
 			-5:00	-	EST	1968
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT
 #
 # Wayne County, Kentucky
 #
-# From
-# <a href="http://www.lake-cumberland.com/life/archive/news990129time.shtml">
-# Lake Cumberland LIFE
-# </a> (1999-01-29) via WKYM-101.7:
+# From Lake Cumberland LIFE
+# http://www.lake-cumberland.com/life/archive/news990129time.shtml
+# (1999-01-29) via WKYM-101.7:
 # Clinton County has joined Wayne County in asking the DoT to change from
 # the Central to the Eastern time zone....  The Wayne County government made
 # the same request in December.  And while Russell County officials have not
@@ -919,9 +907,8 @@
 #
 # From Paul Eggert (2001-07-16):
 # The final rule was published in the
-# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22">
-# Federal Register 65, 160 (2000-08-17), page 50154-50158.
-# </a>
+# Federal Register 65, 160 (2000-08-17), pp 50154-50158.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22
 #
 Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 			-6:00	US	C%sT	1946
@@ -946,9 +933,8 @@
 # See America/North_Dakota/Center for the Oliver County, ND change.
 # West Wendover, NV officially switched from Pacific to mountain time on
 # 1999-10-31.  See the
-# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15">
-# Federal Register 64, 203 (1999-10-21), page 56705-56707.
-# </a>
+# Federal Register 64, 203 (1999-10-21), pp 56705-56707.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15
 # However, the Federal Register says that West Wendover already operated
 # on mountain time, and the rule merely made this official;
 # hence a separate tz entry is not needed.
@@ -986,12 +972,12 @@
 Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Detroit	-5:32:11 -	LMT	1905
-			-6:00	-	CST	1915 May 15 2:00
+			-6:00	-	CST	1915 May 15  2:00
 			-5:00	-	EST	1942
 			-5:00	US	E%sT	1946
 			-5:00	Detroit	E%sT	1973
 			-5:00	US	E%sT	1975
-			-5:00	-	EST	1975 Apr 27 2:00
+			-5:00	-	EST	1975 Apr 27  2:00
 			-5:00	US	E%sT
 #
 # Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
@@ -1004,8 +990,8 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 			-6:00	US	C%sT	1946
-			-6:00 Menominee	C%sT	1969 Apr 27 2:00
-			-5:00	-	EST	1973 Apr 29 2:00
+			-6:00 Menominee	C%sT	1969 Apr 27  2:00
+			-5:00	-	EST	1973 Apr 29  2:00
 			-6:00	US	C%sT
 
 # Navassa
@@ -1042,9 +1028,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	<a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
 #	William Willett, The Waste of Daylight, 19th edition
-#	</a> (1914-03)
+#	<http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	<http://www.jstor.org/stable/1774359>.
@@ -1053,11 +1039,11 @@
 
 # Canada
 
-# From Alain LaBont<e'> (1994-11-14):
+# From Alain LaBonté (1994-11-14):
 # I post here the time zone abbreviations standardized in Canada
 # for both English and French in the CAN/CSA-Z234.4-89 standard....
 #
-#	UTC	Standard time	Daylight savings time
+#	UTC	Standard time	Daylight saving time
 #	offset	French	English	French	English
 #	-2:30	-	-	HAT	NDT
 #	-3	-	-	HAA	ADT
@@ -1070,7 +1056,7 @@
 #	-9	HNY	YST	-	-
 #
 #	HN: Heure Normale	ST: Standard Time
-#	HA: Heure Avanc<e'>e	DT: Daylight saving Time
+#	HA: Heure Avancée	DT: Daylight saving Time
 #
 #	A: de l'Atlantique	Atlantic
 #	C: du Centre		Central
@@ -1085,7 +1071,7 @@
 # From Paul Eggert (1994-11-22):
 # Alas, this sort of thing must be handled by localization software.
 
-# Unless otherwise specified, the data for Canada are all from Shanks
+# Unless otherwise specified, the data entries for Canada are all from Shanks
 # & Pottenger.
 
 # From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
@@ -1134,15 +1120,15 @@
 
 # From Paul Eggert (2006-04-25):
 # H. David Matthews and Mary Vincent's map
-# <a href="http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp">
 # "It's about TIME", _Canadian Geographic_ (September-October 1998)
-# </a> contains detailed boundaries for regions observing nonstandard
+# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# contains detailed boundaries for regions observing nonstandard
 # time and daylight saving time arrangements in Canada circa 1998.
 #
-# INMS, the Institute for National Measurement Standards in Ottawa, has <a
-# href="http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php">
+# INMS, the Institute for National Measurement Standards in Ottawa, has
 # information about standard and daylight saving time zones in Canada.
-# </a> (updated periodically).
+# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
+# (updated periodically).
 # Its unofficial information is often taken from Matthews and Vincent.
 
 # From Paul Eggert (2006-06-27):
@@ -1151,9 +1137,7 @@
 
 # From Chris Walton (2011-12-01)
 # In the first of Tammy Hardwick's articles
-# <a href="http://www.ilovecreston.com/?p=articles&t=spec&ar=260">
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# </a>
 # she quotes the Friday November 1/1918 edition of the Creston Review.
 # The quote includes these two statements:
 # 'Sunday the CPR went back to the old system of time...'
@@ -1221,9 +1205,7 @@
 # Time to Standard Time and from Standard Time to Daylight Savings Time
 # now occurs at 2:00AM.
 # ...
-# <a href="http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm">
 # http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
-# </a>
 # ...
 # MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
 # Office of the Chief Information Officer
@@ -1259,7 +1241,7 @@
 			-3:30	-	NST	1936
 			-3:30	StJohns	N%sT	1942 May 11
 			-3:30	Canada	N%sT	1946
-			-3:30	StJohns	N%sT	1966 Mar 15 2:00
+			-3:30	StJohns	N%sT	1966 Mar 15  2:00
 			-4:00	StJohns	A%sT	2011 Nov
 			-4:00	Canada	A%sT
 
@@ -1320,7 +1302,7 @@
 Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
 			-4:00	Halifax	A%sT	1918
 			-4:00	Canada	A%sT	1919
-			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
+			-4:00	Halifax	A%sT	1942 Feb  9  2:00s
 			-4:00	Canada	A%sT	1946
 			-4:00	Halifax	A%sT	1974
 			-4:00	Canada	A%sT
@@ -1379,7 +1361,7 @@
 # meridian is supposed to observe AST, but residents as far east as
 # Natashquan use EST/EDT, and residents east of Natashquan use AST.
 # The Quebec department of justice writes in
-# "The situation in Minganie and Basse-Cote-Nord"
+# "The situation in Minganie and Basse-Côte-Nord"
 # http://www.justice.gouv.qc.ca/english/publications/generale/temps-minganie-a.htm
 # that the coastal strip from just east of Natashquan to Blanc-Sablon
 # observes Atlantic standard time all year round.
@@ -1387,7 +1369,6 @@
 # says this common practice was codified into law as of 2007.
 # For lack of better info, guess this practice began around 1970, contra to
 # Shanks & Pottenger who have this region observing AST/ADT.
-# for post-1970 data America/Puerto_Rico.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
@@ -1401,18 +1382,10 @@
 Rule	Mont	1924	only	-	May	17	2:00	1:00	D
 Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
 Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
-# The 1927-to-1937 rules can be expressed more simply as
-# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
-# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
-# The rules below avoid use of 24:00
-# (which pre-1998 versions of zic cannot handle).
-Rule	Mont	1927	only	-	May	1	0:00	1:00	D
-Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
-Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1932	only	-	May	1	0:00	1:00	D
-Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1933	only	-	Oct	1	0:00	0	S
-Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
+Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
+Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
+Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
+Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
 Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
 Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
@@ -1426,7 +1399,7 @@
 Zone America/Montreal	-4:54:16 -	LMT	1884
 			-5:00	Mont	E%sT	1918
 			-5:00	Canada	E%sT	1919
-			-5:00	Mont	E%sT	1942 Feb  9 2:00s
+			-5:00	Mont	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Mont	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1448,7 +1421,7 @@
 # have already done so.  In Orillia DST was to run until Saturday,
 # 1912-08-31 (no time mentioned), but it was met with considerable
 # hostility from certain segments of the public, and was revoked after
-# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
+# only two weeks - I copied it as Saturday, 1912-07-07, 22:00, but
 # presumably that should be -07-06.  (1912-06-19, -07-12; also letters
 # earlier in June).
 #
@@ -1458,10 +1431,8 @@
 # Mark Brader writes that an article in the 1997-10-14 Toronto Star
 # says that Atikokan, Ontario currently does not observe DST,
 # but will vote on 11-10 whether to use EST/EDT.
-# He also writes that the
-# <a href="http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html">
-# Ontario Time Act (1990, Chapter T.9)
-# </a>
+# He also writes that the Ontario Time Act (1990, Chapter T.9)
+# http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html
 # says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
 # Officially Atikokan is therefore on CST/CDT, and most likely this report
 # concerns a non-official time observed as a matter of local practice.
@@ -1540,9 +1511,7 @@
 # The Journal of The Royal Astronomical Society of Canada,
 # volume 26, number 2 (February 1932) and, as of 2010-07-17,
 # was available at
-# <a href="http://adsabs.harvard.edu/full/1932JRASC..26...49S">
 # http://adsabs.harvard.edu/full/1932JRASC..26...49S
-# </a>
 #
 # It includes the text below (starting on page 57):
 #
@@ -1553,26 +1522,26 @@
 # ing in 1930. The information for the province of Quebec is definite,
 # for the other provinces only approximate:
 #
-# 	Province	Daylight saving time used
+#	Province	Daylight saving time used
 # Prince Edward Island	Not used.
 # Nova Scotia		In Halifax only.
 # New Brunswick		In St. John only.
 # Quebec		In the following places:
-# 			Montreal	Lachine
-# 			Quebec		Mont-Royal
-# 			Levis		Iberville
-# 			St. Lambert	Cap de la Madeleine
-# 			Verdun		Loretteville
-# 			Westmount	Richmond
-# 			Outremont	St. Jerome
-# 			Longueuil	Greenfield Park
-# 			Arvida		Waterloo
-# 			Chambly-Canton	Beaulieu
-# 			Melbourne	La Tuque
-# 			St. Theophile	Buckingham
+#			Montreal	Lachine
+#			Quebec		Mont-Royal
+#			Lévis		Iberville
+#			St. Lambert	Cap de la Madelèine
+#			Verdun		Loretteville
+#			Westmount	Richmond
+#			Outremont	St. Jérôme
+#			Longueuil	Greenfield Park
+#			Arvida		Waterloo
+#			Chambly-Canton	Beaulieu
+#			Melbourne	La Tuque
+#			St. Théophile	Buckingham
 # Ontario		Used generally in the cities and towns along
-# 			the southerly part of the province. Not
-# 			used in the northwesterlhy part.
+#			the southerly part of the province. Not
+#			used in the northwesterly part.
 # Manitoba		Not used.
 # Saskatchewan		In Regina only.
 # Alberta		Not used.
@@ -1641,7 +1610,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Toronto	-5:17:32 -	LMT	1895
 			-5:00	Canada	E%sT	1919
-			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
+			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Toronto	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1654,16 +1623,16 @@
 			-5:00	Canada	E%sT
 Zone America/Nipigon	-5:53:04 -	LMT	1895
 			-5:00	Canada	E%sT	1940 Sep 29
-			-5:00	1:00	EDT	1942 Feb  9 2:00s
+			-5:00	1:00	EDT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT
 Zone America/Rainy_River -6:18:16 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
 			-6:00	Canada	C%sT
 Zone America/Atikokan	-6:06:28 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
-			-6:00	Canada	C%sT	1945 Sep 30 2:00
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
+			-6:00	Canada	C%sT	1945 Sep 30  2:00
 			-5:00	-	EST
 
 
@@ -1676,7 +1645,7 @@
 # the first Sunday of April of each year and two o'clock Central
 # Standard Time in the morning of the last Sunday of October next
 # following, one hour in advance of Central Standard Time."...
-# I believe that the English legislation [of the old time act] had =
+# I believe that the English legislation [of the old time act] had
 # been assented to (March 22, 1967)....
 # Also, as far as I can tell, there was no order-in-council varying
 # the time of Daylight Saving Time for 2005 and so the provisions of
@@ -1799,12 +1768,12 @@
 Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Regina	-6:58:36 -	LMT	1905 Sep
-			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
+			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
 			-6:00	-	CST
 Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
-			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
+			-7:00	Canada	M%sT	1946 Apr lastSun  2:00
 			-7:00	Regina	M%sT	1950
-			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
+			-7:00	Swift	M%sT	1972 Apr lastSun  2:00
 			-6:00	-	CST
 
 
@@ -1854,9 +1823,7 @@
 # Earlier this year I stumbled across a detailed article about the time
 # keeping history of Creston; it was written by Tammy Hardwick who is the
 # manager of the Creston & District Museum. The article was written in May 2009.
-# <a href="http://www.ilovecreston.com/?p=articles&t=spec&ar=260">
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# </a>
 # According to the article, Creston has not changed its clocks since June 1918.
 # i.e. Creston has been stuck on UTC-7 for 93 years.
 # Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
@@ -1864,18 +1831,16 @@
 # Unfortunately the exact date for the time change in June 1918 remains
 # unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
 # ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
-# as plausible as any other date (in June).  She also said that after writing the
-# article she had discovered another time change in 1916; this is the subject
-# of another article which she wrote in October 2010.
-# <a href="http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56">
+# as plausible as any other date (in June).  She also said that after writing
+# the article she had discovered another time change in 1916; this is the
+# subject of another article which she wrote in October 2010.
 # http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
-# </a>
 
 # Here is a summary of the three clock change events in Creston's history:
 # 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
 # Exact date unknown
 # 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
-# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
+# Exact date in October unknown; Sunday October 1 is a reasonable guess.
 # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
 # Exact date in June unknown; Sunday June 2 is a reasonable guess.
 # note#1:
@@ -1888,9 +1853,7 @@
 # There is no guarantee that Creston will remain on Mountain Standard Time
 # (UTC-7) forever.
 # The subject was debated at least once this year by the town Council.
-# <a href="http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html">
 # http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
-# </a>
 
 # During a period WWII, summer time (Daylight saying) was mandatory in Canada.
 # In Creston, that was handled by shifting the area to PST (-8:00) then applying
@@ -1917,7 +1880,7 @@
 			-8:00	Canada	P%sT
 Zone America/Dawson_Creek -8:00:56 -	LMT	1884
 			-8:00	Canada	P%sT	1947
-			-8:00	Vanc	P%sT	1972 Aug 30 2:00
+			-8:00	Vanc	P%sT	1972 Aug 30  2:00
 			-7:00	-	MST
 Zone America/Creston	-7:46:04 -	LMT	1884
 			-7:00	-	MST	1916 Oct 1
@@ -1944,18 +1907,17 @@
 
 # From Rives McDow (1999-09-04):
 # Nunavut ... moved ... to incorporate the whole territory into one time zone.
-# <a href="http://www.nunatsiaq.com/nunavut/nvt90903_13.html">
 # Nunavut moves to single time zone Oct. 31
-# </a>
+# http://www.nunatsiaq.com/nunavut/nvt90903_13.html
 #
 # From Antoine Leca (1999-09-06):
 # We then need to create a new timezone for the Kitikmeot region of Nunavut
 # to differentiate it from the Yellowknife region.
 
 # From Paul Eggert (1999-09-20):
-# <a href="http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html">
 # Basic Facts: The New Territory
-# </a> (1999) reports that Pangnirtung operates on eastern time,
+# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
+# (1999) reports that Pangnirtung operates on eastern time,
 # and that Coral Harbour does not observe DST.  We don't know when
 # Pangnirtung switched to eastern time; we'll guess 1995.
 
@@ -1983,8 +1945,8 @@
 # the current state of affairs.
 
 # From Michaela Rodrigue, writing in the
-# <a href="http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html">
-# Nunatsiaq News (1999-11-19)</a>:
+# Nunatsiaq News (1999-11-19):
+# http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html
 # Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
 # central - or Nunavut time - for government offices, and eastern time
 # for municipal offices and schools....  Igloolik [was similar but then]
@@ -2002,10 +1964,8 @@
 # Central Time and Southampton Island [in the Central zone] is not
 # required to use daylight savings.
 
-# From
-# <a href="http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html">
-# Nunavut now has two time zones
-# </a> (2000-11-10):
+# From <http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html>
+# Nunavut now has two time zones (2000-11-10):
 # The Nunavut government would allow its employees in Kugluktuk and
 # Cambridge Bay to operate on central time year-round, putting them
 # one hour behind the rest of Nunavut for six months during the winter.
@@ -2096,9 +2056,7 @@
 # used to be the mayor of Resolute Bay and he apparently owns half the
 # businesses including "South Camp Inn." This website has some info on
 # Aziz:
-# <a href="http://www.uphere.ca/node/493">
 # http://www.uphere.ca/node/493
-# </a>
 #
 # I sent Aziz an e-mail asking when Resolute Bay had stopped using
 # Eastern Standard Time.
@@ -2136,47 +2094,47 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
 Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
-			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
-			-5:00	Canada	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
+			-5:00	Canada	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
 Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
-			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
 Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
-			-6:00	Canada	C%sT	2006 Oct 29 2:00
-			-5:00	-	EST	2007 Mar 11 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
+			-6:00	Canada	C%sT	2006 Oct 29  2:00
+			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
 Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
 Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
-			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2000 Nov  5 0:00
-			-6:00	-	CST	2001 Apr  1 3:00
+			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2000 Nov  5  0:00
+			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
 Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
-			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
+			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
+			-9:00	NT_YK	Y%sT	1966 Jul  1  2:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
+			-9:00	NT_YK	Y%sT	1973 Oct 28  0:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 
@@ -2188,9 +2146,8 @@
 # From Paul Eggert (2001-03-05):
 # The Investigation and Analysis Service of the
 # Mexican Library of Congress (MLoC) has published a
-# <a href="http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/">
 # history of Mexican local time (in Spanish)
-# </a>.
+# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
 #
 # Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
 # (In all cases we go with the MLoC.)
@@ -2235,9 +2192,8 @@
 # -------------- End Forwarded Message --------------
 # From Paul Eggert (1996-06-12):
 # For an English translation of the decree, see
-# <a href="http://mexico-travel.com/extra/timezone_eng.html">
 # "Diario Oficial: Time Zone Changeover" (1996-01-04).
-# </a>
+# http://mexico-travel.com/extra/timezone_eng.html
 
 # From Rives McDow (1998-10-08):
 # The State of Quintana Roo has reverted back to central STD and DST times
@@ -2249,7 +2205,7 @@
 # savings time so as to stay on the same time zone as the southern part of
 # Arizona year round.
 
-# From Jesper Norgaard, translating
+# From Jesper Nørgaard, translating
 # <http://www.reforma.com/nacional/articulo/064327/> (2001-01-17):
 # In Oaxaca, the 55.000 teachers from the Section 22 of the National
 # Syndicate of Education Workers, refuse to apply daylight saving each
@@ -2262,7 +2218,7 @@
 # January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
 # that Summer Time will be reduced from seven to five months, starting
 # this year....
-# <http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001>
+# http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001
 # [translated], says "summer time will ... take effect on the first Sunday
 # in May, and end on the last Sunday of September.
 
@@ -2270,23 +2226,22 @@
 # The 2001-01-24 traditional Washington Post contained the page one
 # story "Timely Issue Divides Mexicans."...
 # http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
-# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# ... Mexico City Mayor López Obrador "...is threatening to keep
 # Mexico City and its 20 million residents on a different time than
-# the rest of the country..." In particular, Lopez Obrador would abolish
+# the rest of the country..." In particular, López Obrador would abolish
 # observation of Daylight Saving Time.
 
-# <a href="http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre">
 # Official statute published by the Energy Department
-# </a> (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
-# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
+# http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre
+# (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST.  This was reported by Jesper Nørgaard (2001-02-03).
 
 # From Paul Eggert (2001-03-03):
 #
-# <a href="http://www.latimes.com/news/nation/20010303/t000018766.html">
+# http://www.latimes.com/news/nation/20010303/t000018766.html
 # James F. Smith writes in today's LA Times
-# </a>
 # * Sonora will continue to observe standard time.
-# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
 #   the Federal District will not adopt DST.
 # * 4 of 16 district leaders announced they'll ignore the decree.
 # * The decree does not affect federal-controlled facilities including
@@ -2294,7 +2249,7 @@
 #
 # For now we'll assume that the Federal District will bow to federal rules.
 
-# From Jesper Norgaard (2001-04-01):
+# From Jesper Nørgaard (2001-04-01):
 # I found some references to the Mexican application of daylight
 # saving, which modifies what I had already sent you, stating earlier
 # that a number of northern Mexican states would go on daylight
@@ -2303,7 +2258,7 @@
 # saving all year) will follow the original decree of president
 # Vicente Fox, starting daylight saving May 6, 2001 and ending
 # September 30, 2001.
-# References: "Diario de Monterrey" <www.diariodemonterrey.com/index.asp>
+# References: "Diario de Monterrey" <http://www.diariodemonterrey.com/index.asp>
 # Palabra <http://palabra.infosel.com/010331/primera/ppri3101.pdf> (2001-03-31)
 
 # From Reuters (2001-09-04):
@@ -2315,7 +2270,7 @@
 # standard time. "This is so residents of the Federal District are not
 # subject to unexpected time changes," a statement from the court said.
 
-# From Jesper Norgaard Welen (2002-03-12):
+# From Jesper Nørgaard Welen (2002-03-12):
 # ... consulting my local grocery store(!) and my coworkers, they all insisted
 # that a new decision had been made to reinstate US style DST in Mexico....
 # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
@@ -2329,48 +2284,36 @@
 # > the United States.
 # Now this has passed both the Congress and the Senate, so starting from
 # 2010, some border regions will be the same:
-# <a href="http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/">
 # http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
-# </a>
-# <a href="http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939">
 # http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
-# </a>
 # (Spanish)
 #
 # Could not find the new law text, but the proposed law text changes are here:
-# <a href="http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf">
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
-# </a>
 # (Gaceta Parlamentaria)
 #
 # There is also a list of the votes here:
-# <a href="http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html">
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
-# </a>
 #
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/north-mexico-dst-change.html">
 # http://www.timeanddate.com/news/time/north-mexico-dst-change.html
-# </a>
 
 # From Arthur David Olson (2010-01-20):
 # The page
-# <a href="http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010">
 # http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
-# </a>
 # includes this text:
 # En los municipios fronterizos de Tijuana y Mexicali en Baja California;
-# Ju&aacute;rez y Ojinaga en Chihuahua; Acu&ntilde;a y Piedras Negras en Coahuila;
-# An&aacute;huac en Nuevo Le&oacute;n; y Nuevo Laredo, Reynosa y Matamoros en
-# Tamaulipas, la aplicaci&oacute;n de este horario estacional surtir&aacute; efecto
-# desde las dos horas del segundo domingo de marzo y concluir&aacute; a las dos
+# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
+# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
+# Tamaulipas, la aplicación de este horario estacional surtirá efecto
+# desde las dos horas del segundo domingo de marzo y concluirá a las dos
 # horas del primer domingo de noviembre.
 # En los municipios fronterizos que se encuentren ubicados en la franja
-# fronteriza norte en el territorio comprendido entre la l&iacute;nea
-# internacional y la l&iacute;nea paralela ubicada a una distancia de veinte
-# kil&oacute;metros, as&iacute; como la Ciudad de Ensenada, Baja California, hacia el
-# interior del pa&iacute;s, la aplicaci&oacute;n de este horario estacional surtir&aacute;
-# efecto desde las dos horas del segundo domingo de marzo y concluir&aacute; a
+# fronteriza norte en el territorio comprendido entre la línea
+# internacional y la línea paralela ubicada a una distancia de veinte
+# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
+# interior del país, la aplicación de este horario estacional surtirá
+# efecto desde las dos horas del segundo domingo de marzo y concluirá a
 # las dos horas del primer domingo de noviembre.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -2389,39 +2332,39 @@
 Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
 Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Quintana Roo
+# Quintana Roo; represented by Cancún
 Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
 			-6:00	-	CST	1981 Dec 23
 			-5:00	Mexico	E%sT	1998 Aug  2  2:00
 			-6:00	Mexico	C%sT
-# Campeche, Yucatan
+# Campeche, Yucatán; represented by Mérida
 Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
 			-6:00	-	CST	1981 Dec 23
 			-5:00	-	EST	1982 Dec  2
 			-6:00	Mexico	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (near US border)
 Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT	2010
 			-6:00	US	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (away from US border)
 Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT
 # Central Mexico
-Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
+Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1  0:23:24
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
 			-6:00	-	CST	1931 Oct
 			-7:00	-	MST	1932 Apr  1
-			-6:00	Mexico	C%sT	2001 Sep 30 02:00
+			-6:00	Mexico	C%sT	2001 Sep 30  2:00
 			-6:00	-	CST	2002 Feb 20
 			-6:00	Mexico	C%sT
 # Chihuahua (near US border)
-Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
+Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan  1  0:02:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
@@ -2429,7 +2372,7 @@
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT	2010
 			-7:00	US	M%sT
 # Chihuahua (away from US border)
@@ -2441,7 +2384,7 @@
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT
 # Sonora
 Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
@@ -2457,42 +2400,33 @@
 			-7:00	-	MST
 
 # From Alexander Krivenyshev (2010-04-21):
-# According to news, Bah&iacute;a de Banderas (Mexican state of Nayarit)
+# According to news, Bahía de Banderas (Mexican state of Nayarit)
 # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
 # share the same time zone as nearby city Puerto Vallarta, Jalisco).
 #
 # (Spanish)
-# Bah&iacute;a de Banderas homologa su horario al del centro del
-# pa&iacute;s, a partir de este domingo
-# <a href="http://www.nayarit.gob.mx/notes.asp?id=20748">
+# Bahía de Banderas homologa su horario al del centro del
+# país, a partir de este domingo
 # http://www.nayarit.gob.mx/notes.asp?id=20748
-# </a>
 #
-# Bah&iacute;a de Banderas homologa su horario con el del Centro del
-# Pa&iacute;s
-# <a href="http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50">
-# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
-# </a>
+# Bahía de Banderas homologa su horario con el del Centro del
+# País
+# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50
 #
 # (English)
-# Puerto Vallarta and Bah&iacute;a de Banderas: One Time Zone
-# <a href="http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml">
+# Puerto Vallarta and Bahía de Banderas: One Time Zone
 # http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
-# </a>
-#
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_mexico08.html">
 # http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
-# </a>
 #
 # "Mexico's Senate approved the amendments to the Mexican Schedule System that
-# will allow Bah&iacute;a de Banderas and Puerto Vallarta to share the same time
+# will allow Bahía de Banderas and Puerto Vallarta to share the same time
 # zone ..."
 # Baja California Sur, Nayarit, Sinaloa
 
 # From Arthur David Olson (2010-05-01):
 # Use "Bahia_Banderas" to keep the name to fourteen characters.
 
+# Mazatlán
 Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2504,6 +2438,7 @@
 			-8:00	-	PST	1970
 			-7:00	Mexico	M%sT
 
+# Bahía de Banderas
 Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2513,7 +2448,7 @@
 			-6:00	-	CST	1942 Apr 24
 			-7:00	-	MST	1949 Jan 14
 			-8:00	-	PST	1970
-			-7:00	Mexico	M%sT	2010 Apr 4 2:00
+			-7:00	Mexico	M%sT	2010 Apr  4  2:00
 			-6:00	Mexico	C%sT
 
 # Baja California (near US border)
@@ -2560,7 +2495,7 @@
 # America/Tijuana only in that it did not observe DST from 1976
 # through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
 # Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
-# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# that the 1987 OAG says "Only Ensenada, Mexicali, San Felipe and
 # Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
 # DST-observance was a town-by-town matter back then.  This concerns
 # data after 1970 so most likely there should be at least one Zone
@@ -2573,7 +2508,7 @@
 ###############################################################################
 
 # Anguilla
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Antigua and Barbuda
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2609,8 +2544,8 @@
 Rule	Barb	1979	only	-	Sep	30	2:00	0	S
 Rule	Barb	1980	only	-	Sep	25	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Barbados	-3:58:29 -	LMT	1924		# Bridgetown
-			-3:58:29 -	BMT	1932	  # Bridgetown Mean Time
+Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
+			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
 			-4:00	Barb	A%sT
 
 # Belize
@@ -2640,20 +2575,20 @@
 # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1 2:00    # Hamilton
-			-4:00	-	AST	1974 Apr 28 2:00
+Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
+			-4:00	-	AST	1974 Apr 28  2:00
 			-4:00	Canada	A%sT	1976
 			-4:00	US	A%sT
 
 # Cayman Is
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
+Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
 			-5:00	-	EST
 
 # Costa Rica
 
-# Milne gives -5:36:13.3 as San Jose mean time; round to nearest.
+# Milne gives -5:36:13.3 as San José mean time; round to nearest.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
@@ -2663,10 +2598,10 @@
 # go with Shanks & Pottenger.
 Rule	CR	1991	only	-	Jul	 1	0:00	0	S
 Rule	CR	1992	only	-	Mar	15	0:00	0	S
-# There are too many San Joses elsewhere, so we'll use 'Costa Rica'.
+# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
-			-5:36:13 -	SJMT	1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
+			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
 			-6:00	CR	C%sT
 # Coco
 # no information; probably like America/Costa_Rica
@@ -2685,8 +2620,8 @@
 # During the game, play-by-play announcer Jim Hunter noted that
 # "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
 # Time today."  (The "two hour" remark referred to losing one hour of
-# sleep on 1999-03-28--when the announcers were in Cuba as it switched
-# to DST--and one more hour on 1999-04-04--when the announcers will have
+# sleep on 1999-03-28 - when the announcers were in Cuba as it switched
+# to DST - and one more hour on 1999-04-04 - when the announcers will have
 # returned to Baltimore, which switches on that date.)
 
 # From Steffen Thorsen (2013-11-11):
@@ -2708,16 +2643,16 @@
 # adjustment in Cuba.  We will stay in daylight saving time:
 # http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
 
-# From Jesper Norgaard Welen (2006-10-21):
+# From Jesper Nørgaard Welen (2006-10-21):
 # An article in GRANMA INTERNACIONAL claims that Cuba will end
 # the 3 years of permanent DST next weekend, see
 # http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
 # "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
-# watches should be set back one hour -- going back to 00:00 hours -- returning
+# watches should be set back one hour - going back to 00:00 hours - returning
 # to the normal schedule....
 
 # From Paul Eggert (2007-03-02):
-# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
+# <http://www.granma.cubaweb.cu/english/news/art89.html>, dated yesterday,
 # says Cuban clocks will advance at midnight on March 10.
 # For lack of better information, assume Cuba will use US rules,
 # except that it switches at midnight standard time as usual.
@@ -2731,10 +2666,10 @@
 # http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
 # http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
 #
-# From Alex Kryvenishev (2007-10-25):
+# From Alex Krivenyshev (2007-10-25):
 # Here is also article from Granma (Cuba):
 #
-# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
+# Regirá el Horario Normal desde el próximo domingo 28 de octubre
 # http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
 #
 # http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
@@ -2742,23 +2677,18 @@
 # From Arthur David Olson (2008-03-09):
 # I'm in Maryland which is now observing United States Eastern Daylight
 # Time. At 9:44 local time I used RealPlayer to listen to
-# <a href="http://media.enet.cu/radioreloj">
 # http://media.enet.cu/radioreloj
-# </a>, a Cuban information station, and heard
+# a Cuban information station, and heard
 # the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
 # indicating that Cuba is still on standard time.
 
 # From Steffen Thorsen (2008-03-12):
 # It seems that Cuba will start DST on Sunday, 2007-03-16...
 # It was announced yesterday, according to this source (in Spanish):
-# <a href="http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm">
 # http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
-# </a>
 #
 # Some more background information is posted here:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
-# </a>
 #
 # The article also says that Cuba has been observing DST since 1963,
 # while Shanks (and tzdata) has 1965 as the first date (except in the
@@ -2768,18 +2698,14 @@
 # change some historic records as well.
 #
 # One example:
-# <a href="http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm">
 # http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
-# </a>
 
-# From Jesper Norgaard Welen (2008-03-13):
+# From Jesper Nørgaard Welen (2008-03-13):
 # The Cuban time change has just been confirmed on the most authoritative
 # web site, the Granma.  Please check out
-# <a href="http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html">
 # http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
-# </a>
 #
-# Basically as expected after Steffen Thorsens information, the change
+# Basically as expected after Steffen Thorsen's information, the change
 # will take place midnight between Saturday and Sunday.
 
 # From Arthur David Olson (2008-03-12):
@@ -2790,18 +2716,14 @@
 # midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
 # not on midnight March 14 / March 15 as previously thought.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_cuba05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
 # (in Spanish)
-# </a>
 
 # From Arthur David Olson (2009-03-09)
 # I listened over the Internet to
-# <a href="http://media.enet.cu/readioreloj">
 # http://media.enet.cu/readioreloj
-# </a>
 # this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
-# the time was announced as "diez cinco"--the same time as here, indicating
+# the time was announced as "diez cinco" - the same time as here, indicating
 # that has indeed switched to DST. Assume second Sunday from 2009 forward.
 
 # From Steffen Thorsen (2011-03-08):
@@ -2810,42 +2732,30 @@
 # changed at all).
 #
 # Source:
-# <a href="http://granma.co.cu/2011/03/08/nacional/artic01.html">
 # http://granma.co.cu/2011/03/08/nacional/artic01.html
-# </a>
 #
 # Our info:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
-# </a>
 #
 # From Steffen Thorsen (2011-10-30)
 # Cuba will end DST two weeks later this year. Instead of going back
 # tonight, it has been delayed to 2011-11-13 at 01:00.
 #
 # One source (Spanish)
-# <a href="http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html">
 # http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
-# </a>
 #
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/cuba-time-changes-2011.html">
 # http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
-# </a>
 #
 # From Steffen Thorsen (2012-03-01)
 # According to Radio Reloj, Cuba will start DST on Midnight between March
 # 31 and April 1.
 #
 # Radio Reloj has the following info (Spanish):
-# <a href="http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril">
 # http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
-# </a>
 #
 # Our info on it:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
-# </a>
 
 # From Steffen Thorsen (2012-11-03):
 # Radio Reloj and many other sources report that Cuba is changing back
@@ -2901,7 +2811,7 @@
 			-5:00	Cuba	C%sT
 
 # Dominica
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Dominican Republic
 
@@ -2934,8 +2844,8 @@
 Zone America/Santo_Domingo -4:39:36 -	LMT	1890
 			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
 			-5:00	DR	E%sT	1974 Oct 27
-			-4:00	-	AST	2000 Oct 29 02:00
-			-5:00	US	E%sT	2000 Dec  3 01:00
+			-4:00	-	AST	2000 Oct 29  2:00
+			-5:00	US	E%sT	2000 Dec  3  1:00
 			-4:00	-	AST
 
 # El Salvador
@@ -2946,20 +2856,20 @@
 # There are too many San Salvadors elsewhere, so use America/El_Salvador
 # instead of America/San_Salvador.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
+Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
 			-6:00	Salv	C%sT
 
 # Grenada
 # Guadeloupe
-# St Barthelemy
+# St Barthélemy
 # St Martin (French part)
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Guatemala
 #
 # From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
 # Diario Co Latino, at
-# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
+# <http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079>,
 # says in an article dated 2006-04-19 that the Guatemalan government had
 # decided on that date to advance official time by 60 minutes, to lessen the
 # impact of the elevated cost of oil....  Daylight saving time will last from
@@ -2967,7 +2877,7 @@
 # From Paul Eggert (2006-06-22):
 # The Ministry of Energy and Mines, press release CP-15/2006
 # (2006-04-19), says DST ends at 24:00.  See
-# <http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf>.
+# http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
@@ -2984,11 +2894,10 @@
 
 # Haiti
 # From Gwillim Law (2005-04-15):
-# Risto O. Nykanen wrote me that Haiti is now on DST.
-# I searched for confirmation, and I found a
-# <a href="http://www.haitianconsulate.org/time.doc"> press release
+# Risto O. Nykänen wrote me that Haiti is now on DST.
+# I searched for confirmation, and I found a press release
 # on the Web page of the Haitian Consulate in Chicago (2005-03-31),
-# </a>.  Translated from French, it says:
+# <http://www.haitianconsulate.org/time.doc>.  Translated from French, it says:
 #
 #  "The Prime Minister's Communication Office notifies the public in general
 #   and the press in particular that, following a decision of the Interior
@@ -3065,14 +2974,14 @@
 # <http://www.latribuna.hn/99299.html> that Manuel Zelaya, the president
 # of Honduras, refused to back down on this.
 
-# From Jesper Norgaard Welen (2006-08-08):
+# From Jesper Nørgaard Welen (2006-08-08):
 # It seems that Honduras has returned from DST to standard time this Monday at
 # 00:00 hours (prolonging Sunday to 25 hours duration).
 # http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
 
 # From Paul Eggert (2006-08-08):
-# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
-# <http://www.elheraldo.hn/nota.php?nid=54941&sec=12>.
+# Also see Diario El Heraldo, The country returns to standard time (2006-08-08).
+# http://www.elheraldo.hn/nota.php?nid=54941&sec=12
 # It mentions executive decree 18-2006.
 
 # From Steffen Thorsen (2006-08-17):
@@ -3100,22 +3009,22 @@
 # unspecified official document, and says "This time is used throughout the
 # island".  Go with Milne.  Round to the nearest second as required by zic.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Jamaica	-5:07:11 -	LMT	1890		# Kingston
+Zone	America/Jamaica	-5:07:11 -	LMT	1890        # Kingston
 			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	-	EST	1974 Apr 28 2:00
+			-5:00	-	EST	1974 Apr 28  2:00
 			-5:00	US	E%sT	1984
 			-5:00	-	EST
 
 # Martinique
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
-			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
+Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
+			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
 			-4:00	-	AST	1980 Apr  6
 			-4:00	1:00	ADT	1980 Sep 28
 			-4:00	-	AST
 
 # Montserrat
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Nicaragua
 #
@@ -3138,27 +3047,27 @@
 # From Gwillim Law (2005-04-21):
 # The Associated Press story on the time change, which can be found at
 # http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
-# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
+# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
 # time that a change of clocks was applied to save energy was in the year 2000
-# during the Arnoldo Aleman administration."...
+# during the Arnoldo Alemán administration."...
 # The northamerica file says that Nicaragua has been on UTC-6 continuously
 # since December 1998.  I wasn't able to find any details of Nicaraguan time
 # changes in 2000.  Perhaps a note could be added to the northamerica file, to
 # the effect that we have indirect evidence that DST was observed in 2000.
 #
-# From Jesper Norgaard Welen (2005-11-02):
+# From Jesper Nørgaard Welen (2005-11-02):
 # Nicaragua left DST the 2005-10-02 at 00:00 (local time).
 # http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
 # (2005-09-26)
 #
-# From Jesper Norgaard Welen (2006-05-05):
+# From Jesper Nørgaard Welen (2006-05-05):
 # http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
 # (my informal translation)
-# By order of the president of the republic, Enrique Bolanos, Nicaragua
+# By order of the president of the republic, Enrique Bolaños, Nicaragua
 # advanced by sixty minutes their official time, yesterday at 2 in the
-# morning, and will stay that way until 30.th. of september.
+# morning, and will stay that way until 30th of September.
 #
-# From Jesper Norgaard Welen (2006-09-30):
+# From Jesper Nørgaard Welen (2006-09-30):
 # http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
 # My informal translation runs:
 # The natural sun time is restored in all the national territory, in that the
@@ -3176,7 +3085,7 @@
 			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
 			-6:00	-	CST	1973 May
 			-5:00	-	EST	1975 Feb 16
-			-6:00	Nic	C%sT	1992 Jan  1 4:00
+			-6:00	Nic	C%sT	1992 Jan  1  4:00
 			-5:00	-	EST	1992 Sep 24
 			-6:00	-	CST	1993
 			-5:00	-	EST	1997
@@ -3185,36 +3094,36 @@
 # Panama
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Panama	-5:18:08 -	LMT	1890
-			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
+			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
 			-5:00	-	EST
 
 # Puerto Rico
 # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
+Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
 			-4:00	-	AST	1942 May  3
 			-4:00	US	A%sT	1946
 			-4:00	-	AST
 
 # St Kitts-Nevis
 # St Lucia
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # St Pierre and Miquelon
 # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
+Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
 			-4:00	-	AST	1980 May
 			-3:00	-	PMST	1987 # Pierre & Miquelon Time
 			-3:00	Canada	PM%sT
 
 # St Vincent and the Grenadines
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Turks and Caicos
 #
 # From Chris Dunn in
-# <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007>
+# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007
 # (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
 # daylight saving dates for time changes have been adjusted to match
 # the recent U.S. change of dates.
@@ -3227,21 +3136,23 @@
 # Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
 # indicating that the normal ET rules are followed.
 #
-# From Paul Eggert (2006-05-01):
-# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
-# says they switch at midnight.  Go with Shanks & Pottenger.
+# From Paul Eggert (2014-08-19):
+# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
+# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
+# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
 #
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
-Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
-Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
-Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
-Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Grand_Turk	-4:44:32 -	LMT	1890
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	TC	E%sT
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
+			-5:00	-	EST	1979
+			-5:00	US	E%sT	2014 Nov  2  2:00
+			-4:00	-	AST
 
 # British Virgin Is
 # Virgin Is
-# See 'southamerica'.
+# See America/Port_of_Spain.
+
+
+# Local Variables:
+# coding: utf-8
+# End:
--- a/jdk/make/data/tzdata/pacificnew	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/pacificnew	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/make/data/tzdata/southamerica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/southamerica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2006-03-22):
 # A good source for time zone historical data outside the U.S. is
@@ -35,8 +35,8 @@
 # San Diego: ACS Publications, Inc. (2003).
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # Gwillim Law writes that a good source
 # for recent time zone data is the International Air Transport
@@ -53,24 +53,24 @@
 #	I suggest the use of _Summer time_ instead of the more cumbersome
 #	_daylight-saving time_.  _Summer time_ seems to be in general use
 #	in Europe and South America.
-#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
+#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
 #	H L Mencken, _The American Language: Supplement I_ (1960), p 466
 #
 # Earlier editions of these tables also used the North American style
 # for time zones in Brazil, but this was incorrect, as Brazilians say
-# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
+# "summer time".  Reinaldo Goulart, a São Paulo businessman active in
 # the railroad sector, writes (1999-07-06):
 #	The subject of time zones is currently a matter of discussion/debate in
-#	Brazil.  Let's say that "the Brasilia time" is considered the
-#	"official time" because Brasilia is the capital city.
-#	The other three time zones are called "Brasilia time "minus one" or
+#	Brazil.  Let's say that "the Brasília time" is considered the
+#	"official time" because Brasília is the capital city.
+#	The other three time zones are called "Brasília time "minus one" or
 #	"plus one" or "plus two".  As far as I know there is no such
 #	name/designation as "Eastern Time" or "Central Time".
 # So I invented the following (English-language) abbreviations for now.
 # Corrections are welcome!
 #		std	dst
 #	-2:00	FNT	FNST	Fernando de Noronha
-#	-3:00	BRT	BRST	Brasilia
+#	-3:00	BRT	BRST	Brasília
 #	-4:00	AMT	AMST	Amazon
 #	-5:00	ACT	ACST	Acre
 
@@ -84,7 +84,7 @@
 # Argentina: first Sunday in October to first Sunday in April since 1976.
 # Double Summer time from 1969 to 1974.  Switches at midnight.
 
-# From U. S. Naval Observatory (1988-01-199):
+# From U. S. Naval Observatory (1988-01-19):
 # ARGENTINA           3 H BEHIND   UTC
 
 # From Hernan G. Otero (1995-06-26):
@@ -118,7 +118,7 @@
 # From Hernan G. Otero (1995-06-26):
 # These corrections were contributed by InterSoft Argentina S.A.,
 # obtaining the data from the:
-# Talleres de Hidrografia Naval Argentina
+# Talleres de Hidrografía Naval Argentina
 # (Argentine Naval Hydrography Institute)
 Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
 Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
@@ -140,13 +140,13 @@
 Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 #
 # From Peter Gradelski via Steffen Thorsen (2000-03-01):
-# We just checked with our Sao Paulo office and they say the government of
+# We just checked with our São Paulo office and they say the government of
 # Argentina decided not to become one of the countries that go on or off DST.
 # So Buenos Aires should be -3 hours from GMT at all times.
 #
-# From Fabian L. Arce Jofre (2000-04-04):
+# From Fabián L. Arce Jofré (2000-04-04):
 # The law that claimed DST for Argentina was derogated by President Fernando
-# de la Rua on March 2, 2000, because it would make people spend more energy
+# de la Rúa on March 2, 2000, because it would make people spend more energy
 # in the winter time, rather than less.  The change took effect on March 3.
 #
 # From Mariano Absatz (2001-06-06):
@@ -179,15 +179,13 @@
 # that Argentina will use DST next year as well, from October to
 # March, although exact rules are not given.
 #
-# From Jesper Norgaard Welen (2007-12-26)
+# From Jesper Nørgaard Welen (2007-12-26)
 # The last hurdle of Argentina DST is over, the proposal was approved in
-# the lower chamber too (Deputados) with a vote 192 for and 2 against.
+# the lower chamber too (Diputados) with a vote 192 for and 2 against.
 # By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
 # the original scanned proposal, where the dates and the zero hours are
 # clear and unambiguous...This is the article about final approval:
-# <a href="http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996">
 # http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
-# </a>
 #
 # From Paul Eggert (2007-12-22):
 # For dates after mid-2008, the following rules are my guesses and
@@ -197,13 +195,8 @@
 # As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
 # Argentina will start DST on Sunday October 19, 2008.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_argentina03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
-# </a>
-# OR
-# <a href="http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)">
 # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# </a>
 
 # From Rodrigo Severo (2008-10-06):
 # Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
@@ -212,48 +205,39 @@
 # Hi, there is a problem with timezone-data-2008e and maybe with
 # timezone-data-2008f
 # Argentinian law [Number] 25.155 is no longer valid.
-# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm">
 # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# </a>
 # The new one is law [Number] 26.350
-# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm">
 # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
-# </a>
 # So there is no summer time in Argentina for now.
 
 # From Mariano Absatz (2008-10-20):
-# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
-# From 2008-10-19 until 2009-03-15
-# <a href="http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01">
+# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST
+# in Argentina from 2008-10-19 until 2009-03-15.
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
-# </a>
 #
-# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
-# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
-# and Tierra del Fuego
-# <a href="http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01">
+
+# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer
+# 2008/2009: Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La
+# Pampa, Neuquén, Rio Negro, Chubut, Santa Cruz and Tierra del Fuego
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
-# </a>
 #
-# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
-# it will not apply DST either (even when it was not included in Decree 1705/2008)
-# <a href="http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc">
+# Press release 235 dated Saturday October 18th, from the Government of the
+# Province of Jujuy saying it will not apply DST either (even when it was not
+# included in Decree 1705/2008).
 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
-# </a>
 
 # From fullinet (2009-10-18):
 # As announced in
-# <a hef="http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356">
 # http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
-# </a>
-# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
+# (an official .gob.ar) under title: "Sin Cambio de Hora"
+# (English: "No hour change").
 #
-# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
-# oficial, decision que estaba en estudio para su implementacion el
-# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
-# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
-# la modificacion del huso horario, ya que 2009 nos encuentra con
-# crecimiento en la produccion y distribucion energetica."
+# "Por el momento, el Gobierno Nacional resolvió no modificar la hora
+# oficial, decisión que estaba en estudio para su implementación el
+# domingo 18 de octubre. Desde el Ministerio de Planificación se anunció
+# que la Argentina hoy, en estas condiciones meteorológicas, no necesita
+# la modificación del huso horario, ya que 2009 nos encuentra con
+# crecimiento en la producción y distribución energética."
 
 Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
 Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
@@ -267,10 +251,10 @@
 # It's Law No. 7,210.  This change is due to a public power emergency, so for
 # now we'll assume it's for this year only.
 #
-# From Paul Eggert (2006-03-22):
-# <a href="http://www.spicasc.net/horvera.html">
-# Hora de verano para la Republica Argentina (2003-06-08)
-# </a> says that standard time in Argentina from 1894-10-31
+# From Paul Eggert (2014-08-09):
+# Hora de verano para la República Argentina
+# http://buenasiembra.com.ar/esoterismo/astrologia/hora-de-verano-de-la-republica-argentina-27.html
+# says that standard time in Argentina from 1894-10-31
 # to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
 # over Shanks & Pottenger.
 #
@@ -285,10 +269,10 @@
 # time in October 17th.
 #
 # Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
-# Tierra del Fuego, Tucuman.
+# Tierra del Fuego, Tucumán.
 #
 # From Mariano Absatz (2004-06-14):
-# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
+# ... this weekend, the Province of Tucumán decided it'd go back to UTC-03:00
 # yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
 # annoyance with the change is much higher than the power savings obtained....
 #
@@ -323,49 +307,38 @@
 # Here are articles that Argentina Province San Luis is planning to end DST
 # as earlier as upcoming Monday January 21, 2008 or February 2008:
 #
-# Provincia argentina retrasa reloj y marca diferencia con resto del pais
+# Provincia argentina retrasa reloj y marca diferencia con resto del país
 # (Argentine Province delayed clock and mark difference with the rest of the
 # country)
-# <a href="http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel">
 # http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
-# </a>
 #
 # Es inminente que en San Luis atrasen una hora los relojes
 # (It is imminent in San Luis clocks one hour delay)
-# <a href="http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414">
-# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
-# </a>
-#
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_argentina02.html">
+# http://www.lagaceta.com.ar/nota/253414/Economia/Es-inminente-que-en-San-Luis-atrasen-una-hora-los-relojes.html
 # http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
-# </a>
 
-# From Jesper Norgaard Welen (2008-01-18):
+# From Jesper Nørgaard Welen (2008-01-18):
 # The page of the San Luis provincial government
-# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812">
 # http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
-# </a>
 # confirms what Alex Krivenyshev has earlier sent to the tz
 # emailing list about that San Luis plans to return to standard
 # time much earlier than the rest of the country. It also
 # confirms that upon request the provinces San Juan and Mendoza
 # refused to follow San Luis in this change.
 #
-# The change is supposed to take place Monday the 21.st at 0:00
+# The change is supposed to take place Monday the 21st at 0:00
 # hours. As far as I understand it if this goes ahead, we need
 # a new timezone for San Luis (although there are also documented
 # independent changes in the southamerica file of San Luis in
 # 1990 and 1991 which has not been confirmed).
 
-# From Jesper Norgaard Welen (2008-01-25):
+# From Jesper Nørgaard Welen (2008-01-25):
 # Unfortunately the below page has become defunct, about the San Luis
 # time change. Perhaps because it now is part of a group of pages "Most
 # important pages of 2008."
 #
 # You can use
-# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834">
 # http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
-# </a>
 # instead it seems. Or use "Buscador" from the main page of the San Luis
 # government, and fill in "huso" and click OK, and you will get 3 pages
 # from which the first one is identical to the above.
@@ -385,9 +358,9 @@
 # back in 2004, when these provinces changed to UTC-4 for a few days, I
 # mailed them personally and never got an answer).
 
-# From Paul Eggert (2008-06-30):
-# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
-# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
+# From Paul Eggert (2014-08-12):
+# Unless otherwise specified, data entries are from Shanks & Pottenger through
+# 1992, from the IATA otherwise.  As noted below, Shanks & Pottenger say that
 # America/Cordoba split into 6 subregions during 1991/1992, one of which
 # was America/San_Luis, but we haven't verified this yet so for now we'll
 # keep America/Cordoba a single region rather than splitting it into the
@@ -399,14 +372,9 @@
 # to utc-04:00 until the second Saturday in October...
 #
 # The press release is at
-# <a href="http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102">
 # http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
-# </a>
-# (I couldn't find the decree, but
-# <a href="http://www.sanluis.gov.ar">
-# www.sanluis.gov.ar
-# <a/>
-# is the official page for the Province Government).
+# (I couldn't find the decree, but www.sanluis.gov.ar
+# is the official page for the Province Government.)
 #
 # There's also a note in only one of the major national papers ...
 # http://www.lanacion.com.ar/nota.asp?nota_id=1107912
@@ -423,9 +391,7 @@
 # ...the Province of San Luis is a case in itself.
 #
 # The Law at
-# <a href="http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276>"
 # http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276
-# </a>
 # is ambiguous because establishes a calendar from the 2nd Sunday in
 # October at 0:00 thru the 2nd Saturday in March at 24:00 and the
 # complement of that starting on the 2nd Sunday of March at 0:00 and
@@ -454,19 +420,15 @@
 # ...
 
 # From Alexander Krivenyshev (2010-04-09):
-# According to news reports from El Diario de la Republica Province San
+# According to news reports from El Diario de la República Province San
 # Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
-# after April 11, 2010--will continue to have same time as rest of
+# after April 11, 2010 - will continue to have same time as rest of
 # Argentina (UTC-3) (no DST).
 #
-# Confirmaron la pr&oacute;rroga del huso horario de verano (Spanish)
-# <a href="http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9">
+# Confirmaron la prórroga del huso horario de verano (Spanish)
 # http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
-# </a>
 # or (some English translation):
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_argentina08.html">
 # http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
-# </a>
 
 # From Mariano Absatz (2010-04-12):
 # yes...I can confirm this...and given that San Luis keeps calling
@@ -478,7 +440,7 @@
 # Perhaps San Luis operates on the legal fiction that it is at UTC-4
 # with perpetual summer time, but ordinary usage typically seems to
 # just say it's at UTC-3; see, for example,
-# <http://es.wikipedia.org/wiki/Hora_oficial_argentina>.
+# http://es.wikipedia.org/wiki/Hora_oficial_argentina
 # We've documented similar situations as being plain changes to
 # standard time, so let's do that here too.  This does not change UTC
 # offsets, only tm_isdst and the time zone abbreviations.  One minor
@@ -486,20 +448,20 @@
 # setting for time stamps past 2038.
 
 # From Paul Eggert (2013-02-21):
-# Milne says Cordoba time was -4:16:48.2.  Round to the nearest second.
+# Milne says Córdoba time was -4:16:48.2.  Round to the nearest second.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
-Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
+# Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN),
 # Chaco (CC), Formosa (FM), Santiago del Estero (SE)
 #
 # Shanks & Pottenger also make the following claims, which we haven't verified:
@@ -519,7 +481,7 @@
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
+# Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN)
 Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -531,7 +493,7 @@
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tucuman (TM)
+# Tucumán (TM)
 Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -642,8 +604,8 @@
 			-3:00	-	ART
 #
 # Santa Cruz (SC)
-Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -653,9 +615,9 @@
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
-Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+# Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF)
+Zone America/Argentina/Ushuaia -4:33:12 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -686,13 +648,13 @@
 
 # From IATA SSIM (1996-02):
 # _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
-# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
-# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Santa Catarina (SC), Paraná (PR), São Paulo (SP), Rio de Janeiro (RJ),
+# Espírito Santo (ES), Minas Gerais (MG), Bahia (BA), Goiás (GO),
 # Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
 # [The last three states are new to this issue of the IATA SSIM.]
 
 # From Gwillim Law (1996-10-07):
-# Geography, history (Tocantins was part of Goias until 1989), and other
+# Geography, history (Tocantins was part of Goiás until 1989), and other
 # sources of time zone information lead me to believe that AL, SE, and TO were
 # always in BR1, and so the only change was whether or not they observed DST....
 # The earliest issue of the SSIM I have is 2/91.  Each issue from then until
@@ -706,16 +668,14 @@
 # However, some conclusions can be drawn from another IATA manual: the Airline
 # Coding Directory, which lists close to 400 airports in Brazil.  For each
 # airport it gives a time zone which is coded to the SSIM.  From that
-# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
-# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
-# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
+# information, I'm led to conclude that the states of Amapá (AP), Ceará (CE),
+# Maranhão (MA), Paraíba (PR), Pernambuco (PE), Piauí (PI), and Rio Grande do
+# Norte (RN), and the eastern part of Pará (PA) are all in BR1 without DST.
 
 # From Marcos Tadeu (1998-09-27):
-# <a href="http://pcdsh01.on.br/verao1.html">
-# Brazilian official page
-# </a>
+# Brazilian official page <http://pcdsh01.on.br/verao1.html>
 
-# From Jesper Norgaard (2000-11-03):
+# From Jesper Nørgaard (2000-11-03):
 # [For an official list of which regions in Brazil use which time zones, see:]
 # http://pcdsh01.on.br/Fusbr.htm
 # http://pcdsh01.on.br/Fusbrhv.htm
@@ -748,13 +708,13 @@
 
 # From Paul Schulze (2008-06-24):
 # ...by law number 11.662 of April 24, 2008 (published in the "Diario
-# Oficial da Uniao"...) in Brazil there are changes in the timezones,
+# Oficial da União"...) in Brazil there are changes in the timezones,
 # effective today (00:00am at June 24, 2008) as follows:
 #
-# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
+# a) The timezone UTC+5 is extinguished, with all the Acre state and the
 # part of the Amazonas state that had this timezone now being put to the
 # timezone UTC+4
-# b) The whole Para state now is put at timezone UTC+3, instead of just
+# b) The whole Pará state now is put at timezone UTC+3, instead of just
 # part of it, as was before.
 #
 # This change follows a proposal of senator Tiao Viana of Acre state, that
@@ -767,13 +727,11 @@
 
 # From Rodrigo Severo (2008-06-24):
 # Just correcting the URL:
-# <a href="https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008">
 # https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
-# </a>
 #
 # As a result of the above Decree I believe the America/Rio_Branco
 # timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
-# be created to represent the...west side of the Para State. I
+# be created to represent the...west side of the Pará State. I
 # suggest this new timezone be called Santarem as the most
 # important/populated city in the affected area.
 #
@@ -782,19 +740,16 @@
 
 # From Alex Krivenyshev (2008-06-24):
 # This is a quick reference page for New and Old Brazil Time Zones map.
-# <a href="http://www.worldtimezone.com/brazil-time-new-old.php">
 # http://www.worldtimezone.com/brazil-time-new-old.php
-# </a>
 #
-# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
-# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
-# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
+# - 4 time zones replaced by 3 time zones - eliminating time zone UTC-05
+# (state Acre and the part of the Amazonas will be UTC/GMT-04) - western
+# part of Par state is moving to one timezone UTC-03 (from UTC-04).
 
 # From Paul Eggert (2002-10-10):
 # The official decrees referenced below are mostly taken from
-# <a href="http://pcdsh01.on.br/DecHV.html">
-# Decretos sobre o Horario de Verao no Brasil
-# </a>.
+# Decretos sobre o Horário de Verão no Brasil.
+# http://pcdsh01.on.br/DecHV.html
 
 # From Steffen Thorsen (2008-08-29):
 # As announced by the government and many newspapers in Brazil late
@@ -806,25 +761,17 @@
 # It has not yet been posted to http://pcdsh01.on.br/DecHV.html
 #
 # An official page about it:
-# <a href="http://www.mme.gov.br/site/news/detail.do?newsId=16722">
 # http://www.mme.gov.br/site/news/detail.do?newsId=16722
-# </a>
 # Note that this link does not always work directly, but must be accessed
 # by going to
-# <a href="http://www.mme.gov.br/first">
 # http://www.mme.gov.br/first
-# </a>
 #
 # One example link that works directly:
-# <a href="http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54">
 # http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
 # (Portuguese)
-# </a>
 #
 # We have a written a short article about it as well:
-# <a href="http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html">
 # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
-# </a>
 #
 # From Alexander Krivenyshev (2011-10-04):
 # State Bahia will return to Daylight savings time this year after 8 years off.
@@ -832,17 +779,12 @@
 # television station in Salvador.
 
 # In Portuguese:
-# <a href="http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html">
 # http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
-# </a> and
-# <a href="http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html">
 # http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
-# </a>
 
 # From Guilherme Bernardes Rodrigues (2011-10-07):
 # There is news in the media, however there is still no decree about it.
-# I just send a e-mail to Zulmira Brandao at
-# <a href="http://pcdsh01.on.br/">http://pcdsh01.on.br/</a> the
+# I just send a e-mail to Zulmira Brandao at http://pcdsh01.on.br/ the
 # official agency about time in Brazil, and she confirmed that the old rule is
 # still in force.
 
@@ -854,9 +796,7 @@
 #
 # DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
 # Link :
-# <a href="http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6">
 # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
-# </a>
 
 # From Kelley Cook (2012-10-16):
 # The governor of state of Bahia in Brazil announced on Thursday that
@@ -884,42 +824,42 @@
 # For now, assume western Amazonas will change as well.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
-# Decree <a href="http://pcdsh01.on.br/HV21896.htm">21,896</a> (1932-01-10)
+# Decree 20,466 <http://pcdsh01.on.br/HV20466.htm> (1931-10-01)
+# Decree 21,896 <http://pcdsh01.on.br/HV21896.htm> (1932-01-10)
 Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
 Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
 Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV23195.htm">23,195</a> (1933-10-10)
+# Decree 23,195 <http://pcdsh01.on.br/HV23195.htm> (1933-10-10)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV27496.htm">27,496</a> (1949-11-24)
-# Decree <a href="http://pcdsh01.on.br/HV27998.htm">27,998</a> (1950-04-13)
+# Decree 27,496 <http://pcdsh01.on.br/HV27496.htm> (1949-11-24)
+# Decree 27,998 <http://pcdsh01.on.br/HV27998.htm> (1950-04-13)
 Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
 Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
 Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV32308.htm">32,308</a> (1953-02-24)
+# Decree 32,308 <http://pcdsh01.on.br/HV32308.htm> (1953-02-24)
 Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV34724.htm">34,724</a> (1953-11-30)
+# Decree 34,724 <http://pcdsh01.on.br/HV34724.htm> (1953-11-30)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV52700.htm">52,700</a> (1963-10-18)
+# Decree 52,700 <http://pcdsh01.on.br/HV52700.htm> (1963-10-18)
 # established DST from 1963-10-23 00:00 to 1964-02-29 00:00
 # in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
-# Decree <a href="http://pcdsh01.on.br/HV53071.htm">53,071</a> (1963-12-03)
+# Decree 53,071 <http://pcdsh01.on.br/HV53071.htm> (1963-12-03)
 # extended the above decree to all of the national territory on 12-09.
 Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV53604.htm">53,604</a> (1964-02-25)
+# Decree 53,604 <http://pcdsh01.on.br/HV53604.htm> (1964-02-25)
 # extended summer time by one day to 1964-03-01 00:00 (start of school).
 Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV55639.htm">55,639</a> (1965-01-27)
+# Decree 55,639 <http://pcdsh01.on.br/HV55639.htm> (1965-01-27)
 Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
 Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV57303.htm">57,303</a> (1965-11-22)
+# Decree 57,303 <http://pcdsh01.on.br/HV57303.htm> (1965-11-22)
 Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV57843.htm">57,843</a> (1966-02-18)
+# Decree 57,843 <http://pcdsh01.on.br/HV57843.htm> (1966-02-18)
 Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
 Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV63429.htm">63,429</a> (1968-10-15)
+# Decree 63,429 <http://pcdsh01.on.br/HV63429.htm> (1968-10-15)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV91698.htm">91,698</a> (1985-09-27)
+# Decree 91,698 <http://pcdsh01.on.br/HV91698.htm> (1985-09-27)
 Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
 # Decree 92,310 (1986-01-21)
 # Decree 92,463 (1986-03-13)
@@ -927,42 +867,42 @@
 # Decree 93,316 (1986-10-01)
 Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV94922.htm">94,922</a> (1987-09-22)
+# Decree 94,922 <http://pcdsh01.on.br/HV94922.htm> (1987-09-22)
 Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV96676.htm">96,676</a> (1988-09-12)
+# Decree 96,676 <http://pcdsh01.on.br/HV96676.htm> (1988-09-12)
 # except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
 Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
 Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV98077.htm">98,077</a> (1989-08-21)
+# Decree 98,077 <http://pcdsh01.on.br/HV98077.htm> (1989-08-21)
 # with the same exceptions
 Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
 Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV99530.htm">99,530</a> (1990-09-17)
+# Decree 99,530 <http://pcdsh01.on.br/HV99530.htm> (1990-09-17)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
 # Decree 99,629 (1990-10-19) adds BA, MT.
 Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
 Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
-# <a href="http://pcdsh01.on.br/HV1991.htm">Unnumbered decree</a> (1991-09-25)
+# Unnumbered decree <http://pcdsh01.on.br/HV1991.htm> (1991-09-25)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
 Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
 Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
-# <a href="http://pcdsh01.on.br/HV1992.htm">Unnumbered decree</a> (1992-10-16)
+# Unnumbered decree <http://pcdsh01.on.br/HV1992.htm> (1992-10-16)
 # adopted by same states.
 Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV942.htm">942</a> (1993-09-28)
+# Decree 942 <http://pcdsh01.on.br/HV942.htm> (1993-09-28)
 # adopted by same states, plus AM.
-# Decree <a href="http://pcdsh01.on.br/HV1252.htm">1,252</a> (1994-09-22;
+# Decree 1,252 <http://pcdsh01.on.br/HV1252.htm> (1994-09-22;
 # web page corrected 2004-01-07) adopted by same states, minus AM.
-# Decree <a href="http://pcdsh01.on.br/HV1636.htm">1,636</a> (1995-09-14)
+# Decree 1,636 <http://pcdsh01.on.br/HV1636.htm> (1995-09-14)
 # adopted by same states, plus MT and TO.
-# Decree <a href="http://pcdsh01.on.br/HV1674.htm">1,674</a> (1995-10-13)
+# Decree 1,674 <http://pcdsh01.on.br/HV1674.htm> (1995-10-13)
 # adds AL, SE.
 Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
 Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
 Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV2000.htm">2,000</a> (1996-09-04)
+# Decree 2,000 <http://pcdsh01.on.br/HV2000.htm> (1996-09-04)
 # adopted by same states, minus AL, SE.
 Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
 Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
@@ -975,53 +915,51 @@
 #
 # Decree 2,317 (1997-09-04), adopted by same states.
 Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/figuras/HV2495.JPG">2,495</a>
+# Decree 2,495 <http://pcdsh01.on.br/figuras/HV2495.JPG>
 # (1998-02-10)
 Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/figuras/Hv98.jpg">2,780</a> (1998-09-11)
+# Decree 2,780 <http://pcdsh01.on.br/figuras/Hv98.jpg> (1998-09-11)
 # adopted by the same states as before.
 Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
 Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/figuras/HV3150.gif">3,150</a>
+# Decree 3,150 <http://pcdsh01.on.br/figuras/HV3150.gif>
 # (1999-08-23) adopted by same states.
-# Decree <a href="http://pcdsh01.on.br/DecHV99.gif">3,188</a> (1999-09-30)
+# Decree 3,188 <http://pcdsh01.on.br/DecHV99.gif> (1999-09-30)
 # adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
 Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
 Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/DEC3592.htm">3,592</a> (2000-09-06)
+# Decree 3,592 <http://pcdsh01.on.br/DEC3592.htm> (2000-09-06)
 # adopted by the same states as before.
-# Decree <a href="http://pcdsh01.on.br/Dec3630.jpg">3,630</a> (2000-10-13)
+# Decree 3,630 <http://pcdsh01.on.br/Dec3630.jpg> (2000-10-13)
 # repeals DST in PE and RR, effective 2000-10-15 00:00.
-# Decree <a href="http://pcdsh01.on.br/Dec3632.jpg">3,632</a> (2000-10-17)
+# Decree 3,632 <http://pcdsh01.on.br/Dec3632.jpg> (2000-10-17)
 # repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
-# Decree <a href="http://pcdsh01.on.br/figuras/HV3916.gif">3,916</a>
+# Decree 3,916 <http://pcdsh01.on.br/figuras/HV3916.gif>
 # (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
 Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
 Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
 # Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
-# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2002/D4399.htm">4,399</a>
+# 4,399 <http://www.presidencia.gov.br/CCIVIL/decreto/2002/D4399.htm>
 Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
 # Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
-# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2003/D4844.htm">4,844</a>
+# 4,844 <http://www.presidencia.gov.br/CCIVIL/decreto/2003/D4844.htm>
 Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
 # Decree 5,223 (2004-10-01) reestablishes DST in MT.
-# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2004-2006/2004/Decreto/D5223.htm">5,223</a>
+# 5,223 <http://www.planalto.gov.br/ccivil_03/_Ato2004-2006/2004/Decreto/D5223.htm>
 Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/DecHV5539.gif">5,539</a> (2005-09-19),
+# Decree 5,539 <http://pcdsh01.on.br/DecHV5539.gif> (2005-09-19),
 # adopted by the same states as before.
 Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/DecHV5920.gif">5,920</a> (2006-10-03),
+# Decree 5,920 <http://pcdsh01.on.br/DecHV5920.gif> (2006-10-03),
 # adopted by the same states as before.
 Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
 Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/DecHV6212.gif">6,212</a> (2007-09-26),
+# Decree 6,212 <http://pcdsh01.on.br/DecHV6212.gif> (2007-09-26),
 # adopted by the same states as before.
 Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
 # From Frederico A. C. Neves (2008-09-10):
 # According to this decree
-# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm">
 # http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
-# </a>
 # [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
 # 3rd Feb Sunday. There is an exception on the return date when this is
 # the Carnival Sunday then the return date will be the next Sunday...
@@ -1056,29 +994,29 @@
 			-2:00	Brazil	FN%sT	2002 Oct  1
 			-2:00	-	FNT
 # Other Atlantic islands have no permanent settlement.
-# These include Trindade and Martin Vaz (administratively part of ES),
-# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
+# These include Trindade and Martim Vaz (administratively part of ES),
+# Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE).
 # Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
 # it also included the Penedos.
 #
-# Amapa (AP), east Para (PA)
-# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
-# The division between east and west Para is the river Xingu.
+# Amapá (AP), east Pará (PA)
+# East Pará includes Belém, Marabá, Serra Norte, and São Félix do Xingu.
+# The division between east and west Pará is the river Xingu.
 # In the north a very small part from the river Javary (now Jari I guess,
-# the border with Amapa) to the Amazon, then to the Xingu.
+# the border with Amapá) to the Amazon, then to the Xingu.
 Zone America/Belem	-3:13:56 -	LMT	1914
 			-3:00	Brazil	BR%sT	1988 Sep 12
 			-3:00	-	BRT
 #
-# west Para (PA)
-# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+# west Pará (PA)
+# West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém.
 Zone America/Santarem	-3:38:48 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
-			-4:00	-	AMT	2008 Jun 24 00:00
+			-4:00	-	AMT	2008 Jun 24  0:00
 			-3:00	-	BRT
 #
-# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
-# Paraiba (PB)
+# Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN),
+# Paraíba (PB)
 Zone America/Fortaleza	-2:34:00 -	LMT	1914
 			-3:00	Brazil	BR%sT	1990 Sep 17
 			-3:00	-	BRT	1999 Sep 30
@@ -1125,11 +1063,11 @@
 			-3:00	Brazil	BR%sT	2012 Oct 21
 			-3:00	-	BRT
 #
-# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
-# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Goiás (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR),
 # Santa Catarina (SC), Rio Grande do Sul (RS)
 Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
-			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
+			-3:00	Brazil	BR%sT	1963 Oct 23  0:00
 			-3:00	1:00	BRST	1964
 			-3:00	Brazil	BR%sT
 #
@@ -1143,7 +1081,7 @@
 			-4:00	-	AMT	2004 Oct  1
 			-4:00	Brazil	AM%sT
 #
-# Rondonia (RO)
+# Rondônia (RO)
 Zone America/Porto_Velho -4:15:36 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
 			-4:00	-	AMT
@@ -1155,7 +1093,7 @@
 			-4:00	Brazil	AM%sT	2000 Oct 15
 			-4:00	-	AMT
 #
-# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
+# east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto
 # The great circle line from Tabatinga to Porto Acre divides
 # east from west Amazonas.
 Zone America/Manaus	-4:00:04 -	LMT	1914
@@ -1165,19 +1103,19 @@
 			-4:00	-	AMT
 #
 # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
-#	Eirunepe, Envira, Ipixuna
+#	Eirunepé, Envira, Ipixuna
 Zone America/Eirunepe	-4:39:28 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
 			-5:00	-	ACT	1993 Sep 28
 			-5:00	Brazil	AC%sT	1994 Sep 22
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 #
 # Acre (AC)
 Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 
@@ -1198,66 +1136,54 @@
 # From Oscar van Vlijmen (2006-10-08):
 # http://www.horaoficial.cl/cambio.htm
 
-# From Jesper Norgaard Welen (2006-10-08):
+# From Jesper Nørgaard Welen (2006-10-08):
 # I think that there are some obvious mistakes in the suggested link
 # from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
 # ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
 # (they should have been 1990-09-15 and 1990-09-16 respectively), but
 # anyhow it clears up some doubts too.
 
-# From Paul Eggert (2006-12-27):
-# The following data for Chile and America/Santiago are from
+# From Paul Eggert (2014-08-12):
+# The following data entries for Chile and America/Santiago are from
 # <http://www.horaoficial.cl/horaof.htm> (2006-09-20), transcribed by
-# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
+# Jesper Nørgaard Welen.  The data entries for Pacific/Easter are from Shanks
 # & Pottenger, except with DST transitions after 1932 cloned from
-# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
+# America/Santiago.  The pre-1980 Pacific/Easter data entries are dubious,
 # but we have no other source.
 
-# From German Poo-Caaman~o (2008-03-03):
+# From Germán Poo-Caamaño (2008-03-03):
 # Due to drought, Chile extends Daylight Time in three weeks.  This
 # is one-time change (Saturday 3/29 at 24:00 for America/Santiago
 # and Saturday 3/29 at 22:00 for Pacific/Easter)
 # The Supreme Decree is located at
-# <a href="http://www.shoa.cl/servicios/supremo316.pdf">
 # http://www.shoa.cl/servicios/supremo316.pdf
-# </a>
 # and the instructions for 2008 are located in:
-# <a href="http://www.horaoficial.cl/cambio.htm">
 # http://www.horaoficial.cl/cambio.htm
-# </a>.
 
-# From Jose Miguel Garrido (2008-03-05):
+# From José Miguel Garrido (2008-03-05):
 # ...
 # You could see the announces of the change on
-# <a href="http://www.shoa.cl/noticias/2008/04hora/hora.htm">
 # http://www.shoa.cl/noticias/2008/04hora/hora.htm
-# </a>.
 
 # From Angel Chiang (2010-03-04):
 # Subject: DST in Chile exceptionally extended to 3 April due to earthquake
-# <a href="http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098">
 # http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
-# </a>
 # (in Spanish, last paragraph).
 #
 # This is breaking news. There should be more information available later.
 
-# From Arthur Daivd Olson (2010-03-06):
+# From Arthur David Olson (2010-03-06):
 # Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
 
-# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
+# From Glenn Eychaner (2011-03-02):
 # It appears that the Chilean government has decided to postpone the
 # change from summer time to winter time again, by three weeks to April
 # 2nd:
-# <a href="http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651">
 # http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
-# </a>
 #
 # This is not yet reflected in the official "cambio de hora" site, but
 # probably will be soon:
-# <a href="http://www.horaoficial.cl/cambio.htm">
 # http://www.horaoficial.cl/cambio.htm
-# </a>
 
 # From Arthur David Olson (2011-03-02):
 # The emol.com article mentions a water shortage as the cause of the
@@ -1265,9 +1191,7 @@
 
 # From Glenn Eychaner (2011-03-28):
 # The article:
-# <a href="http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}">
 # http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
-# </a>
 #
 # In English:
 # Chile's clocks will go back an hour this year on the 7th of May instead
@@ -1298,7 +1222,7 @@
 # start date is 2013-09-08 00:00....
 # http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm
 
-# From Jose Miguel Garrido (2014-02-19):
+# From José Miguel Garrido (2014-02-19):
 # Today appeared in the Diario Oficial a decree amending the time change
 # dates to 2014.
 # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
@@ -1352,7 +1276,7 @@
 # (1996-09) says 1998-03-08.  Ignore these.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santiago	-4:42:46 -	LMT	1890
-			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
+			-4:42:46 -	SMT	1910        # Santiago Mean Time
 			-5:00	-	CLT	1916 Jul  1 # Chile Time
 			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
 			-4:00	-	CLT	1919 Jul  1 # Chile Time
@@ -1361,16 +1285,16 @@
 			-4:00	Chile	CL%sT
 Zone Pacific/Easter	-7:17:44 -	LMT	1890
 			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
-			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
+			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter Time
 			-6:00	Chile	EAS%sT
 #
-# Sala y Gomez Island is like Pacific/Easter.
-# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
-# San Felix, and Antarctic bases, are like America/Santiago.
+# Salas y Gómez Island is uninhabited.
+# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
+# and Antarctic bases, are like America/Santiago.
 
 # Colombia
 
-# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest.  He writes,
+# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest.  He writes,
 # "A variation of fifteen minutes in the public clocks of Bogota is not rare."
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1378,37 +1302,37 @@
 Rule	CO	1993	only	-	Apr	 4	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
-			-4:56:16 -	BMT	1914 Nov 23 # Bogota Mean Time
+			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
 			-5:00	CO	CO%sT	# Colombia Time
 # Malpelo, Providencia, San Andres
 # no information; probably like America/Bogota
 
-# Curacao
+# Curaçao
 
-# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
+# Milne gives 4:35:46.9 for Curaçao mean time; round to nearest.
 #
 # From Paul Eggert (2006-03-22):
 # Shanks & Pottenger say that The Bottom and Philipsburg have been at
 # -4:00 since standard time was introduced on 1912-03-02; and that
 # Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
 # 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
-# Saba Island has been like Curacao.
+# Saba Island has been like Curaçao.
 # This all predates our 1970 cutoff, though.
 #
-# By July 2007 Curacao and St Maarten are planned to become
+# By July 2007 Curaçao and St Maarten are planned to become
 # associated states within the Netherlands, much like Aruba;
 # Bonaire, Saba and St Eustatius would become directly part of the
 # Netherlands as Kingdom Islands.  This won't affect their time zones
 # though, as far as we know.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12	# Willemstad
+Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
 			-4:30	-	ANT	1965 # Netherlands Antilles Time
 			-4:00	-	AST
 
 # From Arthur David Olson (2011-06-15):
 # use links for places with new iso3166 codes.
-# The name "Lower Prince's Quarter" is both longer than fourteen charaters
+# The name "Lower Prince's Quarter" is both longer than fourteen characters
 # and contains an apostrophe; use "Lower_Princes" below.
 
 Link	America/Curacao	America/Lower_Princes	# Sint Maarten
@@ -1416,7 +1340,7 @@
 
 # Ecuador
 #
-# Milne says the Sentral and South American Telegraph Company used -5:24:15.
+# Milne says the Central and South American Telegraph Company used -5:24:15.
 #
 # From Paul Eggert (2007-03-04):
 # Apparently Ecuador had a failed experiment with DST in 1992.
@@ -1427,10 +1351,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guayaquil	-5:19:20 -	LMT	1890
 			-5:14:00 -	QMT	1931 # Quito Mean Time
-			-5:00	-	ECT	     # Ecuador Time
+			-5:00	-	ECT	# Ecuador Time
 Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 			-5:00	-	ECT	1986
-			-6:00	-	GALT	     # Galapagos Time
+			-6:00	-	GALT	# Galápagos Time
 
 # Falklands
 
@@ -1439,7 +1363,7 @@
 # the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
 
 # From Falkland Islands Government Office, London (2001-01-22)
-# via Jesper Norgaard:
+# via Jesper Nørgaard:
 # ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
 # April 2001 and advance one hour to summer time at 2 am on Sunday 2
 # September.  It is anticipated that the clocks will revert back at 2
@@ -1488,9 +1412,7 @@
 # daylight saving time.
 #
 # One source:
-# <a href="http://www.falklandnews.com/public/story.cfm?get=5914&source=3">
 # http://www.falklandnews.com/public/story.cfm?get=5914&source=3
-# </a>
 #
 # We have gotten this confirmed by a clerk of the legislative assembly:
 # Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
@@ -1531,10 +1453,10 @@
 Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
-			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
-			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
+			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
+			-4:00	Falk	FK%sT	1983 May    # Falkland Is Time
 			-3:00	Falk	FK%sT	1985 Sep 15
-			-4:00	Falk	FK%sT	2010 Sep 5 02:00
+			-4:00	Falk	FK%sT	2010 Sep  5  2:00
 			-3:00	-	FKST
 
 # French Guiana
@@ -1545,7 +1467,7 @@
 
 # Guyana
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
+Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
 			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
 			-3:45	-	GYT	1975 Jul 31 # Guyana Time
 			-3:00	-	GYT	1991
@@ -1555,8 +1477,8 @@
 # Paraguay
 #
 # From Paul Eggert (2006-03-22):
-# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
-# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
+# Shanks & Pottenger say that spring transitions are 01:00 -> 02:00,
+# and autumn transitions are 00:00 -> 23:00.  Go with pre-1999
 # editions of Shanks, and with the IATA, who say transitions occur at 00:00.
 #
 # From Waldemar Villamayor-Venialbo (2013-09-20):
@@ -1582,9 +1504,8 @@
 # (10-01).
 #
 # Translated by Gwillim Law (2001-02-27) from
-# <a href="http://www.diarionoticias.com.py/011000/nacional/naciona1.htm">
-# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
-# </a>:
+# Noticias, a daily paper in Asunción, Paraguay (2000-10-01):
+# http://www.diarionoticias.com.py/011000/nacional/naciona1.htm
 # Starting at 0:00 today, the clock will be set forward 60 minutes, in
 # fulfillment of Decree No. 7,273 of the Executive Power....  The time change
 # system has been operating for several years.  Formerly there was a separate
@@ -1605,21 +1526,18 @@
 Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
 Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
 #
-# From Jesper Norgaard Welen (2005-01-02):
+# From Jesper Nørgaard Welen (2005-01-02):
 # There are several sources that claim that Paraguay made
 # a timezone rule change in autumn 2004.
 # From Steffen Thorsen (2005-01-05):
 # Decree 1,867 (2004-03-05)
-# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
-# <http://www.presidencia.gov.py/decretos/D1867.pdf>
+# From Carlos Raúl Perasso via Jesper Nørgaard Welen (2006-10-13)
+# http://www.presidencia.gov.py/decretos/D1867.pdf
 Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
 Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
-# From Carlos Raul Perasso (2010-02-18):
-# By decree number 3958 issued yesterday (
-# <a href="http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf">
+# From Carlos Raúl Perasso (2010-02-18):
+# By decree number 3958 issued yesterday
 # http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
-# </a>
-# )
 # Paraguay changes its DST schedule, postponing the March rule to April and
 # modifying the October date. The decree reads:
 # ...
@@ -1635,25 +1553,25 @@
 # Paraguay will end DST on 2013-03-24 00:00....
 # http://www.ande.gov.py/interna.php?id=1075
 #
-# From Carlos Raul Perasso (2013-03-15):
+# From Carlos Raúl Perasso (2013-03-15):
 # The change in Paraguay is now final.  Decree number 10780
 # http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf
-# From Carlos Raul Perasso (2014-02-28):
+# From Carlos Raúl Perasso (2014-02-28):
 # Decree 1264 can be found at:
 # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
 Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Asuncion	-3:50:40 -	LMT	1890
-			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
-			-4:00	-	PYT	1972 Oct # Paraguay Time
+			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
+			-4:00	-	PYT	1972 Oct    # Paraguay Time
 			-3:00	-	PYT	1974 Apr
 			-4:00	Para	PY%sT
 
 # Peru
 #
-# <a href="news:xrGmb.39935$gA1.13896113@news4.srv.hcvlny.cv.net">
-# From Evelyn C. Leeper via Mark Brader (2003-10-26):</a>
+# From Evelyn C. Leeper via Mark Brader (2003-10-26)
+# <news:xrGmb.39935$gA1.13896113@news4.srv.hcvlny.cv.net>:
 # When we were in Peru in 1985-1986, they apparently switched over
 # sometime between December 29 and January 3 while we were on the Amazon.
 #
@@ -1679,7 +1597,7 @@
 
 # South Georgia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
+Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
 			-2:00	-	GST	# South Georgia Time
 
 # South Sandwich Is
@@ -1689,9 +1607,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Paramaribo	-3:40:40 -	LMT	1911
 			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
-			-3:40:36 -	PMT	1945 Oct # The capital moved?
+			-3:40:36 -	PMT	1945 Oct    # The capital moved?
 			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
-			-3:30	-	SRT	1984 Oct # Suriname Time
+			-3:30	-	SRT	1984 Oct    # Suriname Time
 			-3:00	-	SRT
 
 # Trinidad and Tobago
@@ -1706,7 +1624,7 @@
 Link America/Port_of_Spain America/Guadeloupe
 Link America/Port_of_Spain America/Marigot	# St Martin (French part)
 Link America/Port_of_Spain America/Montserrat
-Link America/Port_of_Spain America/St_Barthelemy
+Link America/Port_of_Spain America/St_Barthelemy # St Barthélemy
 Link America/Port_of_Spain America/St_Kitts	# St Kitts & Nevis
 Link America/Port_of_Spain America/St_Lucia
 Link America/Port_of_Spain America/St_Thomas	# Virgin Islands (US)
@@ -1765,7 +1683,7 @@
 Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
 Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
 # From Eduardo Cota (2004-09-20):
-# The uruguayan government has decreed a change in the local time....
+# The Uruguayan government has decreed a change in the local time....
 # http://www.presidencia.gub.uy/decretos/2004091502.htm
 Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
 # From Steffen Thorsen (2005-03-11):
@@ -1779,14 +1697,14 @@
 # 02:00 local time, official time in Uruguay will be at GMT -2.
 Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
 Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
-# From Jesper Norgaard Welen (2006-09-06):
+# From Jesper Nørgaard Welen (2006-09-06):
 # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
 Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
 Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
-			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
-			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
+			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
+			-3:30	Uruguay	UY%sT	1942 Dec 14 # Uruguay Time
 			-3:00	Uruguay	UY%sT
 
 # Venezuela
@@ -1794,14 +1712,14 @@
 # From John Stainforth (2007-11-28):
 # ... the change for Venezuela originally expected for 2007-12-31 has
 # been brought forward to 2007-12-09.  The official announcement was
-# published today in the "Gaceta Oficial de la Republica Bolivariana
-# de Venezuela, numero 38.819" (official document for all laws or
+# published today in the "Gaceta Oficial de la República Bolivariana
+# de Venezuela, número 38.819" (official document for all laws or
 # resolution publication)
 # http://www.globovision.com/news.php?nid=72208
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
-			-4:30	-	VET	1965	     # Venezuela Time
-			-4:00	-	VET	2007 Dec  9 03:00
+			-4:30	-	VET	1965        # Venezuela Time
+			-4:00	-	VET	2007 Dec  9  3:00
 			-4:30	-	VET
--- a/jdk/make/data/tzdata/systemv	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/systemv	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/make/data/tzdata/zone.tab	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/make/data/tzdata/zone.tab	Wed Jul 05 20:00:59 2017 +0200
@@ -21,39 +21,27 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# TZ zone descriptions
+# tz zone descriptions (deprecated version)
 #
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-08-14):
-#
-# This file contains a table where each row stands for an area that is
-# the intersection of a region identified by a country code and of a
-# zone where civil clocks have agreed since 1970.  The columns of the
-# table are as follows:
+# From Paul Eggert (2014-07-31):
+# This file is intended as a backward-compatibility aid for older programs.
+# New programs should use zone1970.tab.  This file is like zone1970.tab (see
+# zone1970.tab's comments), but with the following additional restrictions:
 #
-# 1.  ISO 3166 2-character country code.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the area's principal location
-#     in ISO 6709 sign-degrees-minutes-seconds format,
-#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
-#     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the 'Theory' file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
-#     table, with column 1 being duplicated.
-# 4.  Comments; present if and only if the country has multiple rows.
+# 1.  This file contains only ASCII characters.
+# 2.  The first data column contains exactly one country code.
 #
-# Columns are separated by a single tab.
-# The table is sorted first by country, then an order within the country that
-# (1) makes some geographical sense, and
-# (2) puts the most populous areas first, where that does not contradict (1).
-#
-# Lines beginning with '#' are comments.
+# Because of (2), each row stands for an area that is the intersection
+# of a region identified by a country code and of a zone where civil
+# clocks have agreed since 1970; this is a narrower definition than
+# that of zone1970.tab.
 #
 # This table is intended as an aid for users, to help them select time
-# zone data appropriate for their practical needs.  It is not intended
-# to take or endorse any position on legal or territorial claims.
+# zone data entries appropriate for their practical needs.  It is not
+# intended to take or endorse any position on legal or territorial claims.
 #
 #country-
 #code	coordinates	TZ			comments
@@ -72,7 +60,7 @@
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
 AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
-AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
+AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Adelie Land
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-720041+0023206	Antarctica/Troll	Troll Station, Queen Maud Land
 AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
@@ -151,7 +139,7 @@
 CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
 CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
 CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
-CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
+CA	+744144-0944945	America/Resolute	Central Time - Resolute, Nunavut
 CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
 CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
 CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
@@ -176,13 +164,10 @@
 CI	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most locations
-CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
+CL	-2709-10926	Pacific/Easter	Easter Island
 CM	+0403+00942	Africa/Douala
-CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
-CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
-CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
-CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
-CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
+CN	+3114+12128	Asia/Shanghai	Beijing Time
+CN	+4348+08735	Asia/Urumqi	Xinjiang Time
 CO	+0436-07405	America/Bogota
 CR	+0956-08405	America/Costa_Rica
 CU	+2308-08222	America/Havana
@@ -364,24 +349,26 @@
 RO	+4426+02606	Europe/Bucharest
 RS	+4450+02030	Europe/Belgrade
 RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
-RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
+RU	+554521+0373704	Europe/Moscow	Moscow+00 - west Russia
+RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
 RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
-RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
-RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
+RU	+5312+05009	Europe/Samara	Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia
 RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
 RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
 RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
-RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
+RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo
 RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
 RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
+RU	+5203+11328	Asia/Chita	Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky
 RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
 RU	+623923+1353314	Asia/Khandyga	Moscow+06 - Tomponsky, Ust-Maysky
 RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
 RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
 RU	+643337+1431336	Asia/Ust-Nera	Moscow+07 - Oymyakonsky
-RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
-RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
-RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
+RU	+5934+15048	Asia/Magadan	Moscow+08 (Moscow+07 after 2014-10-26) - Magadan
+RU	+6728+15343	Asia/Srednekolymsk	Moscow+08 - E Sakha, N Kuril Is
+RU	+5301+15839	Asia/Kamchatka	Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka
+RU	+6445+17729	Asia/Anadyr	Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea
 RW	-0157+03004	Africa/Kigali
 SA	+2438+04643	Asia/Riyadh
 SB	-0932+16012	Pacific/Guadalcanal
@@ -448,13 +435,13 @@
 US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
 US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona (except Navajo)
 US	+340308-1181434	America/Los_Angeles	Pacific Time
+US	+550737-1313435	America/Metlakatla	Pacific Standard Time - Annette Island, Alaska
 US	+611305-1495401	America/Anchorage	Alaska Time
 US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
 US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
 US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
 US	+643004-1652423	America/Nome	Alaska Time - west Alaska
 US	+515248-1763929	America/Adak	Aleutian Islands
-US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
 US	+211825-1575130	Pacific/Honolulu	Hawaii
 UY	-3453-05611	America/Montevideo
 UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
--- a/jdk/src/java.base/share/classes/java/lang/Integer.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java	Wed Jul 05 20:00:59 2017 +0200
@@ -595,37 +595,6 @@
     /**
      * Parses the {@link CharSequence} argument as a signed {@code int} in the
      * specified {@code radix}, beginning at the specified {@code beginIndex}
-     * and extending to the end of the sequence.
-     *
-     * <p>The method does not take steps to guard against the
-     * {@code CharSequence} being mutated while parsing.
-     *
-     * @param      s   the {@code CharSequence} containing the {@code int}
-     *                  representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
-     * @param      beginIndex   the beginning index, inclusive.
-     * @return     the signed {@code int} represented by the subsequence in
-     *             the specified radix.
-     * @throws     NullPointerException  if {@code s} is null.
-     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
-     *             negative, or if {@code beginIndex} is greater than
-     *             {@code s.length()}.
-     * @throws     NumberFormatException  if the {@code CharSequence} does not
-     *             contain a parsable {@code int} in the specified
-     *             {@code radix}, or if {@code radix} is either smaller than
-     *             {@link java.lang.Character#MIN_RADIX} or larger than
-     *             {@link java.lang.Character#MAX_RADIX}.
-     * @since  1.9
-     */
-    public static int parseInt(CharSequence s, int radix, int beginIndex)
-                throws NumberFormatException {
-        // forces an implicit null check of s
-        return parseInt(s, radix, beginIndex, s.length());
-    }
-
-    /**
-     * Parses the {@link CharSequence} argument as a signed {@code int} in the
-     * specified {@code radix}, beginning at the specified {@code beginIndex}
      * and extending to {@code endIndex - 1}.
      *
      * <p>The method does not take steps to guard against the
@@ -633,9 +602,9 @@
      *
      * @param      s   the {@code CharSequence} containing the {@code int}
      *                  representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
      * @param      beginIndex   the beginning index, inclusive.
      * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
      * @return     the signed {@code int} represented by the subsequence in
      *             the specified radix.
      * @throws     NullPointerException  if {@code s} is null.
@@ -650,7 +619,7 @@
      *             {@link java.lang.Character#MAX_RADIX}.
      * @since  1.9
      */
-    public static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex)
+    public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
                 throws NumberFormatException {
         s = Objects.requireNonNull(s);
 
@@ -690,7 +659,7 @@
             int result = 0;
             while (i < endIndex) {
                 // Accumulating negatively avoids surprises near MAX_VALUE
-                int digit = Character.digit(s.charAt(i++), radix);
+                int digit = Character.digit(s.charAt(i), radix);
                 if (digit < 0 || result < multmin) {
                     throw NumberFormatException.forCharSequence(s, beginIndex,
                             endIndex, i);
@@ -700,6 +669,7 @@
                     throw NumberFormatException.forCharSequence(s, beginIndex,
                             endIndex, i);
                 }
+                i++;
                 result -= digit;
             }
             return negative ? result : -result;
@@ -808,37 +778,6 @@
     /**
      * Parses the {@link CharSequence} argument as an unsigned {@code int} in
      * the specified {@code radix}, beginning at the specified
-     * {@code beginIndex} and extending to the end of the sequence.
-     *
-     * <p>The method does not take steps to guard against the
-     * {@code CharSequence} being mutated while parsing.
-     *
-     * @param      s   the {@code CharSequence} containing the unsigned
-     *                 {@code int} representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
-     * @param      beginIndex   the beginning index, inclusive.
-     * @return     the unsigned {@code int} represented by the subsequence in
-     *             the specified radix.
-     * @throws     NullPointerException  if {@code s} is null.
-     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
-     *             negative, or if {@code beginIndex} is greater than
-     *             {@code s.length()}.
-     * @throws     NumberFormatException  if the {@code CharSequence} does not
-     *             contain a parsable unsigned {@code int} in the specified
-     *             {@code radix}, or if {@code radix} is either smaller than
-     *             {@link java.lang.Character#MIN_RADIX} or larger than
-     *             {@link java.lang.Character#MAX_RADIX}.
-     * @since  1.9
-     */
-    public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex)
-                throws NumberFormatException {
-        // forces an implicit null check of s
-        return parseUnsignedInt(s, radix, beginIndex, s.length());
-    }
-
-    /**
-     * Parses the {@link CharSequence} argument as an unsigned {@code int} in
-     * the specified {@code radix}, beginning at the specified
      * {@code beginIndex} and extending to {@code endIndex - 1}.
      *
      * <p>The method does not take steps to guard against the
@@ -846,9 +785,9 @@
      *
      * @param      s   the {@code CharSequence} containing the unsigned
      *                 {@code int} representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
      * @param      beginIndex   the beginning index, inclusive.
      * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
      * @return     the unsigned {@code int} represented by the subsequence in
      *             the specified radix.
      * @throws     NullPointerException  if {@code s} is null.
@@ -863,7 +802,7 @@
      *             {@link java.lang.Character#MAX_RADIX}.
      * @since  1.9
      */
-    public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex)
+    public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix)
                 throws NumberFormatException {
         s = Objects.requireNonNull(s);
 
@@ -881,9 +820,9 @@
             } else {
                 if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                         (radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits
-                    return parseInt(s, radix, start, start + len);
+                    return parseInt(s, start, start + len, radix);
                 } else {
-                    long ell = Long.parseLong(s, radix, start, start + len);
+                    long ell = Long.parseLong(s, start, start + len, radix);
                     if ((ell & 0xffff_ffff_0000_0000L) == 0) {
                         return (int) ell;
                     } else {
--- a/jdk/src/java.base/share/classes/java/lang/Long.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java	Wed Jul 05 20:00:59 2017 +0200
@@ -606,37 +606,6 @@
 
     /**
      * Parses the {@link CharSequence} argument as a signed {@code long} in
-     * the specified {@code radix}, beginning at the specified {@code beginIndex}
-     * and extending to the end of the sequence.
-     *
-     * <p>The method does not take steps to guard against the
-     * {@code CharSequence} being mutated while parsing.
-     *
-     * @param      s   the {@code CharSequence} containing the {@code long}
-     *                  representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
-     * @param      beginIndex   the beginning index, inclusive.
-     * @return     the signed {@code long} represented by the subsequence in
-     *             the specified radix.
-     * @throws     NullPointerException  if {@code s} is null.
-     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
-     *             negative, or if {@code beginIndex} is greater than
-     *             {@code s.length()}.
-     * @throws     NumberFormatException  if the {@code CharSequence} does not
-     *             contain a parsable {@code long} in the specified
-     *             {@code radix}, or if {@code radix} is either smaller than
-     *             {@link java.lang.Character#MIN_RADIX} or larger than
-     *             {@link java.lang.Character#MAX_RADIX}.
-     * @since  1.9
-     */
-    public static long parseLong(CharSequence s, int radix, int beginIndex)
-            throws NumberFormatException {
-        // forces a null check of s
-        return parseLong(s, radix, beginIndex, s.length());
-    }
-
-    /**
-     * Parses the {@link CharSequence} argument as a signed {@code long} in
      * the specified {@code radix}, beginning at the specified
      * {@code beginIndex} and extending to {@code endIndex - 1}.
      *
@@ -645,9 +614,9 @@
      *
      * @param      s   the {@code CharSequence} containing the {@code long}
      *                  representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
      * @param      beginIndex   the beginning index, inclusive.
      * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
      * @return     the signed {@code long} represented by the subsequence in
      *             the specified radix.
      * @throws     NullPointerException  if {@code s} is null.
@@ -662,7 +631,7 @@
      *             {@link java.lang.Character#MAX_RADIX}.
      * @since  1.9
      */
-    public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex)
+    public static long parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
                 throws NumberFormatException {
         s = Objects.requireNonNull(s);
 
@@ -702,7 +671,7 @@
             long result = 0;
             while (i < endIndex) {
                 // Accumulating negatively avoids surprises near MAX_VALUE
-                int digit = Character.digit(s.charAt(i++), radix);
+                int digit = Character.digit(s.charAt(i), radix);
                 if (digit < 0 || result < multmin) {
                     throw NumberFormatException.forCharSequence(s, beginIndex,
                             endIndex, i);
@@ -712,6 +681,7 @@
                     throw NumberFormatException.forCharSequence(s, beginIndex,
                             endIndex, i);
                 }
+                i++;
                 result -= digit;
             }
             return negative ? result : -result;
@@ -811,7 +781,7 @@
                 }
 
                 // No need for range checks on len due to testing above.
-                long first = parseLong(s, radix, 0, len - 1);
+                long first = parseLong(s, 0, len - 1, radix);
                 int second = Character.digit(s.charAt(len - 1), radix);
                 if (second < 0) {
                     throw new NumberFormatException("Bad digit at end of " + s);
@@ -883,37 +853,6 @@
     /**
      * Parses the {@link CharSequence} argument as an unsigned {@code long} in
      * the specified {@code radix}, beginning at the specified
-     * {@code beginIndex} and extending to the end of the sequence.
-     *
-     * <p>The method does not take steps to guard against the
-     * {@code CharSequence} being mutated while parsing.
-     *
-     * @param      s   the {@code CharSequence} containing the unsigned
-     *                 {@code long} representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
-     * @param      beginIndex   the beginning index, inclusive.
-     * @return     the unsigned {@code long} represented by the subsequence in
-     *             the specified radix.
-     * @throws     NullPointerException  if {@code s} is null.
-     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
-     *             negative, or if {@code beginIndex} is greater than
-     *             {@code s.length()}.
-     * @throws     NumberFormatException  if the {@code CharSequence} does not
-     *             contain a parsable unsigned {@code long} in the specified
-     *             {@code radix}, or if {@code radix} is either smaller than
-     *             {@link java.lang.Character#MIN_RADIX} or larger than
-     *             {@link java.lang.Character#MAX_RADIX}.
-     * @since  1.9
-     */
-    public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex)
-                throws NumberFormatException {
-        // forces a null check of s
-        return parseUnsignedLong(s, radix, beginIndex, s.length());
-    }
-
-    /**
-     * Parses the {@link CharSequence} argument as an unsigned {@code long} in
-     * the specified {@code radix}, beginning at the specified
      * {@code beginIndex} and extending to {@code endIndex - 1}.
      *
      * <p>The method does not take steps to guard against the
@@ -921,9 +860,9 @@
      *
      * @param      s   the {@code CharSequence} containing the unsigned
      *                 {@code long} representation to be parsed
-     * @param      radix   the radix to be used while parsing {@code s}.
      * @param      beginIndex   the beginning index, inclusive.
      * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
      * @return     the unsigned {@code long} represented by the subsequence in
      *             the specified radix.
      * @throws     NullPointerException  if {@code s} is null.
@@ -938,7 +877,7 @@
      *             {@link java.lang.Character#MAX_RADIX}.
      * @since  1.9
      */
-    public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex)
+    public static long parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
                 throws NumberFormatException {
         s = Objects.requireNonNull(s);
 
@@ -955,11 +894,11 @@
             } else {
                 if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
                     (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
-                    return parseLong(s, radix, start, start + len);
+                    return parseLong(s, start, start + len, radix);
                 }
 
                 // No need for range checks on end due to testing above.
-                long first = parseLong(s, radix, start, start + len - 1);
+                long first = parseLong(s, start, start + len - 1, radix);
                 int second = Character.digit(s.charAt(start + len - 1), radix);
                 if (second < 0) {
                     throw new NumberFormatException("Bad digit at end of " +
--- a/jdk/src/java.base/share/classes/java/lang/String.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/String.java	Wed Jul 05 20:00:59 2017 +0200
@@ -2119,7 +2119,7 @@
      * @since 1.5
      */
     public boolean contains(CharSequence s) {
-        return indexOf(s.toString()) > -1;
+        return indexOf(s.toString()) >= 0;
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Wed Jul 05 20:00:59 2017 +0200
@@ -50,31 +50,31 @@
  *
  * All bound arguments are encapsulated in dedicated species.
  */
-/* non-public */ abstract class BoundMethodHandle extends MethodHandle {
+/*non-public*/ abstract class BoundMethodHandle extends MethodHandle {
 
-    /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
+    /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
         super(type, form);
+        assert(speciesData() == speciesData(form));
     }
 
     //
     // BMH API and internals
     //
 
-    static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
+    static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
         // for some type signatures, there exist pre-defined concrete BMH classes
         try {
             switch (xtype) {
             case L_TYPE:
-                if (true)  return bindSingle(type, form, x);  // Use known fast path.
-                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor[0].invokeBasic(type, form, x);
+                return bindSingle(type, form, x);  // Use known fast path.
             case I_TYPE:
-                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
+                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
             case J_TYPE:
-                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor[0].invokeBasic(type, form, (long) x);
+                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
             case F_TYPE:
-                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor[0].invokeBasic(type, form, (float) x);
+                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
             case D_TYPE:
-                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor[0].invokeBasic(type, form, (double) x);
+                return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
             default : throw newInternalError("unexpected xtype: " + xtype);
             }
         } catch (Throwable t) {
@@ -82,49 +82,61 @@
         }
     }
 
-    static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
-            return new Species_L(type, form, x);
+    /*non-public*/
+    LambdaFormEditor editor() {
+        return form.editor();
+    }
+
+    static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
+        return Species_L.make(type, form, x);
     }
 
-    MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) {
-        try {
-            switch (xtype) {
-            case L_TYPE: return copyWithExtendL(type, form, x);
-            case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
-            case J_TYPE: return copyWithExtendJ(type, form, (long) x);
-            case F_TYPE: return copyWithExtendF(type, form, (float) x);
-            case D_TYPE: return copyWithExtendD(type, form, (double) x);
-            }
-        } catch (Throwable t) {
-            throw newInternalError(t);
-        }
-        throw newInternalError("unexpected type: " + xtype);
+    @Override // there is a default binder in the super class, for 'L' types only
+    /*non-public*/
+    BoundMethodHandle bindArgumentL(int pos, Object value) {
+        return editor().bindArgumentL(this, pos, value);
+    }
+    /*non-public*/
+    BoundMethodHandle bindArgumentI(int pos, int value) {
+        return editor().bindArgumentI(this, pos, value);
+    }
+    /*non-public*/
+    BoundMethodHandle bindArgumentJ(int pos, long value) {
+        return editor().bindArgumentJ(this, pos, value);
+    }
+    /*non-public*/
+    BoundMethodHandle bindArgumentF(int pos, float value) {
+        return editor().bindArgumentF(this, pos, value);
+    }
+    /*non-public*/
+    BoundMethodHandle bindArgumentD(int pos, double value) {
+        return editor().bindArgumentD(this, pos, value);
     }
 
     @Override
-    MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
-        MethodType type = type().dropParameterTypes(pos, pos+1);
-        LambdaForm form = internalForm().bind(1+pos, speciesData());
-        return cloneExtend(type, form, basicType, value);
+    BoundMethodHandle rebind() {
+        if (!tooComplex()) {
+            return this;
+        }
+        return makeReinvoker(this);
     }
 
-    @Override
-    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
-        LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos + drops));
-        try {
-             return copyWith(srcType, form);
-         } catch (Throwable t) {
-             throw newInternalError(t);
-         }
+    private boolean tooComplex() {
+        return (fieldCount() > FIELD_COUNT_THRESHOLD ||
+                form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
     }
+    private static final int FIELD_COUNT_THRESHOLD = 12;      // largest convenient BMH field count
+    private static final int FORM_EXPRESSION_THRESHOLD = 24;  // largest convenient BMH expression count
 
-    @Override
-    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
-        try {
-             return copyWith(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
-         } catch (Throwable t) {
-             throw newInternalError(t);
-         }
+    /**
+     * A reinvoker MH has this form:
+     * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }}
+     */
+    static BoundMethodHandle makeReinvoker(MethodHandle target) {
+        LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
+                target, MethodTypeForm.LF_REBIND,
+                Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
+        return Species_L.make(target.type(), form, target);
     }
 
     /**
@@ -133,14 +145,22 @@
      */
     /*non-public*/ abstract SpeciesData speciesData();
 
+    /*non-public*/ static SpeciesData speciesData(LambdaForm form) {
+        Object c = form.names[0].constraint;
+        if (c instanceof SpeciesData)
+            return (SpeciesData) c;
+        // if there is no BMH constraint, then use the null constraint
+        return SpeciesData.EMPTY;
+    }
+
     /**
      * Return the number of fields in this BMH.  Equivalent to speciesData().fieldCount().
      */
     /*non-public*/ abstract int fieldCount();
 
     @Override
-    final Object internalProperties() {
-        return "/BMH="+internalValues();
+    Object internalProperties() {
+        return "\n& BMH="+internalValues();
     }
 
     @Override
@@ -178,15 +198,6 @@
     /*non-public*/ abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float  narg);
     /*non-public*/ abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg);
 
-    // The following is a grossly irregular hack:
-    @Override MethodHandle reinvokerTarget() {
-        try {
-            return (MethodHandle) arg(0);
-        } catch (Throwable ex) {
-            throw newInternalError(ex);
-        }
-    }
-
     //
     // concrete BMH classes required to close bootstrap loops
     //
@@ -198,8 +209,6 @@
             super(mt, lf);
             this.argL0 = argL0;
         }
-        // The following is a grossly irregular hack:
-        @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
         @Override
         /*non-public*/ SpeciesData speciesData() {
             return SPECIES_DATA;
@@ -219,7 +228,7 @@
         @Override
         /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
             try {
-                return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
+                return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
@@ -227,7 +236,7 @@
         @Override
         /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
             try {
-                return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
+                return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
@@ -235,7 +244,7 @@
         @Override
         /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
             try {
-                return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
+                return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
@@ -243,7 +252,7 @@
         @Override
         /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
             try {
-                return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
+                return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
@@ -251,7 +260,7 @@
         @Override
         /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
             try {
-                return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
+                return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
@@ -268,18 +277,20 @@
      * The fields are immutable; their values are fully specified at object construction.
      * Each BMH type supplies an array of getter functions which may be used in lambda forms.
      * A BMH is constructed by cloning a shorter BMH and adding one or more new field values.
-     * As a degenerate and common case, the "shorter BMH" can be missing, and contributes zero prior fields.
+     * The shortest possible BMH has zero fields; its class is SimpleMethodHandle.
+     * BMH species are not interrelated by subtyping, even though it would appear that
+     * a shorter BMH could serve as a supertype of a longer one which extends it.
      */
     static class SpeciesData {
-        final String                             typeChars;
-        final BasicType[]                        typeCodes;
-        final Class<? extends BoundMethodHandle> clazz;
+        private final String                             typeChars;
+        private final BasicType[]                        typeCodes;
+        private final Class<? extends BoundMethodHandle> clazz;
         // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
         // Therefore, we need a non-final link in the chain.  Use array elements.
-        final MethodHandle[]                     constructor;
-        final MethodHandle[]                     getters;
-        final NamedFunction[]                    nominalGetters;
-        final SpeciesData[]                      extensions;
+        @Stable private final MethodHandle[]             constructor;
+        @Stable private final MethodHandle[]             getters;
+        @Stable private final NamedFunction[]            nominalGetters;
+        @Stable private final SpeciesData[]              extensions;
 
         /*non-public*/ int fieldCount() {
             return typeCodes.length;
@@ -290,9 +301,14 @@
         /*non-public*/ char fieldTypeChar(int i) {
             return typeChars.charAt(i);
         }
-
+        Object fieldSignature() {
+            return typeChars;
+        }
+        public Class<? extends BoundMethodHandle> fieldHolder() {
+            return clazz;
+        }
         public String toString() {
-            return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+typeChars+"]";
+            return "SpeciesData<"+fieldSignature()+">";
         }
 
         /**
@@ -301,7 +317,20 @@
          * getter.
          */
         NamedFunction getterFunction(int i) {
-            return nominalGetters[i];
+            NamedFunction nf = nominalGetters[i];
+            assert(nf.memberDeclaringClassOrNull() == fieldHolder());
+            assert(nf.returnType() == fieldType(i));
+            return nf;
+        }
+
+        NamedFunction[] getterFunctions() {
+            return nominalGetters;
+        }
+
+        MethodHandle[] getterHandles() { return getters; }
+
+        MethodHandle constructor() {
+            return constructor[0];
         }
 
         static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
@@ -324,7 +353,7 @@
 
         private void initForBootstrap() {
             assert(!INIT_DONE);
-            if (constructor[0] == null) {
+            if (constructor() == null) {
                 String types = typeChars;
                 Factory.makeCtors(clazz, types, this.constructor);
                 Factory.makeGetters(clazz, types, this.getters);
@@ -508,19 +537,19 @@
          *         return new Species_LLI(mt, lf, argL0, argL1, argI2);
          *     }
          *     final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
-         *         return SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+         *         return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          *     final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
-         *         return SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+         *         return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          *     final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
-         *         return SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+         *         return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          *     final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
-         *         return SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+         *         return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          *     public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
-         *         return SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+         *         return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          * }
          * </pre>
@@ -575,16 +604,6 @@
             mv.visitMaxs(0, 0);
             mv.visitEnd();
 
-            // emit implementation of reinvokerTarget()
-            mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
-            mv.visitCode();
-            mv.visitVarInsn(ALOAD, 0);
-            mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG);
-            mv.visitTypeInsn(CHECKCAST, MH);
-            mv.visitInsn(ARETURN);
-            mv.visitMaxs(0, 0);
-            mv.visitEnd();
-
             // emit implementation of speciesData()
             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
             mv.visitCode();
@@ -653,16 +672,14 @@
                 char btChar = type.basicTypeChar();
                 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
                 mv.visitCode();
-                // return SPECIES_DATA.extendWith(t).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
+                // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg)
                 // obtain constructor
                 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
                 int iconstInsn = ICONST_0 + ord;
                 assert(iconstInsn <= ICONST_5);
                 mv.visitInsn(iconstInsn);
                 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false);
-                mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
-                mv.visitInsn(ICONST_0);
-                mv.visitInsn(AALOAD);
+                mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false);
                 // load mt, lf
                 mv.visitVarInsn(ALOAD, 1);
                 mv.visitVarInsn(ALOAD, 2);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java	Wed Jul 05 20:00:59 2017 +0200
@@ -102,7 +102,7 @@
      */
     /*package-private*/
     CallSite(MethodType type) {
-        target = type.invokers().uninitializedCallSite();
+        target = makeUninitializedCallSite(type);
     }
 
     /**
@@ -211,27 +211,40 @@
     public abstract MethodHandle dynamicInvoker();
 
     /*non-public*/ MethodHandle makeDynamicInvoker() {
-        MethodHandle getTarget = GET_TARGET.bindReceiver(this);
+        MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this);
         MethodHandle invoker = MethodHandles.exactInvoker(this.type());
         return MethodHandles.foldArguments(invoker, getTarget);
     }
 
     private static final MethodHandle GET_TARGET;
+    private static final MethodHandle THROW_UCS;
     static {
         try {
             GET_TARGET = IMPL_LOOKUP.
                 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+            THROW_UCS = IMPL_LOOKUP.
+                findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class));
         } catch (ReflectiveOperationException e) {
             throw newInternalError(e);
         }
     }
 
     /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
-    /*package-private*/
-    static Empty uninitializedCallSite() {
+    private static Object uninitializedCallSite(Object... ignore) {
         throw new IllegalStateException("uninitialized call site");
     }
 
+    private MethodHandle makeUninitializedCallSite(MethodType targetType) {
+        MethodType basicType = targetType.basicType();
+        MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS);
+        if (invoker == null) {
+            invoker = THROW_UCS.asType(basicType);
+            invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
+        }
+        // unchecked view is OK since no values will be received or returned
+        return invoker.viewAsType(targetType, false);
+    }
+
     // unsafe stuff:
     private static final long TARGET_OFFSET;
     static {
@@ -319,7 +332,7 @@
                 throw new ClassCastException("bootstrap method failed to produce a CallSite");
             }
             if (!site.getTarget().type().equals(type))
-                throw new WrongMethodTypeException("wrong type: "+site.getTarget());
+                throw wrongTargetType(site.getTarget(), type);
         } catch (Throwable ex) {
             BootstrapMethodError bex;
             if (ex instanceof BootstrapMethodError)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 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 java.lang.invoke;
+
+import java.util.Arrays;
+import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A method handle whose invocation behavior is determined by a target.
+ * The delegating MH itself can hold extra "intentions" beyond the simple behavior.
+ * @author jrose
+ */
+/*non-public*/
+abstract class DelegatingMethodHandle extends MethodHandle {
+    protected DelegatingMethodHandle(MethodHandle target) {
+        this(target.type(), target);
+    }
+
+    protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
+        super(type, chooseDelegatingForm(target));
+    }
+
+    /** Define this to extract the delegated target which supplies the invocation behavior. */
+    abstract protected MethodHandle getTarget();
+
+    @Override
+    abstract MethodHandle asTypeUncached(MethodType newType);
+
+    @Override
+    MemberName internalMemberName() {
+        return getTarget().internalMemberName();
+    }
+
+    @Override
+    boolean isInvokeSpecial() {
+        return getTarget().isInvokeSpecial();
+    }
+
+    @Override
+    Class<?> internalCallerClass() {
+        return getTarget().internalCallerClass();
+    }
+
+    @Override
+    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+        // FIXME: rethink 'copyWith' protocol; it is too low-level for use on all MHs
+        throw newIllegalArgumentException("do not use this");
+    }
+
+    @Override
+    String internalProperties() {
+        return "\n& Class="+getClass().getSimpleName()+
+               "\n& Target="+getTarget().debugString();
+    }
+
+    @Override
+    BoundMethodHandle rebind() {
+        return getTarget().rebind();
+    }
+
+    private static LambdaForm chooseDelegatingForm(MethodHandle target) {
+        if (target instanceof SimpleMethodHandle)
+            return target.internalForm();  // no need for an indirection
+        return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
+    }
+
+    /** Create a LF which simply reinvokes a target of the given basic type. */
+    static LambdaForm makeReinvokerForm(MethodHandle target,
+                                        int whichCache,
+                                        Object constraint,
+                                        NamedFunction getTargetFn) {
+        MethodType mtype = target.type().basicType();
+        boolean customized = (whichCache < 0 ||
+                mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
+        LambdaForm form;
+        if (!customized) {
+            form = mtype.form().cachedLambdaForm(whichCache);
+            if (form != null)  return form;
+        }
+        final int THIS_DMH    = 0;
+        final int ARG_BASE    = 1;
+        final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int NEXT_MH     = customized ? -1 : nameCursor++;
+        final int REINVOKE    = nameCursor++;
+        LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
+        assert(names.length == nameCursor);
+        names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
+        Object[] targetArgs;
+        if (customized) {
+            targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
+            names[REINVOKE] = new LambdaForm.Name(target, targetArgs);  // the invoker is the target itself
+        } else {
+            names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
+            targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
+            targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
+            names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
+        }
+        String debugString;
+        switch(whichCache) {
+            case MethodTypeForm.LF_REBIND:   debugString = "BMH.reinvoke"; break;
+            case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate";  break;
+            default:                         debugString = "MH.reinvoke";  break;
+        }
+        form = new LambdaForm(debugString, ARG_LIMIT, names);
+        if (!customized) {
+            form = mtype.form().setCachedLambdaForm(whichCache, form);
+        }
+        return form;
+    }
+
+    private static final NamedFunction NF_getTarget;
+    static {
+        try {
+            NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
+                                             .getDeclaredMethod("getTarget"));
+        } catch (ReflectiveOperationException ex) {
+            throw newInternalError(ex);
+        }
+    }
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Wed Jul 05 20:00:59 2017 +0200
@@ -59,6 +59,7 @@
             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
             if (m != null && m.isPublic()) {
+                assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
                 member = m;
             }
         }
@@ -126,60 +127,30 @@
     }
 
     @Override
+    BoundMethodHandle rebind() {
+        return BoundMethodHandle.makeReinvoker(this);
+    }
+
+    @Override
+    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+        assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
+        return new DirectMethodHandle(mt, lf, member);
+    }
+
+    @Override
     String internalProperties() {
-        return "/DMH="+member.toString();
+        return "\n& DMH.MN="+internalMemberName();
     }
 
     //// Implementation methods.
     @Override
-    MethodHandle viewAsType(MethodType newType) {
-        return new DirectMethodHandle(newType, form, member);
-    }
-    @Override
     @ForceInline
     MemberName internalMemberName() {
         return member;
     }
 
-    @Override
-    MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
-        // If the member needs dispatching, do so.
-        if (pos == 0 && basicType == L_TYPE) {
-            DirectMethodHandle concrete = maybeRebind(value);
-            if (concrete != null)
-                return concrete.bindReceiver(value);
-        }
-        return super.bindArgument(pos, basicType, value);
-    }
-
-    @Override
-    MethodHandle bindReceiver(Object receiver) {
-        // If the member needs dispatching, do so.
-        DirectMethodHandle concrete = maybeRebind(receiver);
-        if (concrete != null)
-            return concrete.bindReceiver(receiver);
-        return super.bindReceiver(receiver);
-    }
-
     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 
-    private DirectMethodHandle maybeRebind(Object receiver) {
-        if (receiver != null) {
-            switch (member.getReferenceKind()) {
-            case REF_invokeInterface:
-            case REF_invokeVirtual:
-                // Pre-dispatch the member.
-                Class<?> concreteClass = receiver.getClass();
-                MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
-                concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
-                if (concrete != null)
-                    return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete);
-                break;
-            }
-        }
-        return null;
-    }
-
     /**
      * Create a LF which can invoke the given method.
      * Cache and share this structure among all methods with
@@ -260,9 +231,10 @@
         } else {
             names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
         }
+        assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
         assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
-        int result = LambdaForm.LAST_RESULT;
+        int result = LAST_RESULT;
         if (doesAlloc) {
             assert(outArgs[outArgs.length-2] == names[NEW_OBJ]);  // got to move this one
             System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
@@ -277,6 +249,16 @@
         return lform;
     }
 
+    static Object findDirectMethodHandle(Name name) {
+        if (name.function == Lazy.NF_internalMemberName ||
+            name.function == Lazy.NF_internalMemberNameEnsureInit ||
+            name.function == Lazy.NF_constructorMethod) {
+            assert(name.arguments.length == 1);
+            return name.arguments[0];
+        }
+        return null;
+    }
+
     private static void maybeCompile(LambdaForm lform, MemberName m) {
         if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
             // Help along bootstrapping...
@@ -389,8 +371,8 @@
             return true;
         }
         @Override
-        MethodHandle viewAsType(MethodType newType) {
-            return new Special(newType, form, member);
+        MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+            return new Special(mt, lf, member);
         }
     }
 
@@ -407,8 +389,8 @@
             assert(initMethod.isResolved());
         }
         @Override
-        MethodHandle viewAsType(MethodType newType) {
-            return new Constructor(newType, form, member, initMethod, instanceClass);
+        MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+            return new Constructor(mt, lf, member, initMethod, instanceClass);
         }
     }
 
@@ -437,8 +419,8 @@
             return fieldType.cast(obj);
         }
         @Override
-        MethodHandle viewAsType(MethodType newType) {
-            return new Accessor(newType, form, member, fieldOffset);
+        MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+            return new Accessor(mt, lf, member, fieldOffset);
         }
     }
 
@@ -480,8 +462,8 @@
             return fieldType.cast(obj);
         }
         @Override
-        MethodHandle viewAsType(MethodType newType) {
-            return new StaticAccessor(newType, form, member, staticBase, staticOffset);
+        MethodHandle copyWith(MethodType mt, LambdaForm lf) {
+            return new StaticAccessor(mt, lf, member, staticBase, staticOffset);
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,21 +25,20 @@
 
 package java.lang.invoke;
 
-import sun.invoke.util.VerifyAccess;
-import static java.lang.invoke.LambdaForm.*;
-
-import sun.invoke.util.Wrapper;
-
 import java.io.*;
 import java.util.*;
+import java.lang.reflect.Modifier;
 
 import jdk.internal.org.objectweb.asm.*;
 
-import java.lang.reflect.*;
+import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.BasicType.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.LambdaForm.BasicType.*;
+
+import sun.invoke.util.VerifyAccess;
 import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
 import sun.reflect.misc.ReflectUtil;
 
 /**
@@ -74,7 +73,11 @@
     private final LambdaForm lambdaForm;
     private final String     invokerName;
     private final MethodType invokerType;
-    private final int[] localsMap;
+
+    /** Info about local variables in compiled lambda form */
+    private final int[]       localsMap;    // index
+    private final BasicType[] localTypes;   // basic type
+    private final Class<?>[]  localClasses; // type
 
     /** ASM bytecode generation. */
     private ClassWriter cw;
@@ -83,6 +86,7 @@
     private static final MemberName.Factory MEMBERNAME_FACTORY = MemberName.getFactory();
     private static final Class<?> HOST_CLASS = LambdaForm.class;
 
+    /** Main constructor; other constructors delegate to this one. */
     private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
                                      String className, String invokerName, MethodType invokerType) {
         if (invokerName.contains(".")) {
@@ -98,18 +102,26 @@
         this.lambdaForm = lambdaForm;
         this.invokerName = invokerName;
         this.invokerType = invokerType;
-        this.localsMap = new int[localsMapSize];
+        this.localsMap = new int[localsMapSize+1];
+        // last entry of localsMap is count of allocated local slots
+        this.localTypes = new BasicType[localsMapSize+1];
+        this.localClasses = new Class<?>[localsMapSize+1];
     }
 
+    /** For generating LambdaForm interpreter entry points. */
     private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
         this(null, invokerType.parameterCount(),
              className, invokerName, invokerType);
         // Create an array to map name indexes to locals indexes.
+        localTypes[localTypes.length - 1] = V_TYPE;
         for (int i = 0; i < localsMap.length; i++) {
             localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
+            if (i < invokerType.parameterCount())
+                localTypes[i] = basicType(invokerType.parameterType(i));
         }
     }
 
+    /** For generating customized code for a single LambdaForm. */
     private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
         this(form, form.names.length,
              className, form.debugName, invokerType);
@@ -117,7 +129,11 @@
         Name[] names = form.names;
         for (int i = 0, index = 0; i < localsMap.length; i++) {
             localsMap[i] = index;
-            index += names[i].type.basicTypeSlots();
+            if (i < names.length) {
+                BasicType type = names[i].type();
+                index += type.basicTypeSlots();
+                localTypes[i] = type;
+            }
         }
     }
 
@@ -148,7 +164,6 @@
 
     static void maybeDump(final String className, final byte[] classFile) {
         if (DUMP_CLASS_FILES) {
-            System.out.println("dump: " + className);
             java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<Void>() {
                 public Void run() {
@@ -156,6 +171,7 @@
                         String dumpName = className;
                         //dumpName = dumpName.replace('/', '-');
                         File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class");
+                        System.out.println("dump: " + dumpFile);
                         dumpFile.getParentFile().mkdirs();
                         FileOutputStream file = new FileOutputStream(dumpFile);
                         file.write(classFile);
@@ -204,7 +220,7 @@
 
     String constantPlaceholder(Object arg) {
         String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++;
-        if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + arg.toString() + ">>";  // debugging aid
+        if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>";  // debugging aid
         if (cpPatches.containsKey(cpPlaceholder)) {
             throw new InternalError("observed CP placeholder twice: " + cpPlaceholder);
         }
@@ -225,6 +241,17 @@
         return res;
     }
 
+    private static String debugString(Object arg) {
+        if (arg instanceof MethodHandle) {
+            MethodHandle mh = (MethodHandle) arg;
+            MemberName member = mh.internalMemberName();
+            if (member != null)
+                return member.toString();
+            return mh.debugString();
+        }
+        return arg.toString();
+    }
+
     /**
      * Extract the number of constant pool entries from a given class file.
      *
@@ -400,6 +427,64 @@
         emitStoreInsn(L_TYPE, index);
     }
 
+    private byte arrayTypeCode(Wrapper elementType) {
+        switch (elementType) {
+            case BOOLEAN: return Opcodes.T_BOOLEAN;
+            case BYTE:    return Opcodes.T_BYTE;
+            case CHAR:    return Opcodes.T_CHAR;
+            case SHORT:   return Opcodes.T_SHORT;
+            case INT:     return Opcodes.T_INT;
+            case LONG:    return Opcodes.T_LONG;
+            case FLOAT:   return Opcodes.T_FLOAT;
+            case DOUBLE:  return Opcodes.T_DOUBLE;
+            case OBJECT:  return 0; // in place of Opcodes.T_OBJECT
+            default:      throw new InternalError();
+        }
+    }
+
+    private int arrayInsnOpcode(byte tcode, int aaop) throws InternalError {
+        assert(aaop == Opcodes.AASTORE || aaop == Opcodes.AALOAD);
+        int xas;
+        switch (tcode) {
+            case Opcodes.T_BOOLEAN: xas = Opcodes.BASTORE; break;
+            case Opcodes.T_BYTE:    xas = Opcodes.BASTORE; break;
+            case Opcodes.T_CHAR:    xas = Opcodes.CASTORE; break;
+            case Opcodes.T_SHORT:   xas = Opcodes.SASTORE; break;
+            case Opcodes.T_INT:     xas = Opcodes.IASTORE; break;
+            case Opcodes.T_LONG:    xas = Opcodes.LASTORE; break;
+            case Opcodes.T_FLOAT:   xas = Opcodes.FASTORE; break;
+            case Opcodes.T_DOUBLE:  xas = Opcodes.DASTORE; break;
+            case 0:                 xas = Opcodes.AASTORE; break;
+            default:      throw new InternalError();
+        }
+        return xas - Opcodes.AASTORE + aaop;
+    }
+
+
+    private void freeFrameLocal(int oldFrameLocal) {
+        int i = indexForFrameLocal(oldFrameLocal);
+        if (i < 0)  return;
+        BasicType type = localTypes[i];
+        int newFrameLocal = makeLocalTemp(type);
+        mv.visitVarInsn(loadInsnOpcode(type), oldFrameLocal);
+        mv.visitVarInsn(storeInsnOpcode(type), newFrameLocal);
+        assert(localsMap[i] == oldFrameLocal);
+        localsMap[i] = newFrameLocal;
+        assert(indexForFrameLocal(oldFrameLocal) < 0);
+    }
+    private int indexForFrameLocal(int frameLocal) {
+        for (int i = 0; i < localsMap.length; i++) {
+            if (localsMap[i] == frameLocal && localTypes[i] != V_TYPE)
+                return i;
+        }
+        return -1;
+    }
+    private int makeLocalTemp(BasicType type) {
+        int frameLocal = localsMap[localsMap.length - 1];
+        localsMap[localsMap.length - 1] = frameLocal + type.basicTypeSlots();
+        return frameLocal;
+    }
+
     /**
      * Emit a boxing call.
      *
@@ -421,41 +506,79 @@
         String owner = "java/lang/" + wrapper.wrapperType().getSimpleName();
         String name  = wrapper.primitiveSimpleName() + "Value";
         String desc  = "()" + wrapper.basicTypeChar();
-        mv.visitTypeInsn(Opcodes.CHECKCAST, owner);
+        emitReferenceCast(wrapper.wrapperType(), null);
         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false);
     }
 
     /**
-     * Emit an implicit conversion.
+     * Emit an implicit conversion for an argument which must be of the given pclass.
+     * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface.
      *
      * @param ptype type of value present on stack
      * @param pclass type of value required on stack
+     * @param arg compile-time representation of value on stack (Node, constant) or null if none
      */
-    private void emitImplicitConversion(BasicType ptype, Class<?> pclass) {
+    private void emitImplicitConversion(BasicType ptype, Class<?> pclass, Object arg) {
         assert(basicType(pclass) == ptype);  // boxing/unboxing handled by caller
         if (pclass == ptype.basicTypeClass() && ptype != L_TYPE)
             return;   // nothing to do
         switch (ptype) {
-        case L_TYPE:
-            if (VerifyType.isNullConversion(Object.class, pclass))
+            case L_TYPE:
+                if (VerifyType.isNullConversion(Object.class, pclass, false)) {
+                    if (PROFILE_LEVEL > 0)
+                        emitReferenceCast(Object.class, arg);
+                    return;
+                }
+                emitReferenceCast(pclass, arg);
+                return;
+            case I_TYPE:
+                if (!VerifyType.isNullConversion(int.class, pclass, false))
+                    emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass));
                 return;
-            if (isStaticallyNameable(pclass)) {
-                mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass));
-            } else {
-                mv.visitLdcInsn(constantPlaceholder(pclass));
-                mv.visitTypeInsn(Opcodes.CHECKCAST, CLS);
-                mv.visitInsn(Opcodes.SWAP);
-                mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false);
-                if (pclass.isArray())
-                    mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY);
+        }
+        throw newInternalError("bad implicit conversion: tc="+ptype+": "+pclass);
+    }
+
+    /** Update localClasses type map.  Return true if the information is already present. */
+    private boolean assertStaticType(Class<?> cls, Name n) {
+        int local = n.index();
+        Class<?> aclass = localClasses[local];
+        if (aclass != null && (aclass == cls || cls.isAssignableFrom(aclass))) {
+            return true;  // type info is already present
+        } else if (aclass == null || aclass.isAssignableFrom(cls)) {
+            localClasses[local] = cls;  // type info can be improved
+        }
+        return false;
+    }
+
+    private void emitReferenceCast(Class<?> cls, Object arg) {
+        Name writeBack = null;  // local to write back result
+        if (arg instanceof Name) {
+            Name n = (Name) arg;
+            if (assertStaticType(cls, n))
+                return;  // this cast was already performed
+            if (lambdaForm.useCount(n) > 1) {
+                // This guy gets used more than once.
+                writeBack = n;
             }
-            return;
-        case I_TYPE:
-            if (!VerifyType.isNullConversion(int.class, pclass))
-                emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass));
-            return;
         }
-        throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass);
+        if (isStaticallyNameable(cls)) {
+            String sig = getInternalName(cls);
+            mv.visitTypeInsn(Opcodes.CHECKCAST, sig);
+        } else {
+            mv.visitLdcInsn(constantPlaceholder(cls));
+            mv.visitTypeInsn(Opcodes.CHECKCAST, CLS);
+            mv.visitInsn(Opcodes.SWAP);
+            mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false);
+            if (Object[].class.isAssignableFrom(cls))
+                mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY);
+            else if (PROFILE_LEVEL > 0)
+                mv.visitTypeInsn(Opcodes.CHECKCAST, OBJ);
+        }
+        if (writeBack != null) {
+            mv.visitInsn(Opcodes.DUP);
+            emitAstoreInsn(writeBack.index());
+        }
     }
 
     /**
@@ -477,7 +600,11 @@
     }
 
     private static String getInternalName(Class<?> c) {
-        assert(VerifyAccess.isTypeVisible(c, Object.class));
+        if (c == Object.class)             return OBJ;
+        else if (c == Object[].class)      return OBJARY;
+        else if (c == Class.class)         return CLS;
+        else if (c == MethodHandle.class)  return MH;
+        assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName();
         return c.getName().replace('.', '/');
     }
 
@@ -506,39 +633,62 @@
 
         // iterate over the form's names, generating bytecode instructions for each
         // start iterating at the first name following the arguments
+        Name onStack = null;
         for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
             Name name = lambdaForm.names[i];
-            MemberName member = name.function.member();
 
-            if (isSelectAlternative(i)) {
-                emitSelectAlternative(name, lambdaForm.names[i + 1]);
-                i++;  // skip MH.invokeBasic of the selectAlternative result
-            } else if (isGuardWithCatch(i)) {
-                emitGuardWithCatch(i);
-                i = i+2; // Jump to the end of GWC idiom
-            } else if (isStaticallyInvocable(member)) {
+            emitStoreResult(onStack);
+            onStack = name;  // unless otherwise modified below
+            MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
+            switch (intr) {
+                case SELECT_ALTERNATIVE:
+                    assert isSelectAlternative(i);
+                    onStack = emitSelectAlternative(name, lambdaForm.names[i+1]);
+                    i++;  // skip MH.invokeBasic of the selectAlternative result
+                    continue;
+                case GUARD_WITH_CATCH:
+                    assert isGuardWithCatch(i);
+                    onStack = emitGuardWithCatch(i);
+                    i = i+2; // Jump to the end of GWC idiom
+                    continue;
+                case NEW_ARRAY:
+                    Class<?> rtype = name.function.methodType().returnType();
+                    if (isStaticallyNameable(rtype)) {
+                        emitNewArray(name);
+                        continue;
+                    }
+                    break;
+                case ARRAY_LOAD:
+                    emitArrayLoad(name);
+                    continue;
+                case ARRAY_STORE:
+                    emitArrayStore(name);
+                    continue;
+                case IDENTITY:
+                    assert(name.arguments.length == 1);
+                    emitPushArguments(name);
+                    continue;
+                case ZERO:
+                    assert(name.arguments.length == 0);
+                    emitConst(name.type.basicTypeWrapper().zero());
+                    continue;
+                case NONE:
+                    // no intrinsic associated
+                    break;
+                default:
+                    throw newInternalError("Unknown intrinsic: "+intr);
+            }
+
+            MemberName member = name.function.member();
+            if (isStaticallyInvocable(member)) {
                 emitStaticInvoke(member, name);
             } else {
                 emitInvoke(name);
             }
-
-            // Update cached form name's info in case an intrinsic spanning multiple names was encountered.
-            name = lambdaForm.names[i];
-            member = name.function.member();
-
-            // store the result from evaluating to the target name in a local if required
-            // (if this is the last value, i.e., the one that is going to be returned,
-            // avoid store/load/return and just return)
-            if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) {
-                // return value - do nothing
-            } else if (name.type != V_TYPE) {
-                // non-void: actually assign
-                emitStoreInsn(name.type, name.index());
-            }
         }
 
         // return statement
-        emitReturn();
+        emitReturn(onStack);
 
         classFileEpilogue();
         bogusMethod(lambdaForm);
@@ -548,29 +698,43 @@
         return classFile;
     }
 
+    void emitArrayLoad(Name name)  { emitArrayOp(name, Opcodes.AALOAD);  }
+    void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); }
+
+    void emitArrayOp(Name name, int arrayOpcode) {
+        assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE;
+        Class<?> elementType = name.function.methodType().parameterType(0).getComponentType();
+        assert elementType != null;
+        emitPushArguments(name);
+        if (elementType.isPrimitive()) {
+            Wrapper w = Wrapper.forPrimitiveType(elementType);
+            arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode);
+        }
+        mv.visitInsn(arrayOpcode);
+    }
+
     /**
      * Emit an invoke for the given name.
      */
     void emitInvoke(Name name) {
+        assert(!isLinkerMethodInvoke(name));  // should use the static path for these
         if (true) {
             // push receiver
             MethodHandle target = name.function.resolvedHandle;
             assert(target != null) : name.exprString();
             mv.visitLdcInsn(constantPlaceholder(target));
-            mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
+            emitReferenceCast(MethodHandle.class, target);
         } else {
             // load receiver
             emitAloadInsn(0);
-            mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
+            emitReferenceCast(MethodHandle.class, null);
             mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG);
             mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG);
             // TODO more to come
         }
 
         // push arguments
-        for (int i = 0; i < name.arguments.length; i++) {
-            emitPushArgument(name, i);
-        }
+        emitPushArguments(name);
 
         // invocation
         MethodType type = name.function.methodType();
@@ -585,6 +749,10 @@
         //MethodHandle.class already covered
     };
 
+    static boolean isStaticallyInvocable(Name name) {
+        return isStaticallyInvocable(name.function.member());
+    }
+
     static boolean isStaticallyInvocable(MemberName member) {
         if (member == null)  return false;
         if (member.isConstructor())  return false;
@@ -611,6 +779,8 @@
     }
 
     static boolean isStaticallyNameable(Class<?> cls) {
+        if (cls == Object.class)
+            return true;
         while (cls.isArray())
             cls = cls.getComponentType();
         if (cls.isPrimitive())
@@ -631,12 +801,17 @@
         return false;
     }
 
+    void emitStaticInvoke(Name name) {
+        emitStaticInvoke(name.function.member(), name);
+    }
+
     /**
      * Emit an invoke for the given name, using the MemberName directly.
      */
     void emitStaticInvoke(MemberName member, Name name) {
         assert(member.equals(name.function.member()));
-        String cname = getInternalName(member.getDeclaringClass());
+        Class<?> defc = member.getDeclaringClass();
+        String cname = getInternalName(defc);
         String mname = member.getName();
         String mtype;
         byte refKind = member.getReferenceKind();
@@ -653,9 +828,7 @@
         }
 
         // push arguments
-        for (int i = 0; i < name.arguments.length; i++) {
-            emitPushArgument(name, i);
-        }
+        emitPushArguments(name);
 
         // invocation
         if (member.isMethod()) {
@@ -666,6 +839,52 @@
             mtype = MethodType.toFieldDescriptorString(member.getFieldType());
             mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype);
         }
+        // Issue a type assertion for the result, so we can avoid casts later.
+        if (name.type == L_TYPE) {
+            Class<?> rtype = member.getInvocationType().returnType();
+            assert(!rtype.isPrimitive());
+            if (rtype != Object.class && !rtype.isInterface()) {
+                assertStaticType(rtype, name);
+            }
+        }
+    }
+
+    void emitNewArray(Name name) throws InternalError {
+        Class<?> rtype = name.function.methodType().returnType();
+        if (name.arguments.length == 0) {
+            // The array will be a constant.
+            Object emptyArray;
+            try {
+                emptyArray = name.function.resolvedHandle.invoke();
+            } catch (Throwable ex) {
+                throw newInternalError(ex);
+            }
+            assert(java.lang.reflect.Array.getLength(emptyArray) == 0);
+            assert(emptyArray.getClass() == rtype);  // exact typing
+            mv.visitLdcInsn(constantPlaceholder(emptyArray));
+            emitReferenceCast(rtype, emptyArray);
+            return;
+        }
+        Class<?> arrayElementType = rtype.getComponentType();
+        assert(arrayElementType != null);
+        emitIconstInsn(name.arguments.length);
+        int xas = Opcodes.AASTORE;
+        if (!arrayElementType.isPrimitive()) {
+            mv.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(arrayElementType));
+        } else {
+            byte tc = arrayTypeCode(Wrapper.forPrimitiveType(arrayElementType));
+            xas = arrayInsnOpcode(tc, xas);
+            mv.visitIntInsn(Opcodes.NEWARRAY, tc);
+        }
+        // store arguments
+        for (int i = 0; i < name.arguments.length; i++) {
+            mv.visitInsn(Opcodes.DUP);
+            emitIconstInsn(i);
+            emitPushArgument(name, i);
+            mv.visitInsn(xas);
+        }
+        // the array is left on the stack
+        assertStaticType(rtype, name);
     }
     int refKindOpcode(byte refKind) {
         switch (refKind) {
@@ -708,6 +927,21 @@
     }
 
     /**
+     * Check if MemberName is a call to MethodHandle.linkToStatic, etc.
+     */
+    private boolean isLinkerMethodInvoke(Name name) {
+        if (name.function == null)
+            return false;
+        if (name.arguments.length < 1)
+            return false;  // must have MH argument
+        MemberName member = name.function.member();
+        return member != null &&
+               member.getDeclaringClass() == MethodHandle.class &&
+               !member.isPublic() && member.isStatic() &&
+               member.getName().startsWith("linkTo");
+    }
+
+    /**
      * Check if i-th name is a call to MethodHandleImpl.selectAlternative.
      */
     private boolean isSelectAlternative(int pos) {
@@ -755,7 +989,9 @@
      *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
      * }</pre></blockquote>
      */
-    private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
+    private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
+        assert isStaticallyInvocable(invokeBasicName);
+
         Name receiver = (Name) invokeBasicName.arguments[0];
 
         Label L_fallback = new Label();
@@ -763,15 +999,15 @@
 
         // load test result
         emitPushArgument(selectAlternativeName, 0);
-        mv.visitInsn(Opcodes.ICONST_1);
 
         // if_icmpne L_fallback
-        mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback);
+        mv.visitJumpInsn(Opcodes.IFEQ, L_fallback);
 
         // invoke selectAlternativeName.arguments[1]
+        Class<?>[] preForkClasses = localClasses.clone();
         emitPushArgument(selectAlternativeName, 1);  // get 2nd argument of selectAlternative
         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
-        emitInvoke(invokeBasicName);
+        emitStaticInvoke(invokeBasicName);
 
         // goto L_done
         mv.visitJumpInsn(Opcodes.GOTO, L_done);
@@ -780,12 +1016,17 @@
         mv.visitLabel(L_fallback);
 
         // invoke selectAlternativeName.arguments[2]
+        System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
         emitPushArgument(selectAlternativeName, 2);  // get 3rd argument of selectAlternative
         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
-        emitInvoke(invokeBasicName);
+        emitStaticInvoke(invokeBasicName);
 
         // L_done:
         mv.visitLabel(L_done);
+        // for now do not bother to merge typestate; just reset to the dominator state
+        System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
+
+        return invokeBasicName;  // return what's on stack
     }
 
     /**
@@ -808,7 +1049,7 @@
       *      return a3.invokeBasic(ex, a6, a7);
       *  }}
       */
-    private void emitGuardWithCatch(int pos) {
+    private Name emitGuardWithCatch(int pos) {
         Name args    = lambdaForm.names[pos];
         Name invoker = lambdaForm.names[pos+1];
         Name result  = lambdaForm.names[pos+2];
@@ -859,6 +1100,12 @@
         mv.visitInsn(Opcodes.ATHROW);
 
         mv.visitLabel(L_done);
+
+        return result;
+    }
+
+    private void emitPushArguments(Name args) {
+        emitPushArguments(args, 0);
     }
 
     private void emitPushArguments(Name args, int start) {
@@ -878,7 +1125,7 @@
         if (arg instanceof Name) {
             Name n = (Name) arg;
             emitLoadInsn(n.type, n.index());
-            emitImplicitConversion(n.type, ptype);
+            emitImplicitConversion(n.type, ptype, n);
         } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) {
             emitConst(arg);
         } else {
@@ -886,15 +1133,25 @@
                 emitConst(arg);
             } else {
                 mv.visitLdcInsn(constantPlaceholder(arg));
-                emitImplicitConversion(L_TYPE, ptype);
+                emitImplicitConversion(L_TYPE, ptype, arg);
             }
         }
     }
 
     /**
+     * Store the name to its local, if necessary.
+     */
+    private void emitStoreResult(Name name) {
+        if (name != null && name.type != V_TYPE) {
+            // non-void: actually assign
+            emitStoreInsn(name.type, name.index());
+        }
+    }
+
+    /**
      * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type.
      */
-    private void emitReturn() {
+    private void emitReturn(Name onStack) {
         // return statement
         Class<?> rclass = invokerType.returnType();
         BasicType rtype = lambdaForm.returnType();
@@ -907,12 +1164,11 @@
             LambdaForm.Name rn = lambdaForm.names[lambdaForm.result];
 
             // put return value on the stack if it is not already there
-            if (lambdaForm.result != lambdaForm.names.length - 1 ||
-                    lambdaForm.result < lambdaForm.arity) {
-                emitLoadInsn(rn.type, lambdaForm.result);
+            if (rn != onStack) {
+                emitLoadInsn(rtype, lambdaForm.result);
             }
 
-            emitImplicitConversion(rtype, rclass);
+            emitImplicitConversion(rtype, rclass, rn);
 
             // generate actual return statement
             emitReturnInsn(rtype);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,8 +25,9 @@
 
 package java.lang.invoke;
 
+import java.lang.reflect.Array;
 import java.util.Arrays;
-import sun.invoke.empty.Empty;
+
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
@@ -40,52 +41,63 @@
     // exact type (sans leading target MH) for the outgoing call
     private final MethodType targetType;
 
-    // FIXME: Get rid of the invokers that are not useful.
-
-    // exact invoker for the outgoing call
-    private /*lazy*/ MethodHandle exactInvoker;
-    private /*lazy*/ MethodHandle basicInvoker;  // invokeBasic (unchecked exact)
-
-    // erased (partially untyped but with primitives) invoker for the outgoing call
-    // FIXME: get rid of
-    private /*lazy*/ MethodHandle erasedInvoker;
-    // FIXME: get rid of
-    /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
-
-    // general invoker for the outgoing call
-    private /*lazy*/ MethodHandle generalInvoker;
-
-    // general invoker for the outgoing call, uses varargs
-    private /*lazy*/ MethodHandle varargsInvoker;
-
-    // general invoker for the outgoing call; accepts a trailing Object[]
-    private final /*lazy*/ MethodHandle[] spreadInvokers;
-
-    // invoker for an unbound callsite
-    private /*lazy*/ MethodHandle uninitializedCallSite;
+    // Cached adapter information:
+    private final @Stable MethodHandle[] invokers = new MethodHandle[INV_LIMIT];
+    // Indexes into invokers:
+    static final int
+            INV_EXACT          =  0,  // MethodHandles.exactInvoker
+            INV_GENERIC        =  1,  // MethodHandles.invoker (generic invocation)
+            INV_BASIC          =  2,  // MethodHandles.basicInvoker
+            INV_LIMIT          =  3;
 
     /** Compute and cache information common to all collecting adapters
      *  that implement members of the erasure-family of the given erased type.
      */
     /*non-public*/ Invokers(MethodType targetType) {
         this.targetType = targetType;
-        this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
     }
 
     /*non-public*/ MethodHandle exactInvoker() {
-        MethodHandle invoker = exactInvoker;
+        MethodHandle invoker = cachedInvoker(INV_EXACT);
         if (invoker != null)  return invoker;
         invoker = makeExactOrGeneralInvoker(true);
-        exactInvoker = invoker;
-        return invoker;
+        return setCachedInvoker(INV_EXACT, invoker);
+    }
+
+    /*non-public*/ MethodHandle genericInvoker() {
+        MethodHandle invoker = cachedInvoker(INV_GENERIC);
+        if (invoker != null)  return invoker;
+        invoker = makeExactOrGeneralInvoker(false);
+        return setCachedInvoker(INV_GENERIC, invoker);
     }
 
-    /*non-public*/ MethodHandle generalInvoker() {
-        MethodHandle invoker = generalInvoker;
+    /*non-public*/ MethodHandle basicInvoker() {
+        MethodHandle invoker = cachedInvoker(INV_BASIC);
         if (invoker != null)  return invoker;
-        invoker = makeExactOrGeneralInvoker(false);
-        generalInvoker = invoker;
-        return invoker;
+        MethodType basicType = targetType.basicType();
+        if (basicType != targetType) {
+            // double cache; not used significantly
+            return setCachedInvoker(INV_BASIC, basicType.invokers().basicInvoker());
+        }
+        invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_BASIC_INV);
+        if (invoker == null) {
+            MemberName method = invokeBasicMethod(basicType);
+            invoker = DirectMethodHandle.make(method);
+            assert(checkInvoker(invoker));
+            invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_BASIC_INV, invoker);
+        }
+        return setCachedInvoker(INV_BASIC, invoker);
+    }
+
+    private MethodHandle cachedInvoker(int idx) {
+        return invokers[idx];
+    }
+
+    private synchronized MethodHandle setCachedInvoker(int idx, final MethodHandle invoker) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = invokers[idx];
+        if (prev != null)  return prev;
+        return invokers[idx] = invoker;
     }
 
     private MethodHandle makeExactOrGeneralInvoker(boolean isExact) {
@@ -95,7 +107,7 @@
         LambdaForm lform = invokeHandleForm(mtype, false, which);
         MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
         String whichName = (isExact ? "invokeExact" : "invoke");
-        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype));
+        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype), false);
         assert(checkInvoker(invoker));
         maybeCompileToBytecode(invoker);
         return invoker;
@@ -110,21 +122,6 @@
         }
     }
 
-    /*non-public*/ MethodHandle basicInvoker() {
-        MethodHandle invoker = basicInvoker;
-        if (invoker != null)  return invoker;
-        MethodType basicType = targetType.basicType();
-        if (basicType != targetType) {
-            // double cache; not used significantly
-            return basicInvoker = basicType.invokers().basicInvoker();
-        }
-        MemberName method = invokeBasicMethod(basicType);
-        invoker = DirectMethodHandle.make(method);
-        assert(checkInvoker(invoker));
-        basicInvoker = invoker;
-        return invoker;
-    }
-
     // This next one is called from LambdaForm.NamedFunction.<init>.
     /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
         assert(basicType == basicType.basicType());
@@ -145,87 +142,42 @@
         return true;
     }
 
-    // FIXME: get rid of
-    /*non-public*/ MethodHandle erasedInvoker() {
-        MethodHandle xinvoker = exactInvoker();
-        MethodHandle invoker = erasedInvoker;
-        if (invoker != null)  return invoker;
-        MethodType erasedType = targetType.erase();
-        invoker = xinvoker.asType(erasedType.invokerType());
-        erasedInvoker = invoker;
-        return invoker;
+    /**
+     * Find or create an invoker which passes unchanged a given number of arguments
+     * and spreads the rest from a trailing array argument.
+     * The invoker target type is the post-spread type {@code (TYPEOF(uarg*), TYPEOF(sarg*))=>RT}.
+     * All the {@code sarg}s must have a common type {@code C}.  (If there are none, {@code Object} is assumed.}
+     * @param leadingArgCount the number of unchanged (non-spread) arguments
+     * @return {@code invoker.invokeExact(mh, uarg*, C[]{sarg*}) := (RT)mh.invoke(uarg*, sarg*)}
+     */
+    /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
+        int spreadArgCount = targetType.parameterCount() - leadingArgCount;
+        MethodType postSpreadType = targetType;
+        Class<?> argArrayType = impliedRestargType(postSpreadType, leadingArgCount);
+        if (postSpreadType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
+            return genericInvoker().asSpreader(argArrayType, spreadArgCount);
+        }
+        // Cannot build a generic invoker here of type ginvoker.invoke(mh, a*[254]).
+        // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
+        // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
+        MethodType preSpreadType = postSpreadType
+            .replaceParameterTypes(leadingArgCount, postSpreadType.parameterCount(), argArrayType);
+        MethodHandle arrayInvoker = MethodHandles.invoker(preSpreadType);
+        MethodHandle makeSpreader = MethodHandles.insertArguments(Lazy.MH_asSpreader, 1, argArrayType, spreadArgCount);
+        return MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
     }
 
-    /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
-        MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
-        if (vaInvoker != null)  return vaInvoker;
-        int spreadArgCount = targetType.parameterCount() - leadingArgCount;
-        MethodType spreadInvokerType = targetType
-            .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class);
-        if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
-            // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a)
-            // where ginvoker.invoke(mh, a*) => mh.invoke(a*).
-            MethodHandle genInvoker = generalInvoker();
-            vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount);
-        } else {
-            // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]).
-            // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
-            // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
-            MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType);
-            MethodHandle makeSpreader;
-            try {
-                makeSpreader = IMPL_LOOKUP
-                    .findVirtual(MethodHandle.class, "asSpreader",
-                        MethodType.methodType(MethodHandle.class, Class.class, int.class));
-            } catch (ReflectiveOperationException ex) {
-                throw newInternalError(ex);
-            }
-            makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount);
-            vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
+    private static Class<?> impliedRestargType(MethodType restargType, int fromPos) {
+        if (restargType.isGeneric())  return Object[].class;  // can be nothing else
+        int maxPos = restargType.parameterCount();
+        if (fromPos >= maxPos)  return Object[].class;  // reasonable default
+        Class<?> argType = restargType.parameterType(fromPos);
+        for (int i = fromPos+1; i < maxPos; i++) {
+            if (argType != restargType.parameterType(i))
+                throw newIllegalArgumentException("need homogeneous rest arguments", restargType);
         }
-        assert(vaInvoker.type().equals(spreadInvokerType.invokerType()));
-        maybeCompileToBytecode(vaInvoker);
-        spreadInvokers[leadingArgCount] = vaInvoker;
-        return vaInvoker;
-    }
-
-    /*non-public*/ MethodHandle varargsInvoker() {
-        MethodHandle vaInvoker = varargsInvoker;
-        if (vaInvoker != null)  return vaInvoker;
-        vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType());
-        varargsInvoker = vaInvoker;
-        return vaInvoker;
-    }
-
-    private static MethodHandle THROW_UCS = null;
-
-    /*non-public*/ MethodHandle uninitializedCallSite() {
-        MethodHandle invoker = uninitializedCallSite;
-        if (invoker != null)  return invoker;
-        if (targetType.parameterCount() > 0) {
-            MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
-            Invokers invokers0 = type0.invokers();
-            invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
-                                                  0, targetType.parameterList());
-            assert(invoker.type().equals(targetType));
-            uninitializedCallSite = invoker;
-            return invoker;
-        }
-        invoker = THROW_UCS;
-        if (invoker == null) {
-            try {
-                THROW_UCS = invoker = IMPL_LOOKUP
-                    .findStatic(CallSite.class, "uninitializedCallSite",
-                                MethodType.methodType(Empty.class));
-            } catch (ReflectiveOperationException ex) {
-                throw newInternalError(ex);
-            }
-        }
-        invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
-        invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
-        assert(invoker.type().equals(targetType));
-        uninitializedCallSite = invoker;
-        return invoker;
+        if (argType == Object.class)  return Object[].class;
+        return Array.newInstance(argType, 0).getClass();
     }
 
     public String toString() {
@@ -308,7 +260,9 @@
                 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
         if (MTYPE_ARG >= INARG_LIMIT) {
             assert(names[MTYPE_ARG] == null);
-            NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
+            BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+            names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+            NamedFunction getter = speciesData.getterFunction(0);
             names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
         }
@@ -360,9 +314,6 @@
     Object checkGenericType(Object mhObj, Object expectedObj) {
         MethodHandle mh = (MethodHandle) mhObj;
         MethodType expected = (MethodType) expectedObj;
-        if (mh.type() == expected)  return mh;
-        MethodHandle atc = mh.asTypeCache;
-        if (atc != null && atc.type() == expected)  return atc;
         return mh.asType(expected);
         /* Maybe add more paths here.  Possible optimizations:
          * for (R)MH.invoke(a*),
@@ -436,27 +387,40 @@
     }
 
     // Local constant functions:
-    private static final NamedFunction NF_checkExactType;
-    private static final NamedFunction NF_checkGenericType;
-    private static final NamedFunction NF_asType;
-    private static final NamedFunction NF_getCallSiteTarget;
+    private static final NamedFunction
+        NF_checkExactType,
+        NF_checkGenericType,
+        NF_getCallSiteTarget;
     static {
         try {
-            NF_checkExactType = new NamedFunction(Invokers.class
-                    .getDeclaredMethod("checkExactType", Object.class, Object.class));
-            NF_checkGenericType = new NamedFunction(Invokers.class
-                    .getDeclaredMethod("checkGenericType", Object.class, Object.class));
-            NF_asType = new NamedFunction(MethodHandle.class
-                    .getDeclaredMethod("asType", MethodType.class));
-            NF_getCallSiteTarget = new NamedFunction(Invokers.class
-                    .getDeclaredMethod("getCallSiteTarget", Object.class));
-            NF_checkExactType.resolve();
-            NF_checkGenericType.resolve();
-            NF_getCallSiteTarget.resolve();
-            // bound
+            NamedFunction nfs[] = {
+                NF_checkExactType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkExactType", Object.class, Object.class)),
+                NF_checkGenericType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
+                NF_getCallSiteTarget = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("getCallSiteTarget", Object.class))
+            };
+            for (NamedFunction nf : nfs) {
+                // Each nf must be statically invocable or we get tied up in our bootstraps.
+                assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
+                nf.resolve();
+            }
         } catch (ReflectiveOperationException ex) {
             throw newInternalError(ex);
         }
     }
 
+    private static class Lazy {
+        private static final MethodHandle MH_asSpreader;
+
+        static {
+            try {
+                MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
+                        MethodType.methodType(MethodHandle.class, Class.class, int.class));
+            } catch (ReflectiveOperationException ex) {
+                throw newInternalError(ex);
+            }
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,11 +27,10 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.Method;
-import java.util.Map;
 import java.util.List;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.concurrent.ConcurrentHashMap;
+
 import sun.invoke.util.Wrapper;
 import java.lang.reflect.Field;
 
@@ -125,8 +124,7 @@
     MemberName vmentry;   // low-level behavior, or null if not yet prepared
     private boolean isCompiled;
 
-    // Caches for common structural transforms:
-    LambdaForm[] bindCache;
+    Object transformCache;  // managed by LambdaFormEditor
 
     public static final int VOID_RESULT = -1, LAST_RESULT = -2;
 
@@ -214,6 +212,13 @@
             }
             return btypes;
         }
+        static byte[] basicTypesOrd(BasicType[] btypes) {
+            byte[] ords = new byte[btypes.length];
+            for (int i = 0; i < btypes.length; i++) {
+                ords[i] = (byte)btypes[i].ordinal();
+            }
+            return ords;
+        }
         static boolean isBasicTypeChar(char c) {
             return "LIJFDV".indexOf(c) >= 0;
         }
@@ -243,7 +248,12 @@
         this.result = fixResult(result, names);
         this.names = names.clone();
         this.debugName = fixDebugName(debugName);
-        normalize();
+        int maxOutArity = normalize();
+        if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
+            // Cannot use LF interpreter on very high arity expressions.
+            assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
+            compileToBytecode();
+        }
     }
 
     LambdaForm(String debugName,
@@ -348,9 +358,12 @@
         return true;
     }
 
-    /** Renumber and/or replace params so that they are interned and canonically numbered. */
-    private void normalize() {
+    /** Renumber and/or replace params so that they are interned and canonically numbered.
+     *  @return maximum argument list length among the names (since we have to pass over them anyway)
+     */
+    private int normalize() {
         Name[] oldNames = null;
+        int maxOutArity = 0;
         int changesStart = 0;
         for (int i = 0; i < names.length; i++) {
             Name n = names[i];
@@ -361,6 +374,8 @@
                 }
                 names[i] = n.cloneWithIndex(i);
             }
+            if (n.arguments != null && maxOutArity < n.arguments.length)
+                maxOutArity = n.arguments.length;
         }
         if (oldNames != null) {
             int startFixing = arity;
@@ -387,6 +402,7 @@
             }
             assert(nameRefsAreLegal());
         }
+        return maxOutArity;
     }
 
     /**
@@ -398,7 +414,7 @@
      * This allows Name references to be freely reused to construct
      * fresh lambdas, without confusion.
      */
-    private boolean nameRefsAreLegal() {
+    boolean nameRefsAreLegal() {
         assert(arity >= 0 && arity <= names.length);
         assert(result >= -1 && result < names.length);
         // Do all names possess an index consistent with their local definition order?
@@ -439,8 +455,20 @@
 
     /** Report the N-th argument type. */
     BasicType parameterType(int n) {
+        return parameter(n).type;
+    }
+
+    /** Report the N-th argument name. */
+    Name parameter(int n) {
         assert(n < arity);
-        return names[n].type;
+        Name param = names[n];
+        assert(param.isParam());
+        return param;
+    }
+
+    /** Report the N-th argument type constraint. */
+    Object parameterConstraint(int n) {
+        return parameter(n).constraint;
     }
 
     /** Report the arity. */
@@ -448,6 +476,11 @@
         return arity;
     }
 
+    /** Report the number of expressions (non-parameter names). */
+    int expressionCount() {
+        return names.length - arity;
+    }
+
     /** Return the method type corresponding to my basic type signature. */
     MethodType methodType() {
         return signatureType(basicTypeSignature());
@@ -464,7 +497,7 @@
         return sig.indexOf('_');
     }
     static BasicType signatureReturn(String sig) {
-        return basicType(sig.charAt(signatureArity(sig)+1));
+        return basicType(sig.charAt(signatureArity(sig) + 1));
     }
     static boolean isValidSignature(String sig) {
         int arity = sig.indexOf('_');
@@ -582,21 +615,12 @@
             isCompiled = true;
             return vmentry;
         } catch (Error | Exception ex) {
-            throw newInternalError("compileToBytecode", ex);
+            throw newInternalError(this.toString(), ex);
         }
     }
 
-    private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS;
-    static {
-        int   capacity   = 512;    // expect many distinct signatures over time
-        float loadFactor = 0.75f;  // normal default
-        int   writers    = 1;
-        PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers);
-    }
-
-    private static Map<String,LambdaForm> computeInitialPreparedForms() {
+    private static void computeInitialPreparedForms() {
         // Find all predefined invokers and associate them with canonical empty lambda forms.
-        HashMap<String,LambdaForm> forms = new HashMap<>();
         for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
             if (!m.isStatic() || !m.isPackage())  continue;
             MethodType mt = m.getMethodType();
@@ -607,13 +631,9 @@
                 assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
                 LambdaForm form = new LambdaForm(sig);
                 form.vmentry = m;
-                form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form);
-                // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only
-                forms.put(sig, form);
+                form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
             }
         }
-        //System.out.println("computeInitialPreparedForms => "+forms);
-        return forms;
     }
 
     // Set this false to disable use of the interpret_L methods defined in this file.
@@ -647,13 +667,11 @@
     }
     private static LambdaForm getPreparedForm(String sig) {
         MethodType mtype = signatureType(sig);
-        //LambdaForm prep = PREPARED_FORMS.get(sig);
         LambdaForm prep =  mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
         if (prep != null)  return prep;
         assert(isValidSignature(sig));
         prep = new LambdaForm(sig);
         prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
-        //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep);
         return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
     }
 
@@ -709,10 +727,7 @@
     /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */
     private static final int COMPILE_THRESHOLD;
     static {
-        if (MethodHandleStatics.COMPILE_THRESHOLD != null)
-            COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD;
-        else
-            COMPILE_THRESHOLD = 30;  // default value
+        COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD);
     }
     private int invocationCounter = 0;
 
@@ -728,7 +743,9 @@
         for (int i = argumentValues.length; i < values.length; i++) {
             values[i] = interpretName(names[i], values);
         }
-        return (result < 0) ? null : values[result];
+        Object rv = (result < 0) ? null : values[result];
+        assert(resultCheck(argumentValues, rv));
+        return rv;
     }
 
     @Hidden
@@ -785,28 +802,6 @@
         return rval;
     }
 
-    //** This transform is applied (statically) to every name.function. */
-    /*
-    private static MethodHandle eraseSubwordTypes(MethodHandle mh) {
-        MethodType mt = mh.type();
-        if (mt.hasPrimitives()) {
-            mt = mt.changeReturnType(eraseSubwordType(mt.returnType()));
-            for (int i = 0; i < mt.parameterCount(); i++) {
-                mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i)));
-            }
-            mh = MethodHandles.explicitCastArguments(mh, mt);
-        }
-        return mh;
-    }
-    private static Class<?> eraseSubwordType(Class<?> type) {
-        if (!type.isPrimitive())  return type;
-        if (type == int.class)  return type;
-        Wrapper w = Wrapper.forPrimitiveType(type);
-        if (w.isSubwordOrInt())  return int.class;
-        return type;
-    }
-    */
-
     static void traceInterpreter(String event, Object obj, Object... args) {
         if (TRACE_INTERPRETER) {
             System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
@@ -819,8 +814,16 @@
         assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
         // also check that the leading (receiver) argument is somehow bound to this LF:
         assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
-        assert(((MethodHandle)argumentValues[0]).internalForm() == this);
+        MethodHandle mh = (MethodHandle) argumentValues[0];
+        assert(mh.internalForm() == this);
         // note:  argument #0 could also be an interface wrapper, in the future
+        argumentTypesMatch(basicTypeSignature(), argumentValues);
+        return true;
+    }
+    private boolean resultCheck(Object[] argumentValues, Object result) {
+        MethodHandle mh = (MethodHandle) argumentValues[0];
+        MethodType mt = mh.type();
+        assert(valueMatches(returnType(), mt.returnType(), result));
         return true;
     }
 
@@ -839,7 +842,7 @@
             if (i == arity)  buf.append(")=>{");
             Name n = names[i];
             if (i >= arity)  buf.append("\n    ");
-            buf.append(n);
+            buf.append(n.paramString());
             if (i < arity) {
                 if (i+1 < arity)  buf.append(",");
                 continue;
@@ -847,6 +850,7 @@
             buf.append("=").append(n.exprString());
             buf.append(";");
         }
+        if (arity == names.length)  buf.append(")=>{");
         buf.append(result < 0 ? "void" : names[result]).append("}");
         if (TRACE_INTERPRETER) {
             // Extra verbosity:
@@ -856,135 +860,19 @@
         return buf.toString();
     }
 
-    /**
-     * Apply immediate binding for a Name in this form indicated by its position relative to the form.
-     * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not
-     * accepted as valid.
-     */
-    LambdaForm bindImmediate(int pos, BasicType basicType, Object value) {
-        // must be an argument, and the types must match
-        assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value);
-
-        int arity2 = arity - 1;
-        Name[] names2 = new Name[names.length - 1];
-        for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2
-            Name n = names[r];
-            if (n.isParam()) {
-                if (n.index == pos) {
-                    // do not copy over the argument that is to be replaced with a literal,
-                    // but adjust the write index
-                    --w;
-                } else {
-                    names2[w] = new Name(w, n.type);
-                }
-            } else {
-                Object[] arguments2 = new Object[n.arguments.length];
-                for (int i = 0; i < n.arguments.length; ++i) {
-                    Object arg = n.arguments[i];
-                    if (arg instanceof Name) {
-                        int ni = ((Name) arg).index;
-                        if (ni == pos) {
-                            arguments2[i] = value;
-                        } else if (ni < pos) {
-                            // replacement position not yet passed
-                            arguments2[i] = names2[ni];
-                        } else {
-                            // replacement position passed
-                            arguments2[i] = names2[ni - 1];
-                        }
-                    } else {
-                        arguments2[i] = arg;
-                    }
-                }
-                names2[w] = new Name(n.function, arguments2);
-                names2[w].initIndex(w);
-            }
-        }
-
-        int result2 = result == -1 ? -1 : result - 1;
-        return new LambdaForm(debugName, arity2, names2, result2);
-    }
-
-    LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
-        Name name = names[namePos];
-        BoundMethodHandle.SpeciesData newData = oldData.extendWith(name.type);
-        return bind(name, new Name(newData.getterFunction(oldData.fieldCount()), names[0]), oldData, newData);
+    @Override
+    public boolean equals(Object obj) {
+        return obj instanceof LambdaForm && equals((LambdaForm)obj);
     }
-    LambdaForm bind(Name name, Name binding,
-                    BoundMethodHandle.SpeciesData oldData,
-                    BoundMethodHandle.SpeciesData newData) {
-        int pos = name.index;
-        assert(name.isParam());
-        assert(!binding.isParam());
-        assert(name.type == binding.type);
-        assert(0 <= pos && pos < arity && names[pos] == name);
-        assert(binding.function.memberDeclaringClassOrNull() == newData.clazz);
-        assert(oldData.getters.length == newData.getters.length-1);
-        if (bindCache != null) {
-            LambdaForm form = bindCache[pos];
-            if (form != null) {
-                assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>";
-                return form;
-            }
-        } else {
-            bindCache = new LambdaForm[arity];
-        }
-        assert(nameRefsAreLegal());
-        int arity2 = arity-1;
-        Name[] names2 = names.clone();
-        names2[pos] = binding;  // we might move this in a moment
-
-        // The newly created LF will run with a different BMH.
-        // Switch over any pre-existing BMH field references to the new BMH class.
-        int firstOldRef = -1;
-        for (int i = 0; i < names2.length; i++) {
-            Name n = names[i];
-            if (n.function != null &&
-                n.function.memberDeclaringClassOrNull() == oldData.clazz) {
-                MethodHandle oldGetter = n.function.resolvedHandle;
-                MethodHandle newGetter = null;
-                for (int j = 0; j < oldData.getters.length; j++) {
-                    if (oldGetter == oldData.getters[j])
-                        newGetter =  newData.getters[j];
-                }
-                if (newGetter != null) {
-                    if (firstOldRef < 0)  firstOldRef = i;
-                    Name n2 = new Name(newGetter, n.arguments);
-                    names2[i] = n2;
-                }
-            }
-        }
-
-        // Walk over the new list of names once, in forward order.
-        // Replace references to 'name' with 'binding'.
-        // Replace data structure references to the old BMH species with the new.
-        // This might cause a ripple effect, but it will settle in one pass.
-        assert(firstOldRef < 0 || firstOldRef > pos);
-        for (int i = pos+1; i < names2.length; i++) {
-            if (i <= arity2)  continue;
-            names2[i] = names2[i].replaceNames(names, names2, pos, i);
-        }
-
-        //  (a0, a1, name=a2, a3, a4)  =>  (a0, a1, a3, a4, binding)
-        int insPos = pos;
-        for (; insPos+1 < names2.length; insPos++) {
-            Name n = names2[insPos+1];
-            if (n.isSiblingBindingBefore(binding)) {
-                names2[insPos] = n;
-            } else {
-                break;
-            }
-        }
-        names2[insPos] = binding;
-
-        // Since we moved some stuff, maybe update the result reference:
-        int result2 = result;
-        if (result2 == pos)
-            result2 = insPos;
-        else if (result2 > pos && result2 <= insPos)
-            result2 -= 1;
-
-        return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2);
+    public boolean equals(LambdaForm that) {
+        if (this.result != that.result)  return false;
+        return Arrays.equals(this.names, that.names);
+    }
+    public int hashCode() {
+        return result + 31 * Arrays.hashCode(names);
+    }
+    LambdaFormEditor editor() {
+        return LambdaFormEditor.lambdaFormEditor(this);
     }
 
     boolean contains(Name name) {
@@ -1000,16 +888,16 @@
     }
 
     LambdaForm addArguments(int pos, BasicType... types) {
-        assert(pos <= arity);
+        // names array has MH in slot 0; skip it.
+        int argpos = pos + 1;
+        assert(argpos <= arity);
         int length = names.length;
         int inTypes = types.length;
         Name[] names2 = Arrays.copyOf(names, length + inTypes);
         int arity2 = arity + inTypes;
         int result2 = result;
-        if (result2 >= arity)
+        if (result2 >= argpos)
             result2 += inTypes;
-        // names array has MH in slot 0; skip it.
-        int argpos = pos + 1;
         // Note:  The LF constructor will rename names2[argpos...].
         // Make space for new arguments (shift temporaries).
         System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
@@ -1102,8 +990,9 @@
         }
         NamedFunction(MemberName member, MethodHandle resolvedHandle) {
             this.member = member;
-            //resolvedHandle = eraseSubwordTypes(resolvedHandle);
             this.resolvedHandle = resolvedHandle;
+             // The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest.
+             //assert(!isInvokeBasic());
         }
         NamedFunction(MethodType basicInvokerType) {
             assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
@@ -1114,6 +1003,13 @@
                 // necessary to pass BigArityTest
                 this.member = Invokers.invokeBasicMethod(basicInvokerType);
             }
+            assert(isInvokeBasic());
+        }
+
+        private boolean isInvokeBasic() {
+            return member != null &&
+                   member.isMethodHandleInvoke() &&
+                   "invokeBasic".equals(member.getName());
         }
 
         // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
@@ -1169,7 +1065,7 @@
                     if (LambdaForm.signatureReturn(sig) == V_TYPE)
                         srcType = srcType.changeReturnType(void.class);
                     MethodTypeForm typeForm = srcType.form();
-                    typeForm.namedFunctionInvoker = DirectMethodHandle.make(m);
+                    typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m));
                 }
             }
         }
@@ -1179,85 +1075,104 @@
         /** void return type invokers. */
         @Hidden
         static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 0);
+            assert(arityCheck(0, void.class, mh, a));
             mh.invokeBasic();
             return null;
         }
         @Hidden
         static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 1);
+            assert(arityCheck(1, void.class, mh, a));
             mh.invokeBasic(a[0]);
             return null;
         }
         @Hidden
         static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 2);
+            assert(arityCheck(2, void.class, mh, a));
             mh.invokeBasic(a[0], a[1]);
             return null;
         }
         @Hidden
         static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 3);
+            assert(arityCheck(3, void.class, mh, a));
             mh.invokeBasic(a[0], a[1], a[2]);
             return null;
         }
         @Hidden
         static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 4);
+            assert(arityCheck(4, void.class, mh, a));
             mh.invokeBasic(a[0], a[1], a[2], a[3]);
             return null;
         }
         @Hidden
         static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 5);
+            assert(arityCheck(5, void.class, mh, a));
             mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
             return null;
         }
         /** Object return type invokers. */
         @Hidden
         static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 0);
+            assert(arityCheck(0, mh, a));
             return mh.invokeBasic();
         }
         @Hidden
         static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 1);
+            assert(arityCheck(1, mh, a));
             return mh.invokeBasic(a[0]);
         }
         @Hidden
         static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 2);
+            assert(arityCheck(2, mh, a));
             return mh.invokeBasic(a[0], a[1]);
         }
         @Hidden
         static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 3);
+            assert(arityCheck(3, mh, a));
             return mh.invokeBasic(a[0], a[1], a[2]);
         }
         @Hidden
         static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 4);
+            assert(arityCheck(4, mh, a));
             return mh.invokeBasic(a[0], a[1], a[2], a[3]);
         }
         @Hidden
         static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(a.length == 5);
+            assert(arityCheck(5, mh, a));
             return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
         }
+        private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) {
+            return arityCheck(arity, Object.class, mh, a);
+        }
+        private static boolean arityCheck(int arity, Class<?> rtype, MethodHandle mh, Object[] a) {
+            assert(a.length == arity)
+                    : Arrays.asList(a.length, arity);
+            assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype))
+                    : Arrays.asList(mh, rtype, arity);
+            MemberName member = mh.internalMemberName();
+            if (member != null && member.getName().equals("invokeBasic") && member.isMethodHandleInvoke()) {
+                assert(arity > 0);
+                assert(a[0] instanceof MethodHandle);
+                MethodHandle mh2 = (MethodHandle) a[0];
+                assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype))
+                        : Arrays.asList(member, mh2, rtype, arity);
+            }
+            return true;
+        }
 
         static final MethodType INVOKER_METHOD_TYPE =
             MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
 
         private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
-            MethodHandle mh = typeForm.namedFunctionInvoker;
+            typeForm = typeForm.basicType().form();  // normalize to basic type
+            MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV);
             if (mh != null)  return mh;
             MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm);  // this could take a while
             mh = DirectMethodHandle.make(invoker);
-            MethodHandle mh2 = typeForm.namedFunctionInvoker;
+            MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV);
             if (mh2 != null)  return mh2;  // benign race
             if (!mh.type().equals(INVOKER_METHOD_TYPE))
                 throw newInternalError(mh.debugString());
-            return typeForm.namedFunctionInvoker = mh;
+            return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh);
         }
 
         @Hidden
@@ -1365,6 +1280,11 @@
         public boolean isConstantZero() {
             return this.equals(constantZero(returnType()));
         }
+
+        public MethodHandleImpl.Intrinsic intrinsicName() {
+            return resolvedHandle == null ? MethodHandleImpl.Intrinsic.NONE
+                                          : resolvedHandle.intrinsicName();
+        }
     }
 
     public static String basicTypeSignature(MethodType type) {
@@ -1411,6 +1331,7 @@
         final BasicType type;
         private short index;
         final NamedFunction function;
+        final Object constraint;  // additional type information, if not null
         @Stable final Object[] arguments;
 
         private Name(int index, BasicType type, NamedFunction function, Object[] arguments) {
@@ -1418,8 +1339,18 @@
             this.type = type;
             this.function = function;
             this.arguments = arguments;
+            this.constraint = null;
             assert(this.index == index);
         }
+        private Name(Name that, Object constraint) {
+            this.index = that.index;
+            this.type = that.type;
+            this.function = that.function;
+            this.arguments = that.arguments;
+            this.constraint = constraint;
+            assert(constraint == null || isParam());  // only params have constraints
+            assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class);
+        }
         Name(MethodHandle function, Object... arguments) {
             this(new NamedFunction(function), arguments);
         }
@@ -1431,7 +1362,7 @@
             this(new NamedFunction(function), arguments);
         }
         Name(NamedFunction function, Object... arguments) {
-            this(-1, function.returnType(), function, arguments = arguments.clone());
+            this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class));
             assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
             for (int i = 0; i < arguments.length; i++)
                 assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
@@ -1467,7 +1398,11 @@
         }
         Name cloneWithIndex(int i) {
             Object[] newArguments = (arguments == null) ? null : arguments.clone();
-            return new Name(i, type, function, newArguments);
+            return new Name(i, type, function, newArguments).withConstraint(constraint);
+        }
+        Name withConstraint(Object constraint) {
+            if (constraint == this.constraint)  return this;
+            return new Name(this, constraint);
         }
         Name replaceName(Name oldName, Name newName) {  // FIXME: use replaceNames uniformly
             if (oldName == newName)  return this;
@@ -1487,7 +1422,11 @@
             if (!replaced)  return this;
             return new Name(function, arguments);
         }
+        /** In the arguments of this Name, replace oldNames[i] pairwise by newNames[i].
+         *  Limit such replacements to {@code start<=i<end}.  Return possibly changed self.
+         */
         Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
+            if (start >= end)  return this;
             @SuppressWarnings("LocalVariableHidesMemberVariable")
             Object[] arguments = this.arguments;
             boolean replaced = false;
@@ -1539,8 +1478,16 @@
             return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+typeChar();
         }
         public String debugString() {
+            String s = paramString();
+            return (function == null) ? s : s + "=" + exprString();
+        }
+        public String paramString() {
             String s = toString();
-            return (function == null) ? s : s + "=" + exprString();
+            Object c = constraint;
+            if (c == null)
+                return s;
+            if (c instanceof Class)  c = ((Class<?>)c).getSimpleName();
+            return s + "/" + c;
         }
         public String exprString() {
             if (function == null)  return toString();
@@ -1572,34 +1519,6 @@
             return true;
         }
 
-        /**
-         * Does this Name precede the given binding node in some canonical order?
-         * This predicate is used to order data bindings (via insertion sort)
-         * with some stability.
-         */
-        boolean isSiblingBindingBefore(Name binding) {
-            assert(!binding.isParam());
-            if (isParam())  return true;
-            if (function.equals(binding.function) &&
-                arguments.length == binding.arguments.length) {
-                boolean sawInt = false;
-                for (int i = 0; i < arguments.length; i++) {
-                    Object a1 = arguments[i];
-                    Object a2 = binding.arguments[i];
-                    if (!a1.equals(a2)) {
-                        if (a1 instanceof Integer && a2 instanceof Integer) {
-                            if (sawInt)  continue;
-                            sawInt = true;
-                            if ((int)a1 < (int)a2)  continue;  // still might be true
-                        }
-                        return false;
-                    }
-                }
-                return sawInt;
-            }
-            return false;
-        }
-
         /** Return the index of the last occurrence of n in the argument array.
          *  Return -1 if the name is not used.
          */
@@ -1690,6 +1609,7 @@
     static Name internArgument(Name n) {
         assert(n.isParam()) : "not param: " + n;
         assert(n.index < INTERNED_ARGUMENT_LIMIT);
+        if (n.constraint != null)  return n;
         return argument(n.index, n.type);
     }
     static Name[] arguments(int extra, String types) {
@@ -1858,37 +1778,6 @@
     @interface Hidden {
     }
 
-
-/*
-    // Smoke-test for the invokers used in this file.
-    static void testMethodHandleLinkers() throws Throwable {
-        MemberName.Factory lookup = MemberName.getFactory();
-        MemberName asList_MN = new MemberName(Arrays.class, "asList",
-                                              MethodType.methodType(List.class, Object[].class),
-                                              REF_invokeStatic);
-        //MethodHandleNatives.resolve(asList_MN, null);
-        asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class);
-        System.out.println("about to call "+asList_MN);
-        Object[] abc = { "a", "bc" };
-        List<?> lst = (List<?>) MethodHandle.linkToStatic(abc, asList_MN);
-        System.out.println("lst="+lst);
-        MemberName toString_MN = new MemberName(Object.class.getMethod("toString"));
-        String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN);
-        toString_MN = new MemberName(Object.class.getMethod("toString"), true);
-        String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN);
-        System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString()));
-        MemberName toArray_MN = new MemberName(List.class.getMethod("toArray"));
-        Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN);
-        System.out.println("toArray="+Arrays.toString(arr));
-    }
-    static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } }
-    // Requires these definitions in MethodHandle:
-    static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable;
-    static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable;
-    static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable;
-    static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable;
- */
-
     private static final HashMap<String,Integer> DEBUG_NAME_COUNTERS;
     static {
         if (debugEnabled())
@@ -1901,7 +1790,7 @@
     static {
         createIdentityForms();
         if (USE_PREDEFINED_INTERPRET_METHODS)
-            PREPARED_FORMS.putAll(computeInitialPreparedForms());
+            computeInitialPreparedForms();
         NamedFunction.initializeInvokers();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2013, 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 java.lang.invoke;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.BasicType.*;
+
+/** Working storage for an LF that is being transformed.
+ *  Similarly to a StringBuffer, the editing can take place in multiple steps.
+ */
+final class LambdaFormBuffer {
+    private int arity, length;
+    private Name[] names;
+    private Name[] originalNames;  // snapshot of pre-transaction names
+    private byte flags;
+    private int firstChange;
+    private Name resultName;
+    private String debugName;
+    private ArrayList<Name> dups;
+
+    private static final int F_TRANS = 0x10, F_OWNED = 0x03;
+
+    LambdaFormBuffer(LambdaForm lf) {
+        this(lf.arity, lf.names, lf.result);
+        debugName = lf.debugName;
+        assert(lf.nameRefsAreLegal());
+    }
+
+    private LambdaFormBuffer(int arity, Name[] names, int result) {
+        this.arity = arity;
+        setNames(names);
+        if (result == LAST_RESULT)  result = length - 1;
+        if (result >= 0 && names[result].type != V_TYPE)
+            resultName = names[result];
+    }
+
+    private LambdaForm lambdaForm() {
+        assert(!inTrans());  // need endEdit call to tidy things up
+        return new LambdaForm(debugName, arity, nameArray(), resultIndex());
+    }
+
+    Name name(int i) {
+        assert(i < length);
+        return names[i];
+    }
+
+    Name[] nameArray() {
+        return Arrays.copyOf(names, length);
+    }
+
+    int resultIndex() {
+        if (resultName == null)  return VOID_RESULT;
+        int index = indexOf(resultName, names);
+        assert(index >= 0);
+        return index;
+    }
+
+    void setNames(Name[] names2) {
+        names = originalNames = names2;  // keep a record of where everything was to start with
+        length = names2.length;
+        flags = 0;
+    }
+
+    private boolean verifyArity() {
+        for (int i = 0; i < arity && i < firstChange; i++) {
+            assert(names[i].isParam()) : "#" + i + "=" + names[i];
+        }
+        for (int i = arity; i < length; i++) {
+            assert(!names[i].isParam()) : "#" + i + "=" + names[i];
+        }
+        for (int i = length; i < names.length; i++) {
+            assert(names[i] == null) : "#" + i + "=" + names[i];
+        }
+        // check resultName also
+        if (resultName != null) {
+            int resultIndex = indexOf(resultName, names);
+            assert(resultIndex >= 0) : "not found: " + resultName.exprString() + Arrays.asList(names);
+            assert(names[resultIndex] == resultName);
+        }
+        return true;
+    }
+
+    private boolean verifyFirstChange() {
+        assert(inTrans());
+        for (int i = 0; i < length; i++) {
+            if (names[i] != originalNames[i]) {
+                assert(firstChange == i) : Arrays.asList(firstChange, i, originalNames[i].exprString(), Arrays.asList(names));
+                return true;
+            }
+        }
+        assert(firstChange == length) : Arrays.asList(firstChange, Arrays.asList(names));
+        return true;
+    }
+
+    private static int indexOf(NamedFunction fn, NamedFunction[] fns) {
+        for (int i = 0; i < fns.length; i++) {
+            if (fns[i] == fn)  return i;
+        }
+        return -1;
+    }
+
+    private static int indexOf(Name n, Name[] ns) {
+        for (int i = 0; i < ns.length; i++) {
+            if (ns[i] == n)  return i;
+        }
+        return -1;
+    }
+
+    boolean inTrans() {
+        return (flags & F_TRANS) != 0;
+    }
+
+    int ownedCount() {
+        return flags & F_OWNED;
+    }
+
+    void growNames(int insertPos, int growLength) {
+        int oldLength = length;
+        int newLength = oldLength + growLength;
+        int oc = ownedCount();
+        if (oc == 0 || newLength > names.length) {
+            names = Arrays.copyOf(names, (names.length + growLength) * 5 / 4);
+            if (oc == 0) {
+                flags++;
+                oc++;
+                assert(ownedCount() == oc);
+            }
+        }
+        if (originalNames != null && originalNames.length < names.length) {
+            originalNames = Arrays.copyOf(originalNames, names.length);
+            if (oc == 1) {
+                flags++;
+                oc++;
+                assert(ownedCount() == oc);
+            }
+        }
+        if (growLength == 0)  return;
+        int insertEnd = insertPos + growLength;
+        int tailLength = oldLength - insertPos;
+        System.arraycopy(names, insertPos, names, insertEnd, tailLength);
+        Arrays.fill(names, insertPos, insertEnd, null);
+        if (originalNames != null) {
+            System.arraycopy(originalNames, insertPos, originalNames, insertEnd, tailLength);
+            Arrays.fill(originalNames, insertPos, insertEnd, null);
+        }
+        length = newLength;
+        if (firstChange >= insertPos) {
+            firstChange += growLength;
+        }
+    }
+
+    int lastIndexOf(Name n) {
+        int result = -1;
+        for (int i = 0; i < length; i++) {
+            if (names[i] == n)  result = i;
+        }
+        return result;
+    }
+
+    /** We have just overwritten the name at pos1 with the name at pos2.
+     *  This means that there are two copies of the name, which we will have to fix later.
+     */
+    private void noteDuplicate(int pos1, int pos2) {
+        Name n = names[pos1];
+        assert(n == names[pos2]);
+        assert(originalNames[pos1] != null);  // something was replaced at pos1
+        assert(originalNames[pos2] == null || originalNames[pos2] == n);
+        if (dups == null) {
+            dups = new ArrayList<>();
+        }
+        dups.add(n);
+    }
+
+    /** Replace duplicate names by nulls, and remove all nulls. */
+    private void clearDuplicatesAndNulls() {
+        if (dups != null) {
+            // Remove duplicates.
+            assert(ownedCount() >= 1);
+            for (Name dup : dups) {
+                for (int i = firstChange; i < length; i++) {
+                    if (names[i] == dup && originalNames[i] != dup) {
+                        names[i] = null;
+                        assert(Arrays.asList(names).contains(dup));
+                        break;  // kill only one dup
+                    }
+                }
+            }
+            dups.clear();
+        }
+        // Now that we are done with originalNames, remove "killed" names.
+        int oldLength = length;
+        for (int i = firstChange; i < length; i++) {
+            if (names[i] == null) {
+                System.arraycopy(names, i + 1, names, i, (--length - i));
+                --i;  // restart loop at this position
+            }
+        }
+        if (length < oldLength) {
+            Arrays.fill(names, length, oldLength, null);
+        }
+        assert(!Arrays.asList(names).subList(0, length).contains(null));
+    }
+
+    /** Create a private, writable copy of names.
+     *  Preserve the original copy, for reference.
+     */
+    void startEdit() {
+        assert(verifyArity());
+        int oc = ownedCount();
+        assert(!inTrans());  // no nested transactions
+        flags |= F_TRANS;
+        Name[] oldNames = names;
+        Name[] ownBuffer = (oc == 2 ? originalNames : null);
+        assert(ownBuffer != oldNames);
+        if (ownBuffer != null && ownBuffer.length >= length) {
+            names = copyNamesInto(ownBuffer);
+        } else {
+            // make a new buffer to hold the names
+            final int SLOP = 2;
+            names = Arrays.copyOf(oldNames, Math.max(length + SLOP, oldNames.length));
+            if (oc < 2)  ++flags;
+            assert(ownedCount() == oc + 1);
+        }
+        originalNames = oldNames;
+        assert(originalNames != names);
+        firstChange = length;
+        assert(inTrans());
+    }
+
+    private void changeName(int i, Name name) {
+        assert(inTrans());
+        assert(i < length);
+        Name oldName = names[i];
+        assert(oldName == originalNames[i]);  // no multiple changes
+        assert(verifyFirstChange());
+        if (ownedCount() == 0)
+            growNames(0, 0);
+        names[i] = name;
+        if (firstChange > i) {
+            firstChange = i;
+        }
+        if (resultName != null && resultName == oldName) {
+            resultName = name;
+        }
+    }
+
+    /** Change the result name.  Null means a void result. */
+    void setResult(Name name) {
+        assert(name == null || lastIndexOf(name) >= 0);
+        resultName = name;
+    }
+
+    /** Finish a transaction. */
+    LambdaForm endEdit() {
+        assert(verifyFirstChange());
+        // Assuming names have been changed pairwise from originalNames[i] to names[i],
+        // update arguments to ensure referential integrity.
+        for (int i = Math.max(firstChange, arity); i < length; i++) {
+            Name name = names[i];
+            if (name == null)  continue;  // space for removed duplicate
+            Name newName = name.replaceNames(originalNames, names, firstChange, i);
+            if (newName != name) {
+                names[i] = newName;
+                if (resultName == name) {
+                    resultName = newName;
+                }
+            }
+        }
+        assert(inTrans());
+        flags &= ~F_TRANS;
+        clearDuplicatesAndNulls();
+        originalNames = null;
+        // If any parameters have been changed, then reorder them as needed.
+        // This is a "sheep-and-goats" stable sort, pushing all non-parameters
+        // to the right of all parameters.
+        if (firstChange < arity) {
+            Name[] exprs = new Name[arity - firstChange];
+            int argp = firstChange, exprp = 0;
+            for (int i = firstChange; i < arity; i++) {
+                Name name = names[i];
+                if (name.isParam()) {
+                    names[argp++] = name;
+                } else {
+                    exprs[exprp++] = name;
+                }
+            }
+            assert(exprp == (arity - argp));
+            // copy the exprs just after the last remaining param
+            System.arraycopy(exprs, 0, names, argp, exprp);
+            // adjust arity
+            arity -= exprp;
+        }
+        assert(verifyArity());
+        return lambdaForm();
+    }
+
+    private Name[] copyNamesInto(Name[] buffer) {
+        System.arraycopy(names, 0, buffer, 0, length);
+        Arrays.fill(buffer, length, buffer.length, null);
+        return buffer;
+    }
+
+    /** Replace any Name whose function is in oldFns with a copy
+     *  whose function is in the corresponding position in newFns.
+     *  Only do this if the arguments are exactly equal to the given.
+     */
+    LambdaFormBuffer replaceFunctions(NamedFunction[] oldFns, NamedFunction[] newFns,
+                                      Object... forArguments) {
+        assert(inTrans());
+        if (oldFns.length == 0)  return this;
+        for (int i = arity; i < length; i++) {
+            Name n = names[i];
+            int nfi = indexOf(n.function, oldFns);
+            if (nfi >= 0 && Arrays.equals(n.arguments, forArguments)) {
+                changeName(i, new Name(newFns[nfi], n.arguments));
+            }
+        }
+        return this;
+    }
+
+    private void replaceName(int pos, Name binding) {
+        assert(inTrans());
+        assert(verifyArity());
+        assert(pos < arity);
+        Name param = names[pos];
+        assert(param.isParam());
+        assert(param.type == binding.type);
+        changeName(pos, binding);
+    }
+
+    /** Replace a parameter by a fresh parameter. */
+    LambdaFormBuffer renameParameter(int pos, Name newParam) {
+        assert(newParam.isParam());
+        replaceName(pos, newParam);
+        return this;
+    }
+
+    /** Replace a parameter by a fresh expression. */
+    LambdaFormBuffer replaceParameterByNewExpression(int pos, Name binding) {
+        assert(!binding.isParam());
+        assert(lastIndexOf(binding) < 0);  // else use replaceParameterByCopy
+        replaceName(pos, binding);
+        return this;
+    }
+
+    /** Replace a parameter by another parameter or expression already in the form. */
+    LambdaFormBuffer replaceParameterByCopy(int pos, int valuePos) {
+        assert(pos != valuePos);
+        replaceName(pos, names[valuePos]);
+        noteDuplicate(pos, valuePos);  // temporarily, will occur twice in the names array
+        return this;
+    }
+
+    private void insertName(int pos, Name expr, boolean isParameter) {
+        assert(inTrans());
+        assert(verifyArity());
+        assert(isParameter ? pos <= arity : pos >= arity);
+        growNames(pos, 1);
+        if (isParameter)  arity += 1;
+        changeName(pos, expr);
+    }
+
+    /** Insert a fresh expression. */
+    LambdaFormBuffer insertExpression(int pos, Name expr) {
+        assert(!expr.isParam());
+        insertName(pos, expr, false);
+        return this;
+    }
+
+    /** Insert a fresh parameter. */
+    LambdaFormBuffer insertParameter(int pos, Name param) {
+        assert(param.isParam());
+        insertName(pos, param, true);
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 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 java.lang.invoke;
+
+import java.util.Arrays;
+import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.BasicType.*;
+import static java.lang.invoke.MethodHandleImpl.Intrinsic;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+
+import sun.invoke.util.Wrapper;
+
+/** Transforms on LFs.
+ *  A lambda-form editor can derive new LFs from its base LF.
+ *  The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes.
+ *  To support this caching, a LF has an optional pointer to its editor.
+ */
+class LambdaFormEditor {
+    final LambdaForm lambdaForm;
+
+    private LambdaFormEditor(LambdaForm lambdaForm) {
+        this.lambdaForm = lambdaForm;
+    }
+
+    // Factory method.
+    static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) {
+        // TO DO:  Consider placing intern logic here, to cut down on duplication.
+        // lambdaForm = findPreexistingEquivalent(lambdaForm)
+        return new LambdaFormEditor(lambdaForm);
+    }
+
+    /** A description of a cached transform, possibly associated with the result of the transform.
+     *  The logical content is a sequence of byte values, starting with a Kind.ordinal value.
+     *  The sequence is unterminated, ending with an indefinite number of zero bytes.
+     *  Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
+     */
+    private static final class Transform {
+        final long packedBytes;
+        final byte[] fullBytes;
+        final LambdaForm result;  // result of transform, or null, if there is none available
+
+        private enum Kind {
+            NO_KIND,  // necessary because ordinal must be greater than zero
+            BIND_ARG, ADD_ARG, DUP_ARG,
+            SPREAD_ARGS,
+            FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO,
+            COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY,
+            FOLD_ARGS, FOLD_ARGS_TO_VOID,
+            PERMUTE_ARGS
+            //maybe add more for guard with test, catch exception, pointwise type conversions
+        }
+
+        private static final boolean STRESS_TEST = false; // turn on to disable most packing
+        private static final int
+                PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4),
+                PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1,
+                PACKED_BYTE_MAX_LENGTH = (STRESS_TEST ? 3 : 64 / PACKED_BYTE_SIZE);
+
+        private static long packedBytes(byte[] bytes) {
+            if (bytes.length > PACKED_BYTE_MAX_LENGTH)  return 0;
+            long pb = 0;
+            int bitset = 0;
+            for (int i = 0; i < bytes.length; i++) {
+                int b = bytes[i] & 0xFF;
+                bitset |= b;
+                pb |= (long)b << (i * PACKED_BYTE_SIZE);
+            }
+            if (!inRange(bitset))
+                return 0;
+            return pb;
+        }
+        private static long packedBytes(int b0, int b1) {
+            assert(inRange(b0 | b1));
+            return (  (b0 << 0*PACKED_BYTE_SIZE)
+                    | (b1 << 1*PACKED_BYTE_SIZE));
+        }
+        private static long packedBytes(int b0, int b1, int b2) {
+            assert(inRange(b0 | b1 | b2));
+            return (  (b0 << 0*PACKED_BYTE_SIZE)
+                    | (b1 << 1*PACKED_BYTE_SIZE)
+                    | (b2 << 2*PACKED_BYTE_SIZE));
+        }
+        private static long packedBytes(int b0, int b1, int b2, int b3) {
+            assert(inRange(b0 | b1 | b2 | b3));
+            return (  (b0 << 0*PACKED_BYTE_SIZE)
+                    | (b1 << 1*PACKED_BYTE_SIZE)
+                    | (b2 << 2*PACKED_BYTE_SIZE)
+                    | (b3 << 3*PACKED_BYTE_SIZE));
+        }
+        private static boolean inRange(int bitset) {
+            assert((bitset & 0xFF) == bitset);  // incoming values must fit in *unsigned* byte
+            return ((bitset & ~PACKED_BYTE_MASK) == 0);
+        }
+        private static byte[] fullBytes(int... byteValues) {
+            byte[] bytes = new byte[byteValues.length];
+            int i = 0;
+            for (int bv : byteValues) {
+                bytes[i++] = bval(bv);
+            }
+            assert(packedBytes(bytes) == 0);
+            return bytes;
+        }
+
+        private byte byteAt(int i) {
+            long pb = packedBytes;
+            if (pb == 0) {
+                if (i >= fullBytes.length)  return 0;
+                return fullBytes[i];
+            }
+            assert(fullBytes == null);
+            if (i > PACKED_BYTE_MAX_LENGTH)  return 0;
+            int pos = (i * PACKED_BYTE_SIZE);
+            return (byte)((pb >>> pos) & PACKED_BYTE_MASK);
+        }
+
+        Kind kind() { return Kind.values()[byteAt(0)]; }
+
+        private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
+            this.packedBytes = packedBytes;
+            this.fullBytes = fullBytes;
+            this.result = result;
+        }
+        private Transform(long packedBytes) {
+            this(packedBytes, null, null);
+            assert(packedBytes != 0);
+        }
+        private Transform(byte[] fullBytes) {
+            this(0, fullBytes, null);
+        }
+
+        private static byte bval(int b) {
+            assert((b & 0xFF) == b);  // incoming value must fit in *unsigned* byte
+            return (byte)b;
+        }
+        private static byte bval(Kind k) {
+            return bval(k.ordinal());
+        }
+        static Transform of(Kind k, int b1) {
+            byte b0 = bval(k);
+            if (inRange(b0 | b1))
+                return new Transform(packedBytes(b0, b1));
+            else
+                return new Transform(fullBytes(b0, b1));
+        }
+        static Transform of(Kind k, int b1, int b2) {
+            byte b0 = (byte) k.ordinal();
+            if (inRange(b0 | b1 | b2))
+                return new Transform(packedBytes(b0, b1, b2));
+            else
+                return new Transform(fullBytes(b0, b1, b2));
+        }
+        static Transform of(Kind k, int b1, int b2, int b3) {
+            byte b0 = (byte) k.ordinal();
+            if (inRange(b0 | b1 | b2 | b3))
+                return new Transform(packedBytes(b0, b1, b2, b3));
+            else
+                return new Transform(fullBytes(b0, b1, b2, b3));
+        }
+        private static final byte[] NO_BYTES = {};
+        static Transform of(Kind k, int... b123) {
+            return ofBothArrays(k, b123, NO_BYTES);
+        }
+        static Transform of(Kind k, int b1, byte[] b234) {
+            return ofBothArrays(k, new int[]{ b1 }, b234);
+        }
+        static Transform of(Kind k, int b1, int b2, byte[] b345) {
+            return ofBothArrays(k, new int[]{ b1, b2 }, b345);
+        }
+        private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) {
+            byte[] fullBytes = new byte[1 + b123.length + b456.length];
+            int i = 0;
+            fullBytes[i++] = bval(k);
+            for (int bv : b123) {
+                fullBytes[i++] = bval(bv);
+            }
+            for (byte bv : b456) {
+                fullBytes[i++] = bv;
+            }
+            long packedBytes = packedBytes(fullBytes);
+            if (packedBytes != 0)
+                return new Transform(packedBytes);
+            else
+                return new Transform(fullBytes);
+        }
+
+        Transform withResult(LambdaForm result) {
+            return new Transform(this.packedBytes, this.fullBytes, result);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return obj instanceof Transform && equals((Transform)obj);
+        }
+        public boolean equals(Transform that) {
+            return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
+        }
+        @Override
+        public int hashCode() {
+            if (packedBytes != 0) {
+                assert(fullBytes == null);
+                return Long.hashCode(packedBytes);
+            }
+            return Arrays.hashCode(fullBytes);
+        }
+        @Override
+        public String toString() {
+            StringBuilder buf = new StringBuilder();
+            long bits = packedBytes;
+            if (bits != 0) {
+                buf.append("(");
+                while (bits != 0) {
+                    buf.append(bits & PACKED_BYTE_MASK);
+                    bits >>>= PACKED_BYTE_SIZE;
+                    if (bits != 0)  buf.append(",");
+                }
+                buf.append(")");
+            }
+            if (fullBytes != null) {
+                buf.append("unpacked");
+                buf.append(Arrays.toString(fullBytes));
+            }
+            if (result != null) {
+                buf.append(" result=");
+                buf.append(result);
+            }
+            return buf.toString();
+        }
+    }
+
+    /** Find a previously cached transform equivalent to the given one, and return its result. */
+    private LambdaForm getInCache(Transform key) {
+        assert(key.result == null);
+        // The transformCache is one of null, Transform, Transform[], or ConcurrentHashMap.
+        Object c = lambdaForm.transformCache;
+        Transform k = null;
+        if (c instanceof ConcurrentHashMap) {
+            @SuppressWarnings("unchecked")
+            ConcurrentHashMap<Transform,Transform> m = (ConcurrentHashMap<Transform,Transform>) c;
+            k = m.get(key);
+        } else if (c == null) {
+            return null;
+        } else if (c instanceof Transform) {
+            // one-element cache avoids overhead of an array
+            Transform t = (Transform)c;
+            if (t.equals(key))  k = t;
+        } else {
+            Transform[] ta = (Transform[])c;
+            for (int i = 0; i < ta.length; i++) {
+                Transform t = ta[i];
+                if (t == null)  break;
+                if (t.equals(key)) { k = t; break; }
+            }
+        }
+        assert(k == null || key.equals(k));
+        return k == null ? null : k.result;
+    }
+
+    /** Arbitrary but reasonable limits on Transform[] size for cache. */
+    private static final int MIN_CACHE_ARRAY_SIZE = 4, MAX_CACHE_ARRAY_SIZE = 16;
+
+    /** Cache a transform with its result, and return that result.
+     *  But if an equivalent transform has already been cached, return its result instead.
+     */
+    private LambdaForm putInCache(Transform key, LambdaForm form) {
+        key = key.withResult(form);
+        for (int pass = 0; ; pass++) {
+            Object c = lambdaForm.transformCache;
+            if (c instanceof ConcurrentHashMap) {
+                @SuppressWarnings("unchecked")
+                ConcurrentHashMap<Transform,Transform> m = (ConcurrentHashMap<Transform,Transform>) c;
+                Transform k = m.putIfAbsent(key, key);
+                return k != null ? k.result : form;
+            }
+            assert(pass == 0);
+            synchronized (lambdaForm) {
+                c = lambdaForm.transformCache;
+                if (c instanceof ConcurrentHashMap)
+                    continue;
+                if (c == null) {
+                    lambdaForm.transformCache = key;
+                    return form;
+                }
+                Transform[] ta;
+                if (c instanceof Transform) {
+                    Transform k = (Transform)c;
+                    if (k.equals(key)) {
+                        return k.result;
+                    }
+                    // expand one-element cache to small array
+                    ta = new Transform[MIN_CACHE_ARRAY_SIZE];
+                    ta[0] = k;
+                    lambdaForm.transformCache = c = ta;
+                } else {
+                    // it is already expanded
+                    ta = (Transform[])c;
+                }
+                int len = ta.length;
+                int i;
+                for (i = 0; i < len; i++) {
+                    Transform k = ta[i];
+                    if (k == null) {
+                        break;
+                    }
+                    if (k.equals(key)) {
+                        return k.result;
+                    }
+                }
+                if (i < len) {
+                    // just fall through to cache update
+                } else if (len < MAX_CACHE_ARRAY_SIZE) {
+                    len = Math.min(len * 2, MAX_CACHE_ARRAY_SIZE);
+                    ta = Arrays.copyOf(ta, len);
+                    lambdaForm.transformCache = ta;
+                } else {
+                    ConcurrentHashMap<Transform, Transform> m = new ConcurrentHashMap<>(MAX_CACHE_ARRAY_SIZE * 2);
+                    for (Transform k : ta) {
+                        m.put(k, k);
+                    }
+                    lambdaForm.transformCache = m;
+                    // The second iteration will update for this query, concurrently.
+                    continue;
+                }
+                ta[i] = key;
+                return form;
+            }
+        }
+    }
+
+    private LambdaFormBuffer buffer() {
+        return new LambdaFormBuffer(lambdaForm);
+    }
+
+    /// Editing methods for method handles.  These need to have fast paths.
+
+    private BoundMethodHandle.SpeciesData oldSpeciesData() {
+        return BoundMethodHandle.speciesData(lambdaForm);
+    }
+    private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) {
+        return oldSpeciesData().extendWith(type);
+    }
+
+    BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = L_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendL(type2, form2, value);
+    }
+    BoundMethodHandle bindArgumentI(BoundMethodHandle mh, int pos, int value) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = I_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendI(type2, form2, value);
+    }
+
+    BoundMethodHandle bindArgumentJ(BoundMethodHandle mh, int pos, long value) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = J_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendJ(type2, form2, value);
+    }
+
+    BoundMethodHandle bindArgumentF(BoundMethodHandle mh, int pos, float value) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = F_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendF(type2, form2, value);
+    }
+
+    BoundMethodHandle bindArgumentD(BoundMethodHandle mh, int pos, double value) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = D_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendD(type2, form2, value);
+    }
+
+    private MethodType bindArgumentType(BoundMethodHandle mh, int pos, BasicType bt) {
+        assert(mh.form == lambdaForm);
+        assert(mh.form.names[1+pos].type == bt);
+        assert(BasicType.basicType(mh.type().parameterType(pos)) == bt);
+        return mh.type().dropParameterTypes(pos, pos+1);
+    }
+
+    /// Editing methods for lambda forms.
+    // Each editing method can (potentially) cache the edited LF so that it can be reused later.
+
+    LambdaForm bindArgumentForm(int pos) {
+        Transform key = Transform.of(Transform.Kind.BIND_ARG, pos);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
+        BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos));
+        Name oldBaseAddress = lambdaForm.parameter(0);  // BMH holding the values
+        Name newBaseAddress;
+        NamedFunction getter = newData.getterFunction(oldData.fieldCount());
+
+        if (pos != 0) {
+            // The newly created LF will run with a different BMH.
+            // Switch over any pre-existing BMH field references to the new BMH class.
+            buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
+            newBaseAddress = oldBaseAddress.withConstraint(newData);
+            buf.renameParameter(0, newBaseAddress);
+            buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
+        } else {
+            // cannot bind the MH arg itself, unless oldData is empty
+            assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
+            newBaseAddress = new Name(L_TYPE).withConstraint(newData);
+            buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
+            buf.insertParameter(0, newBaseAddress);
+        }
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm addArgumentForm(int pos, BasicType type) {
+        Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal());
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity+1);
+            assert(form.parameterType(pos) == type);
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        buf.insertParameter(pos, new Name(type));
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm dupArgumentForm(int srcPos, int dstPos) {
+        Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity-1);
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        assert(lambdaForm.parameter(srcPos).constraint == null);
+        assert(lambdaForm.parameter(dstPos).constraint == null);
+        buf.replaceParameterByCopy(dstPos, srcPos);
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm spreadArgumentsForm(int pos, Class<?> arrayType, int arrayLength) {
+        Class<?> elementType = arrayType.getComponentType();
+        Class<?> erasedArrayType = arrayType;
+        if (!elementType.isPrimitive())
+            erasedArrayType = Object[].class;
+        BasicType bt = basicType(elementType);
+        int elementTypeKey = bt.ordinal();
+        if (bt.basicTypeClass() != elementType) {
+            if (elementType.isPrimitive()) {
+                elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
+            }
+        }
+        Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity - arrayLength + 1);
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        assert(pos <= MethodType.MAX_JVM_ARITY);
+        assert(pos + arrayLength <= lambdaForm.arity);
+        assert(pos > 0);  // cannot spread the MH arg itself
+
+        Name spreadParam = new Name(L_TYPE);
+        Name checkSpread = new Name(MethodHandleImpl.Lazy.NF_checkSpreadArgument, spreadParam, arrayLength);
+
+        // insert the new expressions
+        int exprPos = lambdaForm.arity();
+        buf.insertExpression(exprPos++, checkSpread);
+        // adjust the arguments
+        MethodHandle aload = MethodHandles.arrayElementGetter(erasedArrayType);
+        for (int i = 0; i < arrayLength; i++) {
+            Name loadArgument = new Name(aload, spreadParam, i);
+            buf.insertExpression(exprPos + i, loadArgument);
+            buf.replaceParameterByCopy(pos + i, exprPos + i);
+        }
+        buf.insertParameter(pos, spreadParam);
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm collectArgumentsForm(int pos, MethodType collectorType) {
+        int collectorArity = collectorType.parameterCount();
+        boolean dropResult = (collectorType.returnType() == void.class);
+        if (collectorArity == 1 && !dropResult) {
+            return filterArgumentForm(pos, basicType(collectorType.parameterType(0)));
+        }
+        BasicType[] newTypes = BasicType.basicTypes(collectorType.parameterList());
+        Transform.Kind kind = (dropResult
+                ? Transform.Kind.COLLECT_ARGS_TO_VOID
+                : Transform.Kind.COLLECT_ARGS);
+        if (dropResult && collectorArity == 0)  pos = 1;  // pure side effect
+        Transform key = Transform.of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes));
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity);
+            return form;
+        }
+        form = makeArgumentCombinationForm(pos, collectorType, false, dropResult);
+        return putInCache(key, form);
+    }
+
+    LambdaForm collectArgumentArrayForm(int pos, MethodHandle arrayCollector) {
+        MethodType collectorType = arrayCollector.type();
+        int collectorArity = collectorType.parameterCount();
+        assert(arrayCollector.intrinsicName() == Intrinsic.NEW_ARRAY);
+        Class<?> arrayType = collectorType.returnType();
+        Class<?> elementType = arrayType.getComponentType();
+        BasicType argType = basicType(elementType);
+        int argTypeKey = argType.ordinal();
+        if (argType.basicTypeClass() != elementType) {
+            // return null if it requires more metadata (like String[].class)
+            if (!elementType.isPrimitive())
+                return null;
+            argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
+        }
+        assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType)));
+        Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY;
+        Transform key = Transform.of(kind, pos, collectorArity, argTypeKey);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity - 1 + collectorArity);
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        assert(pos + 1 <= lambdaForm.arity);
+        assert(pos > 0);  // cannot filter the MH arg itself
+
+        Name[] newParams = new Name[collectorArity];
+        for (int i = 0; i < collectorArity; i++) {
+            newParams[i] = new Name(pos + i, argType);
+        }
+        Name callCombiner = new Name(arrayCollector, (Object[]) /*...*/ newParams);
+
+        // insert the new expression
+        int exprPos = lambdaForm.arity();
+        buf.insertExpression(exprPos, callCombiner);
+
+        // insert new arguments
+        int argPos = pos + 1;  // skip result parameter
+        for (Name newParam : newParams) {
+            buf.insertParameter(argPos++, newParam);
+        }
+        assert(buf.lastIndexOf(callCombiner) == exprPos+newParams.length);
+        buf.replaceParameterByCopy(pos, exprPos+newParams.length);
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm filterArgumentForm(int pos, BasicType newType) {
+        Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal());
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity);
+            assert(form.parameterType(pos) == newType);
+            return form;
+        }
+
+        BasicType oldType = lambdaForm.parameterType(pos);
+        MethodType filterType = MethodType.methodType(oldType.basicTypeClass(),
+                newType.basicTypeClass());
+        form = makeArgumentCombinationForm(pos, filterType, false, false);
+        return putInCache(key, form);
+    }
+
+    private LambdaForm makeArgumentCombinationForm(int pos,
+                                                   MethodType combinerType,
+                                                   boolean keepArguments, boolean dropResult) {
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+        int combinerArity = combinerType.parameterCount();
+        int resultArity = (dropResult ? 0 : 1);
+
+        assert(pos <= MethodType.MAX_JVM_ARITY);
+        assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= lambdaForm.arity);
+        assert(pos > 0);  // cannot filter the MH arg itself
+        assert(combinerType == combinerType.basicType());
+        assert(combinerType.returnType() != void.class || dropResult);
+
+        BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
+        BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE);
+
+        // The newly created LF will run with a different BMH.
+        // Switch over any pre-existing BMH field references to the new BMH class.
+        Name oldBaseAddress = lambdaForm.parameter(0);  // BMH holding the values
+        buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
+        Name newBaseAddress = oldBaseAddress.withConstraint(newData);
+        buf.renameParameter(0, newBaseAddress);
+
+        Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress);
+        Object[] combinerArgs = new Object[1 + combinerArity];
+        combinerArgs[0] = getCombiner;
+        Name[] newParams;
+        if (keepArguments) {
+            newParams = new Name[0];
+            System.arraycopy(lambdaForm.names, pos + resultArity,
+                             combinerArgs, 1, combinerArity);
+        } else {
+            newParams = new Name[combinerArity];
+            BasicType[] newTypes = basicTypes(combinerType.parameterList());
+            for (int i = 0; i < newTypes.length; i++) {
+                newParams[i] = new Name(pos + i, newTypes[i]);
+            }
+            System.arraycopy(newParams, 0,
+                             combinerArgs, 1, combinerArity);
+        }
+        Name callCombiner = new Name(combinerType, combinerArgs);
+
+        // insert the two new expressions
+        int exprPos = lambdaForm.arity();
+        buf.insertExpression(exprPos+0, getCombiner);
+        buf.insertExpression(exprPos+1, callCombiner);
+
+        // insert new arguments, if needed
+        int argPos = pos + resultArity;  // skip result parameter
+        for (Name newParam : newParams) {
+            buf.insertParameter(argPos++, newParam);
+        }
+        assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length);
+        if (!dropResult) {
+            buf.replaceParameterByCopy(pos, exprPos+1+newParams.length);
+        }
+
+        return buf.endEdit();
+    }
+
+    LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
+        Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN);
+        Transform key = Transform.of(kind, newType.ordinal());
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity);
+            assert(form.returnType() == newType);
+            return form;
+        }
+        LambdaFormBuffer buf = buffer();
+        buf.startEdit();
+
+        int insPos = lambdaForm.names.length;
+        Name callFilter;
+        if (constantZero) {
+            // Synthesize a constant zero value for the given type.
+            if (newType == V_TYPE)
+                callFilter = null;
+            else
+                callFilter = new Name(constantZero(newType));
+        } else {
+            BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
+            BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE);
+
+            // The newly created LF will run with a different BMH.
+            // Switch over any pre-existing BMH field references to the new BMH class.
+            Name oldBaseAddress = lambdaForm.parameter(0);  // BMH holding the values
+            buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
+            Name newBaseAddress = oldBaseAddress.withConstraint(newData);
+            buf.renameParameter(0, newBaseAddress);
+
+            Name getFilter = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress);
+            buf.insertExpression(insPos++, getFilter);
+            BasicType oldType = lambdaForm.returnType();
+            if (oldType == V_TYPE) {
+                MethodType filterType = MethodType.methodType(newType.basicTypeClass());
+                callFilter = new Name(filterType, getFilter);
+            } else {
+                MethodType filterType = MethodType.methodType(newType.basicTypeClass(), oldType.basicTypeClass());
+                callFilter = new Name(filterType, getFilter, lambdaForm.names[lambdaForm.result]);
+            }
+        }
+
+        if (callFilter != null)
+            buf.insertExpression(insPos++, callFilter);
+        buf.setResult(callFilter);
+
+        form = buf.endEdit();
+        return putInCache(key, form);
+    }
+
+    LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
+        int combinerArity = combinerType.parameterCount();
+        Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS);
+        Transform key = Transform.of(kind, foldPos, combinerArity);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0));
+            return form;
+        }
+        form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
+        return putInCache(key, form);
+    }
+
+    LambdaForm permuteArgumentsForm(int skip, int[] reorder) {
+        assert(skip == 1);  // skip only the leading MH argument, names[0]
+        int length = lambdaForm.names.length;
+        int outArgs = reorder.length;
+        int inTypes = 0;
+        boolean nullPerm = true;
+        for (int i = 0; i < reorder.length; i++) {
+            int inArg = reorder[i];
+            if (inArg != i)  nullPerm = false;
+            inTypes = Math.max(inTypes, inArg+1);
+        }
+        assert(skip + reorder.length == lambdaForm.arity);
+        if (nullPerm)  return lambdaForm;  // do not bother to cache
+        Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder);
+        LambdaForm form = getInCache(key);
+        if (form != null) {
+            assert(form.arity == skip+inTypes) : form;
+            return form;
+        }
+
+        BasicType[] types = new BasicType[inTypes];
+        for (int i = 0; i < outArgs; i++) {
+            int inArg = reorder[i];
+            types[inArg] = lambdaForm.names[skip + i].type;
+        }
+        assert (skip + outArgs == lambdaForm.arity);
+        assert (permutedTypesMatch(reorder, types, lambdaForm.names, skip));
+        int pos = 0;
+        while (pos < outArgs && reorder[pos] == pos) {
+            pos += 1;
+        }
+        Name[] names2 = new Name[length - outArgs + inTypes];
+        System.arraycopy(lambdaForm.names, 0, names2, 0, skip + pos);
+        int bodyLength = length - lambdaForm.arity;
+        System.arraycopy(lambdaForm.names, skip + outArgs, names2, skip + inTypes, bodyLength);
+        int arity2 = names2.length - bodyLength;
+        int result2 = lambdaForm.result;
+        if (result2 >= 0) {
+            if (result2 < skip + outArgs) {
+                result2 = reorder[result2 - skip];
+            } else {
+                result2 = result2 - outArgs + inTypes;
+            }
+        }
+        for (int j = pos; j < outArgs; j++) {
+            Name n = lambdaForm.names[skip + j];
+            int i = reorder[j];
+            Name n2 = names2[skip + i];
+            if (n2 == null) {
+                names2[skip + i] = n2 = new Name(types[i]);
+            } else {
+                assert (n2.type == types[i]);
+            }
+            for (int k = arity2; k < names2.length; k++) {
+                names2[k] = names2[k].replaceName(n, n2);
+            }
+        }
+        for (int i = skip + pos; i < arity2; i++) {
+            if (names2[i] == null) {
+                names2[i] = argument(i, types[i - skip]);
+            }
+        }
+        for (int j = lambdaForm.arity; j < lambdaForm.names.length; j++) {
+            int i = j - lambdaForm.arity + arity2;
+            Name n = lambdaForm.names[j];
+            Name n2 = names2[i];
+            if (n != n2) {
+                for (int k = i + 1; k < names2.length; k++) {
+                    names2[k] = names2[k].replaceName(n, n2);
+                }
+            }
+        }
+
+        form = new LambdaForm(lambdaForm.debugName, arity2, names2, result2);
+        return putInCache(key, form);
+    }
+
+    static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) {
+        for (int i = 0; i < reorder.length; i++) {
+            assert (names[skip + i].isParam());
+            assert (names[skip + i].type == types[reorder[i]]);
+        }
+        return true;
+    }
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Wed Jul 05 20:00:59 2017 +0200
@@ -327,10 +327,6 @@
         assert(getReferenceKind() == oldKind);
         assert(MethodHandleNatives.refKindIsValid(refKind));
         flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
-//        if (isConstructor() && refKind != REF_newInvokeSpecial)
-//            flags += (IS_METHOD - IS_CONSTRUCTOR);
-//        else if (refKind == REF_newInvokeSpecial && isMethod())
-//            flags += (IS_CONSTRUCTOR - IS_METHOD);
         return this;
     }
 
@@ -344,9 +340,11 @@
         return !testFlags(mask, 0);
     }
 
-    /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
+    /** Utility method to query if this member is a method handle invocation (invoke or invokeExact).
+     *  Also returns true for the non-public MH.invokeBasic.
+     */
     public boolean isMethodHandleInvoke() {
-        final int bits = MH_INVOKE_MODS;
+        final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
         final int negs = Modifier.STATIC;
         if (testFlags(bits | negs, bits) &&
             clazz == MethodHandle.class) {
@@ -355,7 +353,14 @@
         return false;
     }
     public static boolean isMethodHandleInvokeName(String name) {
-        return name.equals("invoke") || name.equals("invokeExact");
+        switch (name) {
+        case "invoke":
+        case "invokeExact":
+        case "invokeBasic":  // internal sig-poly method
+            return true;
+        default:
+            return false;
+        }
     }
     private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
 
@@ -720,16 +725,8 @@
         init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
         initResolved(false);
     }
-    /** Create a field or type name from the given components:  Declaring class, name, type.
-     *  The declaring class may be supplied as null if this is to be a bare name and type.
-     *  The modifier flags default to zero.
-     *  The resulting name will in an unresolved state.
-     */
-    public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
-        this(defClass, name, type, REF_NONE);
-        initResolved(false);
-    }
-    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
+    /** Create a method or constructor name from the given components:
+     *  Declaring class, name, type, reference kind.
      *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
      *  The declaring class may be supplied as null if this is to be a bare name and type.
      *  The last argument is optional, a boolean which requests REF_invokeSpecial.
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,12 +27,8 @@
 
 
 import java.util.*;
-import java.lang.invoke.LambdaForm.BasicType;
-import sun.invoke.util.*;
-import sun.misc.Unsafe;
 
 import static java.lang.invoke.MethodHandleStatics.*;
-import static java.lang.invoke.LambdaForm.BasicType.*;
 
 /**
  * A method handle is a typed, directly executable reference to an underlying method,
@@ -625,15 +621,8 @@
      * @see MethodHandles#spreadInvoker
      */
     public Object invokeWithArguments(Object... arguments) throws Throwable {
-        int argc = arguments == null ? 0 : arguments.length;
-        @SuppressWarnings("LocalVariableHidesMemberVariable")
-        MethodType type = type();
-        if (type.parameterCount() != argc || isVarargsCollector()) {
-            // simulate invoke
-            return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
-        }
-        MethodHandle invoker = type.invokers().varargsInvoker();
-        return invoker.invokeExact(this, arguments);
+        MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length);
+        return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments);
     }
 
     /**
@@ -763,18 +752,26 @@
             return this;
         }
         // Return 'this.asTypeCache' if the conversion is already memoized.
+        MethodHandle atc = asTypeCached(newType);
+        if (atc != null) {
+            return atc;
+        }
+        return asTypeUncached(newType);
+    }
+
+    private MethodHandle asTypeCached(MethodType newType) {
         MethodHandle atc = asTypeCache;
         if (atc != null && newType == atc.type) {
             return atc;
         }
-        return asTypeUncached(newType);
+        return null;
     }
 
     /** Override this to change asType behavior. */
     /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
         if (!type.isConvertibleTo(newType))
             throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
-        return asTypeCache = convertArguments(newType);
+        return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true);
     }
 
     /**
@@ -867,34 +864,48 @@
      * @see #asCollector
      */
     public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
-        asSpreaderChecks(arrayType, arrayLength);
-        int spreadArgPos = type.parameterCount() - arrayLength;
-        return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
+        MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength);
+        int arity = type().parameterCount();
+        int spreadArgPos = arity - arrayLength;
+        if (USE_LAMBDA_FORM_EDITOR) {
+            MethodHandle afterSpread = this.asType(postSpreadType);
+            BoundMethodHandle mh = afterSpread.rebind();
+            LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength);
+            MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType);
+            return mh.copyWith(preSpreadType, lform);
+        } else {
+            return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
+        }
     }
 
-    private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
+    /**
+     * See if {@code asSpreader} can be validly called with the given arguments.
+     * Return the type of the method handle call after spreading but before conversions.
+     */
+    private MethodType asSpreaderChecks(Class<?> arrayType, int arrayLength) {
         spreadArrayChecks(arrayType, arrayLength);
         int nargs = type().parameterCount();
         if (nargs < arrayLength || arrayLength < 0)
             throw newIllegalArgumentException("bad spread array length");
-        if (arrayType != Object[].class && arrayLength != 0) {
-            boolean sawProblem = false;
-            Class<?> arrayElement = arrayType.getComponentType();
-            for (int i = nargs - arrayLength; i < nargs; i++) {
-                if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
-                    sawProblem = true;
+        Class<?> arrayElement = arrayType.getComponentType();
+        MethodType mtype = type();
+        boolean match = true, fail = false;
+        for (int i = nargs - arrayLength; i < nargs; i++) {
+            Class<?> ptype = mtype.parameterType(i);
+            if (ptype != arrayElement) {
+                match = false;
+                if (!MethodType.canConvert(arrayElement, ptype)) {
+                    fail = true;
                     break;
                 }
             }
-            if (sawProblem) {
-                ArrayList<Class<?>> ptypes = new ArrayList<>(type().parameterList());
-                for (int i = nargs - arrayLength; i < nargs; i++) {
-                    ptypes.set(i, arrayElement);
-                }
-                // elicit an error:
-                this.asType(MethodType.methodType(type().returnType(), ptypes));
-            }
         }
+        if (match)  return mtype;
+        MethodType needType = mtype.asSpreaderType(arrayType, arrayLength);
+        if (!fail)  return needType;
+        // elicit an error:
+        this.asType(needType);
+        throw newInternalError("should not return", null);
     }
 
     private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
@@ -984,16 +995,31 @@
      */
     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
         asCollectorChecks(arrayType, arrayLength);
-        int collectArgPos = type().parameterCount()-1;
-        MethodHandle target = this;
-        if (arrayType != type().parameterType(collectArgPos))
-            target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
-        MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength);
-        return MethodHandles.collectArguments(target, collectArgPos, collector);
+        int collectArgPos = type().parameterCount() - 1;
+        if (USE_LAMBDA_FORM_EDITOR) {
+            BoundMethodHandle mh = rebind();
+            MethodType resultType = type().asCollectorType(arrayType, arrayLength);
+            MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
+            LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray);
+            if (lform != null) {
+                return mh.copyWith(resultType, lform);
+            }
+            lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType());
+            return mh.copyWithExtendL(resultType, lform, newArray);
+        } else {
+            MethodHandle target = this;
+            if (arrayType != type().parameterType(collectArgPos))
+                target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), true);
+            MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
+            return MethodHandles.collectArguments(target, collectArgPos, collector);
+        }
     }
 
-    // private API: return true if last param exactly matches arrayType
-    private boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
+    /**
+     * See if {@code asCollector} can be validly called with the given arguments.
+     * Return false if the last parameter is not an exact match to arrayType.
+     */
+    /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
         spreadArrayChecks(arrayType, arrayLength);
         int nargs = type().parameterCount();
         if (nargs != 0) {
@@ -1155,7 +1181,7 @@
      * @see #asFixedArity
      */
     public MethodHandle asVarargsCollector(Class<?> arrayType) {
-        Class<?> arrayElement = arrayType.getComponentType();
+        arrayType.getClass(); // explicit NPE
         boolean lastMatch = asCollectorChecks(arrayType, 0);
         if (isVarargsCollector() && lastMatch)
             return this;
@@ -1257,14 +1283,8 @@
      * @see MethodHandles#insertArguments
      */
     public MethodHandle bindTo(Object x) {
-        Class<?> ptype;
-        @SuppressWarnings("LocalVariableHidesMemberVariable")
-        MethodType type = type();
-        if (type.parameterCount() == 0 ||
-            (ptype = type.parameterType(0)).isPrimitive())
-            throw newIllegalArgumentException("no leading reference parameter", x);
-        x = ptype.cast(x);  // throw CCE if needed
-        return bindReceiver(x);
+        x = type.leadingReferenceParameter().cast(x);  // throw CCE if needed
+        return bindArgumentL(0, x);
     }
 
     /**
@@ -1284,14 +1304,17 @@
      */
     @Override
     public String toString() {
-        if (DEBUG_METHOD_HANDLE_NAMES)  return debugString();
+        if (DEBUG_METHOD_HANDLE_NAMES)  return "MethodHandle"+debugString();
         return standardString();
     }
     String standardString() {
         return "MethodHandle"+type;
     }
+    /** Return a string with a several lines describing the method handle structure.
+     *  This string would be suitable for display in an IDE debugger.
+     */
     String debugString() {
-        return standardString()+"/LF="+internalForm()+internalProperties();
+        return type+" : "+internalForm()+internalProperties();
     }
 
     //// Implementation methods.
@@ -1300,22 +1323,42 @@
 
     // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
 
+    BoundMethodHandle bindArgumentL(int pos, Object value) {
+        return rebind().bindArgumentL(pos, value);
+    }
+
     /*non-public*/
     MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
         if (!member.isVarargs())  return this;
-        int argc = type().parameterCount();
-        if (argc != 0) {
-            Class<?> arrayType = type().parameterType(argc-1);
-            if (arrayType.isArray()) {
-                return MethodHandleImpl.makeVarargsCollector(this, arrayType);
-            }
+        Class<?> arrayType = type().lastParameterType();
+        if (arrayType.isArray()) {
+            return MethodHandleImpl.makeVarargsCollector(this, arrayType);
         }
         throw member.makeAccessException("cannot make variable arity", null);
     }
+
     /*non-public*/
-    MethodHandle viewAsType(MethodType newType) {
+    MethodHandle viewAsType(MethodType newType, boolean strict) {
         // No actual conversions, just a new view of the same method.
-        return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
+        // Note that this operation must not produce a DirectMethodHandle,
+        // because retyped DMHs, like any transformed MHs,
+        // cannot be cracked into MethodHandleInfo.
+        assert viewAsTypeChecks(newType, strict);
+        BoundMethodHandle mh = rebind();
+        assert(!((MethodHandle)mh instanceof DirectMethodHandle));
+        return mh.copyWith(newType, mh.form);
+    }
+
+    /*non-public*/
+    boolean viewAsTypeChecks(MethodType newType, boolean strict) {
+        if (strict) {
+            assert(type().isViewableAs(newType, true))
+                : Arrays.asList(this, newType);
+        } else {
+            assert(type().basicType().isViewableAs(newType.basicType(), true))
+                : Arrays.asList(this, newType);
+        }
+        return true;
     }
 
     // Decoding
@@ -1336,9 +1379,15 @@
     }
 
     /*non-public*/
-    MethodHandle withInternalMemberName(MemberName member) {
+    MethodHandleImpl.Intrinsic intrinsicName() {
+        // no special intrinsic meaning to most MHs
+        return MethodHandleImpl.Intrinsic.NONE;
+    }
+
+    /*non-public*/
+    MethodHandle withInternalMemberName(MemberName member, boolean isInvokeSpecial) {
         if (member != null) {
-            return MethodHandleImpl.makeWrappedMember(this, member);
+            return MethodHandleImpl.makeWrappedMember(this, member, isInvokeSpecial);
         } else if (internalMemberName() == null) {
             // The required internaMemberName is null, and this MH (like most) doesn't have one.
             return this;
@@ -1362,7 +1411,7 @@
 
     /*non-public*/
     Object internalProperties() {
-        // Override to something like "/FOO=bar"
+        // Override to something to follow this.form, like "\n& FOO=bar"
         return "";
     }
 
@@ -1370,95 +1419,14 @@
     //// Sub-classes can override these default implementations.
     //// All these methods assume arguments are already validated.
 
-    /*non-public*/ MethodHandle convertArguments(MethodType newType) {
-        // Override this if it can be improved.
-        return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
-    }
-
     /*non-public*/
-    MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
-        // Override this if it can be improved.
-        return rebind().bindArgument(pos, basicType, value);
-    }
-
-    /*non-public*/
-    MethodHandle bindReceiver(Object receiver) {
-        // Override this if it can be improved.
-        return bindArgument(0, L_TYPE, receiver);
-    }
-
-    /*non-public*/
-    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
-        // Override this if it can be improved.
-        return rebind().dropArguments(srcType, pos, drops);
-    }
-
-    /*non-public*/
-    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
-        // Override this if it can be improved.
-        return rebind().permuteArguments(newType, reorder);
-    }
-
-    /*non-public*/
-    MethodHandle rebind() {
-        // Bind 'this' into a new invoker, of the known class BMH.
-        MethodType type2 = type();
-        LambdaForm form2 = reinvokerForm(this);
-        // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
-        return BoundMethodHandle.bindSingle(type2, form2, this);
-    }
-
-    /*non-public*/
-    MethodHandle reinvokerTarget() {
-        throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this);
-    }
+    abstract MethodHandle copyWith(MethodType mt, LambdaForm lf);
 
-    /** Create a LF which simply reinvokes a target of the given basic type.
-     *  The target MH must override {@link #reinvokerTarget} to provide the target.
+    /** Require this method handle to be a BMH, or else replace it with a "wrapper" BMH.
+     *  Many transforms are implemented only for BMHs.
+     *  @return a behaviorally equivalent BMH
      */
-    static LambdaForm reinvokerForm(MethodHandle target) {
-        MethodType mtype = target.type().basicType();
-        LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
-        if (reinvoker != null)  return reinvoker;
-        if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)
-            return makeReinvokerForm(target.type(), target);  // cannot cache this
-        reinvoker = makeReinvokerForm(mtype, null);
-        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker);
-    }
-    private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) {
-        boolean customized = (customTargetOrNull != null);
-        MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype);
-        final int THIS_BMH    = 0;
-        final int ARG_BASE    = 1;
-        final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
-        int nameCursor = ARG_LIMIT;
-        final int NEXT_MH     = customized ? -1 : nameCursor++;
-        final int REINVOKE    = nameCursor++;
-        LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
-        Object[] targetArgs;
-        MethodHandle targetMH;
-        if (customized) {
-            targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
-            targetMH = customTargetOrNull;
-        } else {
-            names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
-            targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
-            targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
-            targetMH = MethodHandles.basicInvoker(mtype);
-        }
-        names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs);
-        return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names);
-    }
-
-    private static final LambdaForm.NamedFunction NF_reinvokerTarget;
-    static {
-        try {
-            NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class
-                .getDeclaredMethod("reinvokerTarget"));
-        } catch (ReflectiveOperationException ex) {
-            throw newInternalError(ex);
-        }
-    }
+    abstract BoundMethodHandle rebind();
 
     /**
      * Replace the old lambda form of this method handle with a new one.
@@ -1470,6 +1438,7 @@
     /*non-public*/
     void updateForm(LambdaForm newForm) {
         if (form == newForm)  return;
+        assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic());
         // ISSUE: Should we have a memory fence here?
         UNSAFE.putObject(this, FORM_OFFSET, newForm);
         this.form.prepare();  // as in MethodHandle.<init>
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,8 +27,10 @@
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
+
 import sun.invoke.empty.Empty;
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyType;
@@ -44,6 +46,20 @@
  * @author jrose
  */
 /*non-public*/ abstract class MethodHandleImpl {
+    // Do not adjust this except for special platforms:
+    private static final int MAX_ARITY;
+    static {
+        final Object[] values = { 255 };
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                values[0] = Integer.getInteger(MethodHandleImpl.class.getName()+".MAX_ARITY", 255);
+                return null;
+            }
+        });
+        MAX_ARITY = (Integer) values[0];
+    }
+
     /// Factory methods to create method handles:
 
     static void initStatics() {
@@ -52,27 +68,55 @@
     }
 
     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
+        if (arrayClass == Object[].class)
+            return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
         if (!arrayClass.isArray())
             throw newIllegalArgumentException("not an array: "+arrayClass);
-        MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
-        MethodType srcType = accessor.type().erase();
-        MethodType lambdaType = srcType.invokerType();
-        Name[] names = arguments(1, lambdaType);
-        Name[] args  = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
-        names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
-        LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
-        MethodHandle mh = SimpleMethodHandle.make(srcType, form);
-        if (ArrayAccessor.needCast(arrayClass)) {
-            mh = mh.bindTo(arrayClass);
+        MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
+        int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
+        MethodHandle mh = cache[cacheIndex];
+        if (mh != null)  return mh;
+        mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
+        MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
+        if (mh.type() != correctType) {
+            assert(mh.type().parameterType(0) == Object[].class);
+            assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
+            assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
+            // safe to view non-strictly, because element type follows from array type
+            mh = mh.viewAsType(correctType, false);
         }
-        mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
+        mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD));
+        // Atomically update accessor cache.
+        synchronized(cache) {
+            if (cache[cacheIndex] == null) {
+                cache[cacheIndex] = mh;
+            } else {
+                // Throw away newly constructed accessor and use cached version.
+                mh = cache[cacheIndex];
+            }
+        }
         return mh;
     }
 
     static final class ArrayAccessor {
         /// Support for array element access
-        static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>();  // TODO use it
-        static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>();  // TODO use it
+        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
+        static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
+                = new ClassValue<MethodHandle[]>() {
+                    @Override
+                    protected MethodHandle[] computeValue(Class<?> type) {
+                        return new MethodHandle[INDEX_LIMIT];
+                    }
+                };
+        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER;
+        static {
+            MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
+            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD);
+            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true),  Intrinsic.ARRAY_STORE);
+
+            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
+            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
+        }
 
         static int     getElementI(int[]     a, int i)            { return              a[i]; }
         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
@@ -94,45 +138,21 @@
         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
 
-        static Object  getElementL(Class<?> arrayClass, Object[] a, int i)           { arrayClass.cast(a); return a[i]; }
-        static void    setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
-
-        // Weakly typed wrappers of Object[] accessors:
-        static Object  getElementL(Object    a, int i)            { return getElementL((Object[])a, i); }
-        static void    setElementL(Object    a, int i, Object  x) {        setElementL((Object[]) a, i, x); }
-        static Object  getElementL(Object   arrayClass, Object a, int i)             { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
-        static void    setElementL(Object   arrayClass, Object a, int i, Object x)   {        setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
-
-        static boolean needCast(Class<?> arrayClass) {
-            Class<?> elemClass = arrayClass.getComponentType();
-            return !elemClass.isPrimitive() && elemClass != Object.class;
-        }
         static String name(Class<?> arrayClass, boolean isSetter) {
             Class<?> elemClass = arrayClass.getComponentType();
-            if (elemClass == null)  throw new IllegalArgumentException();
+            if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
         }
-        static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
         static MethodType type(Class<?> arrayClass, boolean isSetter) {
             Class<?> elemClass = arrayClass.getComponentType();
             Class<?> arrayArgClass = arrayClass;
             if (!elemClass.isPrimitive()) {
                 arrayArgClass = Object[].class;
-                if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
-                    arrayArgClass = Object.class;
+                elemClass = Object.class;
             }
-            if (!needCast(arrayClass)) {
-                return !isSetter ?
+            return !isSetter ?
                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
-            } else {
-                Class<?> classArgClass = Class.class;
-                if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
-                    classArgClass = Object.class;
-                return !isSetter ?
-                    MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
-                    MethodType.methodType(void.class,   classArgClass, arrayArgClass, int.class, Object.class);
-            }
         }
         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
             Class<?> elemClass = arrayClass.getComponentType();
@@ -159,40 +179,110 @@
      * integral widening or narrowing, and floating point widening or narrowing.
      * @param srcType required call type
      * @param target original method handle
-     * @param level which strength of conversion is allowed
+     * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed
+     * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double)
      * @return an adapter to the original handle with the desired new type,
      *          or the original target if the types are already identical
      *          or null if the adaptation cannot be made
      */
-    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
-        assert(level >= 0 && level <= 2);
+    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
+                                            boolean strict, boolean monobox) {
         MethodType dstType = target.type();
         assert(dstType.parameterCount() == target.type().parameterCount());
         if (srcType == dstType)
             return target;
+        if (USE_LAMBDA_FORM_EDITOR) {
+            return makePairwiseConvertByEditor(target, srcType, strict, monobox);
+        } else {
+            return makePairwiseConvertIndirect(target, srcType, strict, monobox);
+        }
+    }
 
-        // Calculate extra arguments (temporaries) required in the names array.
-        // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
-        final int INARG_COUNT = srcType.parameterCount();
-        int conversions = 0;
-        boolean[] needConv = new boolean[1+INARG_COUNT];
-        for (int i = 0; i <= INARG_COUNT; i++) {
-            Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
-            Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
-            if (!VerifyType.isNullConversion(src, dst) ||
-                level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
-                needConv[i] = true;
-                conversions++;
+    private static int countNonNull(Object[] array) {
+        int count = 0;
+        for (Object x : array) {
+            if (x != null)  ++count;
+        }
+        return count;
+    }
+
+    static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType,
+                                                    boolean strict, boolean monobox) {
+        Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
+        int convCount = countNonNull(convSpecs);
+        if (convCount == 0)
+            return target.viewAsType(srcType, strict);
+        MethodType basicSrcType = srcType.basicType();
+        MethodType midType = target.type().basicType();
+        BoundMethodHandle mh = target.rebind();
+        // FIXME: Reduce number of bindings when there is more than one Class conversion.
+        // FIXME: Reduce number of bindings when there are repeated conversions.
+        for (int i = 0; i < convSpecs.length-1; i++) {
+            Object convSpec = convSpecs[i];
+            if (convSpec == null)  continue;
+            MethodHandle fn;
+            if (convSpec instanceof Class) {
+                fn = Lazy.MH_castReference.bindTo(convSpec);
+            } else {
+                fn = (MethodHandle) convSpec;
+            }
+            Class<?> newType = basicSrcType.parameterType(i);
+            if (--convCount == 0)
+                midType = srcType;
+            else
+                midType = midType.changeParameterType(i, newType);
+            LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType));
+            mh = mh.copyWithExtendL(midType, form2, fn);
+            mh = mh.rebind();
+        }
+        Object convSpec = convSpecs[convSpecs.length-1];
+        if (convSpec != null) {
+            MethodHandle fn;
+            if (convSpec instanceof Class) {
+                if (convSpec == void.class)
+                    fn = null;
+                else
+                    fn = Lazy.MH_castReference.bindTo(convSpec);
+            } else {
+                fn = (MethodHandle) convSpec;
+            }
+            Class<?> newType = basicSrcType.returnType();
+            assert(--convCount == 0);
+            midType = srcType;
+            if (fn != null) {
+                mh = mh.rebind();  // rebind if too complex
+                LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false);
+                mh = mh.copyWithExtendL(midType, form2, fn);
+            } else {
+                LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true);
+                mh = mh.copyWith(midType, form2);
             }
         }
-        boolean retConv = needConv[INARG_COUNT];
+        assert(convCount == 0);
+        assert(mh.type().equals(srcType));
+        return mh;
+    }
+
+    static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
+                                                    boolean strict, boolean monobox) {
+        // Calculate extra arguments (temporaries) required in the names array.
+        Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
+        final int INARG_COUNT = srcType.parameterCount();
+        int convCount = countNonNull(convSpecs);
+        boolean retConv = (convSpecs[INARG_COUNT] != null);
+        boolean retVoid = srcType.returnType() == void.class;
+        if (retConv && retVoid) {
+            convCount -= 1;
+            retConv = false;
+        }
 
         final int IN_MH         = 0;
         final int INARG_BASE    = 1;
         final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
-        final int NAME_LIMIT    = INARG_LIMIT + conversions + 1;
+        final int NAME_LIMIT    = INARG_LIMIT + convCount + 1;
         final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
         final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
+        final int RESULT        = (retVoid ? -1 : NAME_LIMIT - 1);
 
         // Now build a LambdaForm.
         MethodType lambdaType = srcType.basicType().invokerType();
@@ -204,59 +294,21 @@
 
         int nameCursor = INARG_LIMIT;
         for (int i = 0; i < INARG_COUNT; i++) {
-            Class<?> src = srcType.parameterType(i);
-            Class<?> dst = dstType.parameterType(i);
-
-            if (!needConv[i]) {
+            Object convSpec = convSpecs[i];
+            if (convSpec == null) {
                 // do nothing: difference is trivial
                 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
                 continue;
             }
 
-            // Tricky case analysis follows.
-            MethodHandle fn = null;
-            if (src.isPrimitive()) {
-                if (dst.isPrimitive()) {
-                    fn = ValueConversions.convertPrimitive(src, dst);
-                } else {
-                    Wrapper w = Wrapper.forPrimitiveType(src);
-                    MethodHandle boxMethod = ValueConversions.box(w);
-                    if (dst == w.wrapperType())
-                        fn = boxMethod;
-                    else
-                        fn = boxMethod.asType(MethodType.methodType(dst, src));
-                }
+            Name conv;
+            if (convSpec instanceof Class) {
+                Class<?> convClass = (Class<?>) convSpec;
+                conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]);
             } else {
-                if (dst.isPrimitive()) {
-                    // Caller has boxed a primitive.  Unbox it for the target.
-                    Wrapper w = Wrapper.forPrimitiveType(dst);
-                    if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
-                        fn = ValueConversions.unbox(dst);
-                    } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
-                        // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
-                        // must include additional conversions
-                        // src must be examined at runtime, to detect Byte, Character, etc.
-                        MethodHandle unboxMethod = (level == 1
-                                                    ? ValueConversions.unbox(dst)
-                                                    : ValueConversions.unboxCast(dst));
-                        fn = unboxMethod;
-                    } else {
-                        // Example: Byte->int
-                        // Do this by reformulating the problem to Byte->byte.
-                        Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
-                        MethodHandle unbox = ValueConversions.unbox(srcPrim);
-                        // Compose the two conversions.  FIXME:  should make two Names for this job
-                        fn = unbox.asType(MethodType.methodType(dst, src));
-                    }
-                } else {
-                    // Simple reference conversion.
-                    // Note:  Do not check for a class hierarchy relation
-                    // between src and dst.  In all cases a 'null' argument
-                    // will pass the cast conversion.
-                    fn = ValueConversions.cast(dst, Lazy.MH_castReference);
-                }
+                MethodHandle fn = (MethodHandle) convSpec;
+                conv = new Name(fn, names[INARG_BASE + i]);
             }
-            Name conv = new Name(fn, names[INARG_BASE + i]);
             assert(names[nameCursor] == null);
             names[nameCursor++] = conv;
             assert(outArgs[OUTARG_BASE + i] == null);
@@ -267,29 +319,29 @@
         assert(nameCursor == OUT_CALL);
         names[OUT_CALL] = new Name(target, outArgs);
 
-        if (RETURN_CONV < 0) {
+        Object convSpec = convSpecs[INARG_COUNT];
+        if (!retConv) {
             assert(OUT_CALL == names.length-1);
         } else {
-            Class<?> needReturn = srcType.returnType();
-            Class<?> haveReturn = dstType.returnType();
-            MethodHandle fn;
-            Object[] arg = { names[OUT_CALL] };
-            if (haveReturn == void.class) {
-                // synthesize a zero value for the given void
-                Object zero = Wrapper.forBasicType(needReturn).zero();
-                fn = MethodHandles.constant(needReturn, zero);
-                arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
+            Name conv;
+            if (convSpec == void.class) {
+                conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType())));
+            } else if (convSpec instanceof Class) {
+                Class<?> convClass = (Class<?>) convSpec;
+                conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]);
             } else {
-                MethodHandle identity = MethodHandles.identity(needReturn);
-                MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
-                fn = makePairwiseConvert(identity, needConversion, level);
+                MethodHandle fn = (MethodHandle) convSpec;
+                if (fn.type().parameterCount() == 0)
+                    conv = new Name(fn);  // don't pass retval to void conversion
+                else
+                    conv = new Name(fn, names[OUT_CALL]);
             }
             assert(names[RETURN_CONV] == null);
-            names[RETURN_CONV] = new Name(fn, arg);
+            names[RETURN_CONV] = conv;
             assert(RETURN_CONV == names.length-1);
         }
 
-        LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
+        LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT);
         return SimpleMethodHandle.make(srcType, form);
     }
 
@@ -312,12 +364,79 @@
         return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
     }
 
-    static MethodHandle makeReferenceIdentity(Class<?> refType) {
-        MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
-        Name[] names = arguments(1, lambdaType);
-        names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
-        LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
-        return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
+    static Object[] computeValueConversions(MethodType srcType, MethodType dstType,
+                                            boolean strict, boolean monobox) {
+        final int INARG_COUNT = srcType.parameterCount();
+        Object[] convSpecs = new Object[INARG_COUNT+1];
+        for (int i = 0; i <= INARG_COUNT; i++) {
+            boolean isRet = (i == INARG_COUNT);
+            Class<?> src = isRet ? dstType.returnType() : srcType.parameterType(i);
+            Class<?> dst = isRet ? srcType.returnType() : dstType.parameterType(i);
+            if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) {
+                convSpecs[i] = valueConversion(src, dst, strict, monobox);
+            }
+        }
+        return convSpecs;
+    }
+    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
+                                            boolean strict) {
+        return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false);
+    }
+
+    /**
+     * Find a conversion function from the given source to the given destination.
+     * This conversion function will be used as a LF NamedFunction.
+     * Return a Class object if a simple cast is needed.
+     * Return void.class if void is involved.
+     */
+    static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
+        assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict));  // caller responsibility
+        if (dst == void.class)
+            return dst;
+        MethodHandle fn;
+        if (src.isPrimitive()) {
+            if (src == void.class) {
+                return void.class;  // caller must recognize this specially
+            } else if (dst.isPrimitive()) {
+                // Examples: int->byte, byte->int, boolean->int (!strict)
+                fn = ValueConversions.convertPrimitive(src, dst);
+            } else {
+                // Examples: int->Integer, boolean->Object, float->Number
+                Wrapper wsrc = Wrapper.forPrimitiveType(src);
+                fn = ValueConversions.boxExact(wsrc);
+                assert(fn.type().parameterType(0) == wsrc.primitiveType());
+                assert(fn.type().returnType() == wsrc.wrapperType());
+                if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
+                    // Corner case, such as int->Long, which will probably fail.
+                    MethodType mt = MethodType.methodType(dst, src);
+                    if (strict)
+                        fn = fn.asType(mt);
+                    else
+                        fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false);
+                }
+            }
+        } else if (dst.isPrimitive()) {
+            Wrapper wdst = Wrapper.forPrimitiveType(dst);
+            if (monobox || src == wdst.wrapperType()) {
+                // Use a strongly-typed unboxer, if possible.
+                fn = ValueConversions.unboxExact(wdst, strict);
+            } else {
+                // Examples:  Object->int, Number->int, Comparable->int, Byte->int
+                // must include additional conversions
+                // src must be examined at runtime, to detect Byte, Character, etc.
+                fn = (strict
+                        ? ValueConversions.unboxWiden(wdst)
+                        : ValueConversions.unboxCast(wdst));
+            }
+        } else {
+            // Simple reference conversion.
+            // Note:  Do not check for a class hierarchy relation
+            // between src and dst.  In all cases a 'null' argument
+            // will pass the cast conversion.
+            return dst;
+        }
+        assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
+        return fn;
     }
 
     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
@@ -326,34 +445,46 @@
         if (type.parameterType(last) != arrayType)
             target = target.asType(type.changeParameterType(last, arrayType));
         target = target.asFixedArity();  // make sure this attribute is turned off
-        return new AsVarargsCollector(target, target.type(), arrayType);
+        return new AsVarargsCollector(target, arrayType);
     }
 
-    static class AsVarargsCollector extends MethodHandle {
+    private static final class AsVarargsCollector extends DelegatingMethodHandle {
         private final MethodHandle target;
         private final Class<?> arrayType;
-        private /*@Stable*/ MethodHandle asCollectorCache;
+        private @Stable MethodHandle asCollectorCache;
 
-        AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
-            super(type, reinvokerForm(target));
+        AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
+            this(target.type(), target, arrayType);
+        }
+        AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
+            super(type, target);
             this.target = target;
             this.arrayType = arrayType;
             this.asCollectorCache = target.asCollector(arrayType, 0);
         }
 
-        @Override MethodHandle reinvokerTarget() { return target; }
-
         @Override
         public boolean isVarargsCollector() {
             return true;
         }
 
         @Override
+        protected MethodHandle getTarget() {
+            return target;
+        }
+
+        @Override
         public MethodHandle asFixedArity() {
             return target;
         }
 
         @Override
+        MethodHandle setVarargs(MemberName member) {
+            if (member.isVarargs())  return this;
+            return asFixedArity();
+        }
+
+        @Override
         public MethodHandle asTypeUncached(MethodType newType) {
             MethodType type = this.type();
             int collectArg = type.parameterCount() - 1;
@@ -381,54 +512,15 @@
         }
 
         @Override
-        MethodHandle setVarargs(MemberName member) {
-            if (member.isVarargs())  return this;
-            return asFixedArity();
-        }
-
-        @Override
-        MethodHandle viewAsType(MethodType newType) {
-            if (newType.lastParameterType() != type().lastParameterType())
-                throw new InternalError();
-            MethodHandle newTarget = asFixedArity().viewAsType(newType);
-            // put back the varargs bit:
-            return new AsVarargsCollector(newTarget, newType, arrayType);
-        }
-
-        @Override
-        MemberName internalMemberName() {
-            return asFixedArity().internalMemberName();
-        }
-        @Override
-        Class<?> internalCallerClass() {
-            return asFixedArity().internalCallerClass();
-        }
-
-        /*non-public*/
-        @Override
-        boolean isInvokeSpecial() {
-            return asFixedArity().isInvokeSpecial();
-        }
-
-
-        @Override
-        MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
-            return asFixedArity().bindArgument(pos, basicType, value);
-        }
-
-        @Override
-        MethodHandle bindReceiver(Object receiver) {
-            return asFixedArity().bindReceiver(receiver);
-        }
-
-        @Override
-        MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
-            return asFixedArity().dropArguments(srcType, pos, drops);
-        }
-
-        @Override
-        MethodHandle permuteArguments(MethodType newType, int[] reorder) {
-            return asFixedArity().permuteArguments(newType, reorder);
+        boolean viewAsTypeChecks(MethodType newType, boolean strict) {
+            super.viewAsTypeChecks(newType, true);
+            if (strict) return true;
+            // extra assertion for non-strict checks:
+            assert (type().lastParameterType().getComponentType()
+                    .isAssignableFrom(
+                            newType.lastParameterType().getComponentType()))
+                    : Arrays.asList(this, newType);
+            return true;
         }
     }
 
@@ -499,32 +591,46 @@
      * Pre-initialized NamedFunctions for bootstrapping purposes.
      * Factored in an inner class to delay initialization until first usage.
      */
-    private static class Lazy {
+    static class Lazy {
         private static final Class<?> MHI = MethodHandleImpl.class;
 
         static final NamedFunction NF_checkSpreadArgument;
         static final NamedFunction NF_guardWithCatch;
-        static final NamedFunction NF_selectAlternative;
         static final NamedFunction NF_throwException;
 
         static final MethodHandle MH_castReference;
+        static final MethodHandle MH_selectAlternative;
+        static final MethodHandle MH_copyAsPrimitiveArray;
+        static final MethodHandle MH_fillNewTypedArray;
+        static final MethodHandle MH_fillNewArray;
+        static final MethodHandle MH_arrayIdentity;
 
         static {
             try {
                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
                                                                                  MethodHandle.class, Object[].class));
-                NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
-                                                                                 MethodHandle.class));
                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 
                 NF_checkSpreadArgument.resolve();
                 NF_guardWithCatch.resolve();
-                NF_selectAlternative.resolve();
                 NF_throwException.resolve();
 
-                MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class);
-                MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt);
+                MH_castReference        = IMPL_LOOKUP.findStatic(MHI, "castReference",
+                                            MethodType.methodType(Object.class, Class.class, Object.class));
+                MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray",
+                                            MethodType.methodType(Object.class, Wrapper.class, Object[].class));
+                MH_arrayIdentity        = IMPL_LOOKUP.findStatic(MHI, "identity",
+                                            MethodType.methodType(Object[].class, Object[].class));
+                MH_fillNewArray         = IMPL_LOOKUP.findStatic(MHI, "fillNewArray",
+                                            MethodType.methodType(Object[].class, Integer.class, Object[].class));
+                MH_fillNewTypedArray    = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray",
+                                            MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
+
+                MH_selectAlternative    = makeIntrinsic(
+                        IMPL_LOOKUP.findStatic(MHI, "selectAlternative",
+                                MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)),
+                        Intrinsic.SELECT_ALTERNATIVE);
             } catch (ReflectiveOperationException ex) {
                 throw newInternalError(ex);
             }
@@ -595,29 +701,66 @@
     MethodHandle makeGuardWithTest(MethodHandle test,
                                    MethodHandle target,
                                    MethodHandle fallback) {
-        MethodType basicType = target.type().basicType();
-        MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
-        int arity = basicType.parameterCount();
-        int extraNames = 3;
+        MethodType type = target.type();
+        assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
+        MethodType basicType = type.basicType();
+        LambdaForm form = makeGuardWithTestForm(basicType);
+        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
+        BoundMethodHandle mh;
+        try {
+            mh = (BoundMethodHandle)
+                    data.constructor().invokeBasic(type, form,
+                        (Object) test, (Object) target, (Object) fallback);
+        } catch (Throwable ex) {
+            throw uncaughtException(ex);
+        }
+        assert(mh.type() == type);
+        return mh;
+    }
+
+    static
+    LambdaForm makeGuardWithTestForm(MethodType basicType) {
+        LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
+        if (lform != null)  return lform;
+        final int THIS_MH      = 0;  // the BMH_LLL
+        final int ARG_BASE     = 1;  // start of incoming arguments
+        final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int GET_TEST     = nameCursor++;
+        final int GET_TARGET   = nameCursor++;
+        final int GET_FALLBACK = nameCursor++;
+        final int CALL_TEST    = nameCursor++;
+        final int SELECT_ALT   = nameCursor++;
+        final int CALL_TARGET  = nameCursor++;
+        assert(CALL_TARGET == SELECT_ALT+1);  // must be true to trigger IBG.emitSelectAlternative
+
         MethodType lambdaType = basicType.invokerType();
-        Name[] names = arguments(extraNames, lambdaType);
+        Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 
-        Object[] testArgs   = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
-        Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
+        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
+        names[THIS_MH] = names[THIS_MH].withConstraint(data);
+        names[GET_TEST]     = new Name(data.getterFunction(0), names[THIS_MH]);
+        names[GET_TARGET]   = new Name(data.getterFunction(1), names[THIS_MH]);
+        names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]);
+
+        Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class);
 
         // call test
-        names[arity + 1] = new Name(test, testArgs);
+        MethodType testType = basicType.changeReturnType(boolean.class).basicType();
+        invokeArgs[0] = names[GET_TEST];
+        names[CALL_TEST] = new Name(testType, invokeArgs);
 
         // call selectAlternative
-        Object[] selectArgs = { names[arity + 1], target, fallback };
-        names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
-        targetArgs[0] = names[arity + 2];
+        names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST],
+                                     names[GET_TARGET], names[GET_FALLBACK]);
 
         // call target or fallback
-        names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
+        invokeArgs[0] = names[SELECT_ALT];
+        names[CALL_TARGET] = new Name(basicType, invokeArgs);
 
-        LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
-        return SimpleMethodHandle.make(target.type(), form);
+        lform = new LambdaForm("guard", lambdaType.parameterCount(), names);
+
+        return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform);
     }
 
     /**
@@ -665,6 +808,7 @@
         Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 
         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
+        names[THIS_MH]          = names[THIS_MH].withConstraint(data);
         names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
         names[GET_CLASS]        = new Name(data.getterFunction(1), names[THIS_MH]);
         names[GET_CATCHER]      = new Name(data.getterFunction(2), names[THIS_MH]);
@@ -679,7 +823,7 @@
         Object[] args = new Object[invokeBasic.type().parameterCount()];
         args[0] = names[GET_COLLECT_ARGS];
         System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
-        names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
+        names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args);
 
         // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
         Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
@@ -688,7 +832,7 @@
         // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
         MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
         Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
-        names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
+        names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
 
         lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
 
@@ -705,22 +849,27 @@
         // Prepare auxiliary method handles used during LambdaForm interpretation.
         // Box arguments and wrap them into Object[]: ValueConversions.array().
         MethodType varargsType = type.changeReturnType(Object[].class);
-        MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
-                                                   .asType(varargsType);
+        MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
         // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
         MethodHandle unboxResult;
-        if (type.returnType().isPrimitive()) {
-            unboxResult = ValueConversions.unbox(type.returnType());
+        Class<?> rtype = type.returnType();
+        if (rtype.isPrimitive()) {
+            if (rtype == void.class) {
+                unboxResult = ValueConversions.ignore();
+            } else {
+                Wrapper w = Wrapper.forPrimitiveType(type.returnType());
+                unboxResult = ValueConversions.unboxExact(w);
+            }
         } else {
-            unboxResult = ValueConversions.identity();
+            unboxResult = MethodHandles.identity(Object.class);
         }
 
         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
         BoundMethodHandle mh;
         try {
             mh = (BoundMethodHandle)
-                    data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
-                                                    (Object) collectArgs, (Object) unboxResult);
+                    data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
+                                                   (Object) collectArgs, (Object) unboxResult);
         } catch (Throwable ex) {
             throw uncaughtException(ex);
         }
@@ -758,9 +907,11 @@
         assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
         int arity = type.parameterCount();
         if (arity > 1) {
-            return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
+            MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
+            mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
+            return mh;
         }
-        return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
+        return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, false, true);
     }
 
     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
@@ -782,7 +933,7 @@
         mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
         if (!method.getInvocationType().equals(mh.type()))
             throw new InternalError(method.toString());
-        mh = mh.withInternalMemberName(method);
+        mh = mh.withInternalMemberName(method, false);
         mh = mh.asVarargsCollector(Object[].class);
         assert(method.isVarargs());
         FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
@@ -819,7 +970,7 @@
             MethodHandle vamh = prepareForInvoker(mh);
             // Cache the result of makeInjectedInvoker once per argument class.
             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
-            return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
+            return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
         }
 
         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
@@ -874,12 +1025,14 @@
         }
 
         // Undo the adapter effect of prepareForInvoker:
-        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
-                                                  MemberName member,
+        private static MethodHandle restoreToType(MethodHandle vamh,
+                                                  MethodHandle original,
                                                   Class<?> hostClass) {
+            MethodType type = original.type();
             MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
+            MemberName member = original.internalMemberName();
             mh = mh.asType(type);
-            mh = new WrappedMember(mh, type, member, hostClass);
+            mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass);
             return mh;
         }
 
@@ -945,29 +1098,23 @@
 
 
     /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
-    static class WrappedMember extends MethodHandle {
+    private static final class WrappedMember extends DelegatingMethodHandle {
         private final MethodHandle target;
         private final MemberName member;
         private final Class<?> callerClass;
+        private final boolean isInvokeSpecial;
 
-        private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
-            super(type, reinvokerForm(target));
+        private WrappedMember(MethodHandle target, MethodType type,
+                              MemberName member, boolean isInvokeSpecial,
+                              Class<?> callerClass) {
+            super(type, target);
             this.target = target;
             this.member = member;
             this.callerClass = callerClass;
+            this.isInvokeSpecial = isInvokeSpecial;
         }
 
         @Override
-        MethodHandle reinvokerTarget() {
-            return target;
-        }
-        @Override
-        public MethodHandle asTypeUncached(MethodType newType) {
-            // This MH is an alias for target, except for the MemberName
-            // Drop the MemberName if there is any conversion.
-            return asTypeCache = target.asType(newType);
-        }
-        @Override
         MemberName internalMemberName() {
             return member;
         }
@@ -977,18 +1124,367 @@
         }
         @Override
         boolean isInvokeSpecial() {
-            return target.isInvokeSpecial();
+            return isInvokeSpecial;
+        }
+        @Override
+        protected MethodHandle getTarget() {
+            return target;
         }
         @Override
-        MethodHandle viewAsType(MethodType newType) {
-            return new WrappedMember(target, newType, member, callerClass);
+        public MethodHandle asTypeUncached(MethodType newType) {
+            // This MH is an alias for target, except for the MemberName
+            // Drop the MemberName if there is any conversion.
+            return asTypeCache = target.asType(newType);
+        }
+    }
+
+    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
+        if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
+            return target;
+        return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
+    }
+
+    /** Intrinsic IDs */
+    /*non-public*/
+    enum Intrinsic {
+        SELECT_ALTERNATIVE,
+        GUARD_WITH_CATCH,
+        NEW_ARRAY,
+        ARRAY_LOAD,
+        ARRAY_STORE,
+        IDENTITY,
+        ZERO,
+        NONE // no intrinsic associated
+    }
+
+    /** Mark arbitrary method handle as intrinsic.
+     * InvokerBytecodeGenerator uses this info to produce more efficient bytecode shape. */
+    private static final class IntrinsicMethodHandle extends DelegatingMethodHandle {
+        private final MethodHandle target;
+        private final Intrinsic intrinsicName;
+
+        IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) {
+            super(target.type(), target);
+            this.target = target;
+            this.intrinsicName = intrinsicName;
+        }
+
+        @Override
+        protected MethodHandle getTarget() {
+            return target;
+        }
+
+        @Override
+        Intrinsic intrinsicName() {
+            return intrinsicName;
+        }
+
+        @Override
+        public MethodHandle asTypeUncached(MethodType newType) {
+            // This MH is an alias for target, except for the intrinsic name
+            // Drop the name if there is any conversion.
+            return asTypeCache = target.asType(newType);
+        }
+
+        @Override
+        String internalProperties() {
+            return super.internalProperties() +
+                    "\n& Intrinsic="+intrinsicName;
+        }
+
+        @Override
+        public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
+            if (intrinsicName == Intrinsic.IDENTITY) {
+                MethodType resultType = type().asCollectorType(arrayType, arrayLength);
+                MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
+                return newArray.asType(resultType);
+            }
+            return super.asCollector(arrayType, arrayLength);
+        }
+    }
+
+    static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) {
+        if (intrinsicName == target.intrinsicName())
+            return target;
+        return new IntrinsicMethodHandle(target, intrinsicName);
+    }
+
+    static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) {
+        return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName);
+    }
+
+    /// Collection of multiple arguments.
+
+    private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
+        MethodType type = MethodType.genericMethodType(nargs)
+                .changeReturnType(rtype)
+                .insertParameterTypes(0, ptypes);
+        try {
+            return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
+        } catch (ReflectiveOperationException ex) {
+            return null;
         }
     }
 
-    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
-        if (member.equals(target.internalMemberName()))
-            return target;
-        return new WrappedMember(target, target.type(), member, null);
+    private static final Object[] NO_ARGS_ARRAY = {};
+    private static Object[] makeArray(Object... args) { return args; }
+    private static Object[] array() { return NO_ARGS_ARRAY; }
+    private static Object[] array(Object a0)
+                { return makeArray(a0); }
+    private static Object[] array(Object a0, Object a1)
+                { return makeArray(a0, a1); }
+    private static Object[] array(Object a0, Object a1, Object a2)
+                { return makeArray(a0, a1, a2); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+                { return makeArray(a0, a1, a2, a3); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { return makeArray(a0, a1, a2, a3, a4); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5)
+                { return makeArray(a0, a1, a2, a3, a4, a5); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8, Object a9)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+    private static MethodHandle[] makeArrays() {
+        ArrayList<MethodHandle> mhs = new ArrayList<>();
+        for (;;) {
+            MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
+            if (mh == null)  break;
+            mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
+            mhs.add(mh);
+        }
+        assert(mhs.size() == 11);  // current number of methods
+        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
+    }
+    private static final MethodHandle[] ARRAYS = makeArrays();
+
+    // filling versions of the above:
+    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
+    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
+        Object[] a = new Object[len];
+        fillWithArguments(a, 0, args);
+        return a;
+    }
+    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
+        Object[] a = Arrays.copyOf(example, len);
+        assert(a.getClass() != Object[].class);
+        fillWithArguments(a, 0, args);
+        return a;
+    }
+    private static void fillWithArguments(Object[] a, int pos, Object... args) {
+        System.arraycopy(args, 0, a, pos, args.length);
+    }
+    // using Integer pos instead of int pos to avoid bootstrapping problems
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
+                { fillWithArguments(a, pos, a0); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
+                { fillWithArguments(a, pos, a0, a1); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
+                { fillWithArguments(a, pos, a0, a1, a2); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
+                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
+    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8, Object a9)
+                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
+    private static MethodHandle[] makeFillArrays() {
+        ArrayList<MethodHandle> mhs = new ArrayList<>();
+        mhs.add(null);  // there is no empty fill; at least a0 is required
+        for (;;) {
+            MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
+            if (mh == null)  break;
+            mhs.add(mh);
+        }
+        assert(mhs.size() == 11);  // current number of methods
+        return mhs.toArray(new MethodHandle[0]);
+    }
+    private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
+
+    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
+        Object a = w.makeArray(boxes.length);
+        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
+        return a;
+    }
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    static MethodHandle varargsArray(int nargs) {
+        MethodHandle mh = ARRAYS[nargs];
+        if (mh != null)  return mh;
+        mh = findCollector("array", nargs, Object[].class);
+        if (mh != null)  mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
+        if (mh != null)  return ARRAYS[nargs] = mh;
+        mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
+        assert(assertCorrectArity(mh, nargs));
+        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
+        return ARRAYS[nargs] = mh;
+    }
+
+    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
+        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
+        return true;
     }
 
+    // Array identity function (used as Lazy.MH_arrayIdentity).
+    static <T> T[] identity(T[] x) {
+        return x;
+    }
+
+    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
+        // Build up the result mh as a sequence of fills like this:
+        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
+        // The various fill(_,10*I,___*[J]) are reusable.
+        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
+        int rightLen = nargs - leftLen;
+        MethodHandle leftCollector = newArray.bindTo(nargs);
+        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
+        MethodHandle mh = finisher;
+        if (rightLen > 0) {
+            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
+            if (mh == Lazy.MH_arrayIdentity)
+                mh = rightFiller;
+            else
+                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
+        }
+        if (mh == Lazy.MH_arrayIdentity)
+            mh = leftCollector;
+        else
+            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
+        return mh;
+    }
+
+    private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
+    private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
+    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
+     *  fills a[L]..a[N-1] with corresponding arguments,
+     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
+     */
+    private static MethodHandle fillToRight(int nargs) {
+        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
+        if (filler != null)  return filler;
+        filler = buildFiller(nargs);
+        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
+        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
+    }
+    private static MethodHandle buildFiller(int nargs) {
+        if (nargs <= LEFT_ARGS)
+            return Lazy.MH_arrayIdentity;  // no args to fill; return the array unchanged
+        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
+        final int CHUNK = LEFT_ARGS;
+        int rightLen = nargs % CHUNK;
+        int midLen = nargs - rightLen;
+        if (rightLen == 0) {
+            midLen = nargs - (rightLen = CHUNK);
+            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
+                // build some precursors from left to right
+                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
+                    if (j > LEFT_ARGS)  fillToRight(j);
+            }
+        }
+        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
+        assert(rightLen > 0);
+        MethodHandle midFill = fillToRight(midLen);  // recursive fill
+        MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
+        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
+        assert(rightFill.type().parameterCount() == 1 + rightLen);
+
+        // Combine the two fills:
+        //   right(mid(a, x10..x19), x20..x23)
+        // The final product will look like this:
+        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
+        if (midLen == LEFT_ARGS)
+            return rightFill;
+        else
+            return MethodHandles.collectArguments(rightFill, 0, midFill);
+    }
+
+    // Type-polymorphic version of varargs maker.
+    private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
+        = new ClassValue<MethodHandle[]>() {
+            @Override
+            protected MethodHandle[] computeValue(Class<?> type) {
+                return new MethodHandle[256];
+            }
+    };
+
+    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
+
+    /** Return a method handle that takes the indicated number of
+     *  typed arguments and returns an array of them.
+     *  The type argument is the array type.
+     */
+    static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+        Class<?> elemType = arrayType.getComponentType();
+        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
+        // FIXME: Need more special casing and caching here.
+        if (nargs >= MAX_JVM_ARITY/2 - 1) {
+            int slots = nargs;
+            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
+            if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive())
+                slots *= Wrapper.forPrimitiveType(elemType).stackSlots();
+            if (slots > MAX_ARRAY_SLOTS)
+                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
+        }
+        if (elemType == Object.class)
+            return varargsArray(nargs);
+        // other cases:  primitive arrays, subtypes of Object[]
+        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
+        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
+        if (mh != null)  return mh;
+        if (nargs == 0) {
+            Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0);
+            mh = MethodHandles.constant(arrayType, example);
+        } else if (elemType.isPrimitive()) {
+            MethodHandle builder = Lazy.MH_fillNewArray;
+            MethodHandle producer = buildArrayProducer(arrayType);
+            mh = buildVarargsArray(builder, producer, nargs);
+        } else {
+            Class<? extends Object[]> objArrayType = arrayType.asSubclass(Object[].class);
+            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
+            MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example);
+            MethodHandle producer = Lazy.MH_arrayIdentity; // must be weakly typed
+            mh = buildVarargsArray(builder, producer, nargs);
+        }
+        mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
+        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
+        assert(assertCorrectArity(mh, nargs));
+        if (nargs < cache.length)
+            cache[nargs] = mh;
+        return mh;
+    }
+
+    private static MethodHandle buildArrayProducer(Class<?> arrayType) {
+        Class<?> elemType = arrayType.getComponentType();
+        assert(elemType.isPrimitive());
+        return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType));
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,6 +33,7 @@
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
+import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
  * This class consists exclusively of static methods that help adapt
@@ -148,7 +149,7 @@
     public static
     <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
         if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
-            throw new IllegalArgumentException("not a public interface: "+intfc.getName());
+            throw newIllegalArgumentException("not a public interface", intfc.getName());
         final MethodHandle mh;
         if (System.getSecurityManager() != null) {
             final Class<?> caller = Reflection.getCallerClass();
@@ -165,7 +166,7 @@
         }
         final Method[] methods = getSingleNameMethods(intfc);
         if (methods == null)
-            throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
+            throw newIllegalArgumentException("not a single-method interface", intfc.getName());
         final MethodHandle[] vaTargets = new MethodHandle[methods.length];
         for (int i = 0; i < methods.length; i++) {
             Method sm = methods[i];
@@ -189,7 +190,7 @@
                         return getArg(method.getName());
                     if (isObjectMethod(method))
                         return callObjectMethod(proxy, method, args);
-                    throw new InternalError("bad proxy method: "+method);
+                    throw newInternalError("bad proxy method: "+method);
                 }
             };
 
@@ -240,7 +241,7 @@
                 return (WrapperInstance) x;
         } catch (ClassCastException ex) {
         }
-        throw new IllegalArgumentException("not a wrapper instance");
+        throw newIllegalArgumentException("not a wrapper instance");
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Wed Jul 05 20:00:59 2017 +0200
@@ -45,16 +45,21 @@
     static final boolean DUMP_CLASS_FILES;
     static final boolean TRACE_INTERPRETER;
     static final boolean TRACE_METHOD_LINKAGE;
-    static final Integer COMPILE_THRESHOLD;
+    static final boolean USE_LAMBDA_FORM_EDITOR;
+    static final int COMPILE_THRESHOLD;
+    static final int PROFILE_LEVEL;
+
     static {
-        final Object[] values = { false, false, false, false, null };
+        final Object[] values = { false, false, false, false, false, null, null };
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
                 public Void run() {
                     values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
                     values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
                     values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
                     values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
-                    values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD");
+                    values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR");
+                    values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30);
+                    values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
                     return null;
                 }
             });
@@ -62,7 +67,9 @@
         DUMP_CLASS_FILES          = (Boolean) values[1];
         TRACE_INTERPRETER         = (Boolean) values[2];
         TRACE_METHOD_LINKAGE      = (Boolean) values[3];
-        COMPILE_THRESHOLD         = (Integer) values[4];
+        USE_LAMBDA_FORM_EDITOR    = (Boolean) values[4];
+        COMPILE_THRESHOLD         = (Integer) values[5];
+        PROFILE_LEVEL             = (Integer) values[6];
     }
 
     /** Tell if any of the debugging switches are turned on.
@@ -127,7 +134,10 @@
     /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) {
         return new IllegalArgumentException(message(message, obj, obj2));
     }
+    /** Propagate unchecked exceptions and errors, but wrap anything checked and throw that instead. */
     /*non-public*/ static Error uncaughtException(Throwable ex) {
+        if (ex instanceof Error)  throw (Error) ex;
+        if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
         throw newInternalError("uncaught exception", ex);
     }
     static Error NYI() {
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Jul 05 20:00:59 2017 +0200
@@ -26,8 +26,8 @@
 package java.lang.invoke;
 
 import java.lang.reflect.*;
+import java.util.BitSet;
 import java.util.List;
-import java.util.ArrayList;
 import java.util.Arrays;
 
 import sun.invoke.util.ValueConversions;
@@ -40,6 +40,7 @@
 import java.lang.invoke.LambdaForm.BasicType;
 import static java.lang.invoke.LambdaForm.BasicType.*;
 import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandleImpl.Intrinsic;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -862,6 +863,8 @@
                 return invoker(type);
             if ("invokeExact".equals(name))
                 return exactInvoker(type);
+            if ("invokeBasic".equals(name))
+                return basicInvoker(type);
             assert(!MemberName.isMethodHandleInvokeName(name));
             return null;
         }
@@ -1141,7 +1144,7 @@
             Class<? extends Object> refc = receiver.getClass(); // may get NPE
             MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
             MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
-            return mh.bindReceiver(receiver).setVarargs(method);
+            return mh.bindArgumentL(0, receiver).setVarargs(method);
         }
 
         /**
@@ -1576,7 +1579,7 @@
                 return false;
             return true;
         }
-        private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
+        private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
             assert(!method.isStatic());
             // receiver type of mh is too wide; narrow to caller
             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
@@ -1585,7 +1588,9 @@
             MethodType rawType = mh.type();
             if (rawType.parameterType(0) == caller)  return mh;
             MethodType narrowType = rawType.changeParameterType(0, caller);
-            return mh.viewAsType(narrowType);
+            assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
+            assert(mh.viewAsTypeChecks(narrowType, true));
+            return mh.copyWith(narrowType, mh.form);
         }
 
         /** Check access and get the requested method. */
@@ -1647,15 +1652,17 @@
                 checkMethod(refKind, refc, method);
             }
 
-            MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
-            mh = maybeBindCaller(method, mh, callerClass);
-            mh = mh.setVarargs(method);
+            DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method);
+            MethodHandle mh = dmh;
             // Optionally narrow the receiver argument to refc using restrictReceiver.
             if (doRestrict &&
                    (refKind == REF_invokeSpecial ||
                        (MethodHandleNatives.refKindHasReceiver(refKind) &&
-                           restrictProtectedReceiver(method))))
-                mh = restrictReceiver(method, mh, lookupClass());
+                           restrictProtectedReceiver(method)))) {
+                mh = restrictReceiver(method, dmh, lookupClass());
+            }
+            mh = maybeBindCaller(method, mh, callerClass);
+            mh = mh.setVarargs(method);
             return mh;
         }
         private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
@@ -1687,12 +1694,12 @@
             // Optionally check with the security manager; this isn't needed for unreflect* calls.
             if (checkSecurity)
                 checkSecurityManager(refc, field);
-            MethodHandle mh = DirectMethodHandle.make(refc, field);
+            DirectMethodHandle dmh = DirectMethodHandle.make(refc, field);
             boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
                                     restrictProtectedReceiver(field));
             if (doRestrict)
-                mh = restrictReceiver(field, mh, lookupClass());
-            return mh;
+                return restrictReceiver(field, dmh, lookupClass());
+            return dmh;
         }
         /** Check access and get the requested constructor. */
         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
@@ -1879,7 +1886,8 @@
     static public
     MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
         if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
-            throw new IllegalArgumentException("bad argument count "+leadingArgCount);
+            throw newIllegalArgumentException("bad argument count", leadingArgCount);
+        type = type.asSpreaderType(Object[].class, type.parameterCount() - leadingArgCount);
         return type.invokers().spreadInvoker(leadingArgCount);
     }
 
@@ -1959,12 +1967,12 @@
      */
     static public
     MethodHandle invoker(MethodType type) {
-        return type.invokers().generalInvoker();
+        return type.invokers().genericInvoker();
     }
 
     static /*non-public*/
     MethodHandle basicInvoker(MethodType type) {
-        return type.form().basicInvoker();
+        return type.invokers().basicInvoker();
     }
 
      /// method handle modification (creation from other method handles)
@@ -2015,10 +2023,13 @@
      */
     public static
     MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
-        if (!target.type().isCastableTo(newType)) {
-            throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType);
+        MethodType oldType = target.type();
+        // use the asTypeCache when possible:
+        if (oldType == newType)  return target;
+        if (oldType.explicitCastEquivalentToAsType(newType)) {
+            return target.asType(newType);
         }
-        return MethodHandleImpl.makePairwiseConvert(target, newType, 2);
+        return MethodHandleImpl.makePairwiseConvert(target, newType, false);
     }
 
     /**
@@ -2082,12 +2093,165 @@
      */
     public static
     MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
-        reorder = reorder.clone();
-        checkReorder(reorder, newType, target.type());
-        return target.permuteArguments(newType, reorder);
+        reorder = reorder.clone();  // get a private copy
+        MethodType oldType = target.type();
+        permuteArgumentChecks(reorder, newType, oldType);
+        if (USE_LAMBDA_FORM_EDITOR) {
+            // first detect dropped arguments and handle them separately
+            int[] originalReorder = reorder;
+            BoundMethodHandle result = target.rebind();
+            LambdaForm form = result.form;
+            int newArity = newType.parameterCount();
+            // Normalize the reordering into a real permutation,
+            // by removing duplicates and adding dropped elements.
+            // This somewhat improves lambda form caching, as well
+            // as simplifying the transform by breaking it up into steps.
+            for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) {
+                if (ddIdx > 0) {
+                    // We found a duplicated entry at reorder[ddIdx].
+                    // Example:  (x,y,z)->asList(x,y,z)
+                    // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1)
+                    // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0)
+                    // The starred element corresponds to the argument
+                    // deleted by the dupArgumentForm transform.
+                    int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos];
+                    boolean killFirst = false;
+                    for (int val; (val = reorder[--dstPos]) != dupVal; ) {
+                        // Set killFirst if the dup is larger than an intervening position.
+                        // This will remove at least one inversion from the permutation.
+                        if (dupVal > val) killFirst = true;
+                    }
+                    if (!killFirst) {
+                        srcPos = dstPos;
+                        dstPos = ddIdx;
+                    }
+                    form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos);
+                    assert (reorder[srcPos] == reorder[dstPos]);
+                    oldType = oldType.dropParameterTypes(dstPos, dstPos + 1);
+                    // contract the reordering by removing the element at dstPos
+                    int tailPos = dstPos + 1;
+                    System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos);
+                    reorder = Arrays.copyOf(reorder, reorder.length - 1);
+                } else {
+                    int dropVal = ~ddIdx, insPos = 0;
+                    while (insPos < reorder.length && reorder[insPos] < dropVal) {
+                        // Find first element of reorder larger than dropVal.
+                        // This is where we will insert the dropVal.
+                        insPos += 1;
+                    }
+                    Class<?> ptype = newType.parameterType(dropVal);
+                    form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype));
+                    oldType = oldType.insertParameterTypes(insPos, ptype);
+                    // expand the reordering by inserting an element at insPos
+                    int tailPos = insPos + 1;
+                    reorder = Arrays.copyOf(reorder, reorder.length + 1);
+                    System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos);
+                    reorder[insPos] = dropVal;
+                }
+                assert (permuteArgumentChecks(reorder, newType, oldType));
+            }
+            assert (reorder.length == newArity);  // a perfect permutation
+            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
+            form = form.editor().permuteArgumentsForm(1, reorder);
+            if (newType == result.type() && form == result.internalForm())
+                return result;
+            return result.copyWith(newType, form);
+        } else {
+            // first detect dropped arguments and handle them separately
+            MethodHandle originalTarget = target;
+            int newArity = newType.parameterCount();
+            for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) {
+                // dropIdx is missing from reorder; add it in at the end
+                int oldArity = reorder.length;
+                target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
+                reorder = Arrays.copyOf(reorder, oldArity+1);
+                reorder[oldArity] = dropIdx;
+            }
+            assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
+            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
+            BoundMethodHandle result = target.rebind();
+            LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList()));
+            return result.copyWith(newType, form);
+        }
     }
 
-    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
+    /** Return the first value in [0..newArity-1] that is not present in reorder. */
+    private static int findFirstDrop(int[] reorder, int newArity) {
+        final int BIT_LIMIT = 63;  // max number of bits in bit mask
+        if (newArity < BIT_LIMIT) {
+            long mask = 0;
+            for (int arg : reorder) {
+                assert(arg < newArity);
+                mask |= (1 << arg);
+            }
+            if (mask == (1 << newArity) - 1) {
+                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
+                return -1;
+            }
+            // find first zero
+            long zeroBit = Long.lowestOneBit(~mask);
+            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
+            assert(zeroPos < newArity);
+            return zeroPos;
+        }
+        BitSet mask = new BitSet(newArity);
+        for (int arg : reorder) {
+            assert(arg < newArity);
+            mask.set(arg);
+        }
+        int zeroPos = mask.nextClearBit(0);
+        if (zeroPos == newArity)
+            return -1;
+        return zeroPos;
+    }
+
+    /**
+     * Return an indication of any duplicate or omission in reorder.
+     * If the reorder contains a duplicate entry, return the index of the second occurrence.
+     * Otherwise, return ~(n), for the first n in [0..newArity-1] that is not present in reorder.
+     * Otherwise, return zero.
+     * If an element not in [0..newArity-1] is encountered, return reorder.length.
+     */
+    private static int findFirstDupOrDrop(int[] reorder, int newArity) {
+        final int BIT_LIMIT = 63;  // max number of bits in bit mask
+        if (newArity < BIT_LIMIT) {
+            long mask = 0;
+            for (int i = 0; i < reorder.length; i++) {
+                int arg = reorder[i];
+                if (arg >= newArity)  return reorder.length;
+                int bit = 1 << arg;
+                if ((mask & bit) != 0)
+                    return i;  // >0 indicates a dup
+                mask |= bit;
+            }
+            if (mask == (1 << newArity) - 1) {
+                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
+                return 0;
+            }
+            // find first zero
+            long zeroBit = Long.lowestOneBit(~mask);
+            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
+            assert(zeroPos < newArity);
+            return ~zeroPos;
+        } else {
+            // same algorithm, different bit set
+            BitSet mask = new BitSet(newArity);
+            for (int i = 0; i < reorder.length; i++) {
+                int arg = reorder[i];
+                if (arg >= newArity)  return reorder.length;
+                if (mask.get(arg))
+                    return i;  // >0 indicates a dup
+                mask.set(arg);
+            }
+            int zeroPos = mask.nextClearBit(0);
+            if (zeroPos == newArity) {
+                return 0;
+            }
+            return ~zeroPos;
+        }
+    }
+
+    private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) {
         if (newType.returnType() != oldType.returnType())
             throw newIllegalArgumentException("return types do not match",
                     oldType, newType);
@@ -2105,7 +2269,7 @@
                     throw newIllegalArgumentException("parameter types do not match after reorder",
                             oldType, newType);
             }
-            if (!bad)  return;
+            if (!bad)  return true;
         }
         throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
     }
@@ -2131,9 +2295,14 @@
             if (type == void.class)
                 throw newIllegalArgumentException("void type");
             Wrapper w = Wrapper.forPrimitiveType(type);
-            return insertArguments(identity(type), 0, w.convert(value, type));
+            value = w.convert(value, type);
+            if (w.zero().equals(value))
+                return zero(w, type);
+            return insertArguments(identity(type), 0, value);
         } else {
-            return identity(type).bindTo(type.cast(value));
+            if (value == null)
+                return zero(Wrapper.OBJECT, type);
+            return identity(type).bindTo(value);
         }
     }
 
@@ -2146,14 +2315,48 @@
      */
     public static
     MethodHandle identity(Class<?> type) {
-        if (type == void.class)
-            throw newIllegalArgumentException("void type");
-        else if (type == Object.class)
-            return ValueConversions.identity();
-        else if (type.isPrimitive())
-            return ValueConversions.identity(Wrapper.forPrimitiveType(type));
-        else
-            return MethodHandleImpl.makeReferenceIdentity(type);
+        Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT);
+        int pos = btw.ordinal();
+        MethodHandle ident = IDENTITY_MHS[pos];
+        if (ident == null) {
+            ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType()));
+        }
+        if (ident.type().returnType() == type)
+            return ident;
+        // something like identity(Foo.class); do not bother to intern these
+        assert(btw == Wrapper.OBJECT);
+        return makeIdentity(type);
+    }
+    private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
+    private static MethodHandle makeIdentity(Class<?> ptype) {
+        MethodType mtype = MethodType.methodType(ptype, ptype);
+        LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
+        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
+    }
+
+    private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
+        int pos = btw.ordinal();
+        MethodHandle zero = ZERO_MHS[pos];
+        if (zero == null) {
+            zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
+        }
+        if (zero.type().returnType() == rtype)
+            return zero;
+        assert(btw == Wrapper.OBJECT);
+        return makeZero(rtype);
+    }
+    private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
+    private static MethodHandle makeZero(Class<?> rtype) {
+        MethodType mtype = MethodType.methodType(rtype);
+        LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
+        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
+    }
+
+    synchronized private static MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = cache[pos];
+        if (prev != null) return prev;
+        return cache[pos] = value;
     }
 
     /**
@@ -2189,6 +2392,37 @@
     public static
     MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
         int insCount = values.length;
+        Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos);
+        if (insCount == 0)  return target;
+        BoundMethodHandle result = target.rebind();
+        for (int i = 0; i < insCount; i++) {
+            Object value = values[i];
+            Class<?> ptype = ptypes[pos+i];
+            if (ptype.isPrimitive()) {
+                result = insertArgumentPrimitive(result, pos, ptype, value);
+            } else {
+                value = ptype.cast(value);  // throw CCE if needed
+                result = result.bindArgumentL(pos, value);
+            }
+        }
+        return result;
+    }
+
+    private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos,
+                                                             Class<?> ptype, Object value) {
+        Wrapper w = Wrapper.forPrimitiveType(ptype);
+        // perform unboxing and/or primitive conversion
+        value = w.convert(value, ptype);
+        switch (w) {
+        case INT:     return result.bindArgumentI(pos, (int)value);
+        case LONG:    return result.bindArgumentJ(pos, (long)value);
+        case FLOAT:   return result.bindArgumentF(pos, (float)value);
+        case DOUBLE:  return result.bindArgumentD(pos, (double)value);
+        default:      return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
+        }
+    }
+
+    private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
         MethodType oldType = target.type();
         int outargs = oldType.parameterCount();
         int inargs  = outargs - insCount;
@@ -2196,31 +2430,7 @@
             throw newIllegalArgumentException("too many values to insert");
         if (pos < 0 || pos > inargs)
             throw newIllegalArgumentException("no argument type to append");
-        MethodHandle result = target;
-        for (int i = 0; i < insCount; i++) {
-            Object value = values[i];
-            Class<?> ptype = oldType.parameterType(pos+i);
-            if (ptype.isPrimitive()) {
-                BasicType btype = I_TYPE;
-                Wrapper w = Wrapper.forPrimitiveType(ptype);
-                switch (w) {
-                case LONG:    btype = J_TYPE; break;
-                case FLOAT:   btype = F_TYPE; break;
-                case DOUBLE:  btype = D_TYPE; break;
-                }
-                // perform unboxing and/or primitive conversion
-                value = w.convert(value, ptype);
-                result = result.bindArgument(pos, btype, value);
-                continue;
-            }
-            value = ptype.cast(value);  // throw CCE if needed
-            if (pos == 0) {
-                result = result.bindReceiver(value);
-            } else {
-                result = result.bindArgument(pos, L_TYPE, value);
-            }
-        }
-        return result;
+        return oldType.ptypes();
     }
 
     /**
@@ -2268,18 +2478,33 @@
     public static
     MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
         MethodType oldType = target.type();  // get NPE
+        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
+        if (dropped == 0)  return target;
+        BoundMethodHandle result = target.rebind();
+        LambdaForm lform = result.form;
+        if (USE_LAMBDA_FORM_EDITOR) {
+            int insertFormArg = 1 + pos;
+            for (Class<?> ptype : valueTypes) {
+                lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype));
+            }
+        } else {
+            lform = lform.addArguments(pos, valueTypes);
+        }
+        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
+        result = result.copyWith(newType, lform);
+        return result;
+    }
+
+    private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
         int dropped = valueTypes.size();
         MethodType.checkSlotCount(dropped);
-        if (dropped == 0)  return target;
         int outargs = oldType.parameterCount();
         int inargs  = outargs + dropped;
-        if (pos < 0 || pos >= inargs)
-            throw newIllegalArgumentException("no argument type to remove");
-        ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList());
-        ptypes.addAll(pos, valueTypes);
-        if (ptypes.size() != inargs)  throw newIllegalArgumentException("valueTypes");
-        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
-        return target.dropArguments(newType, pos, dropped);
+        if (pos < 0 || pos > outargs)
+            throw newIllegalArgumentException("no argument type to remove"
+                    + Arrays.asList(oldType, pos, valueTypes, inargs, outargs)
+                    );
+        return dropped;
     }
 
     /**
@@ -2401,32 +2626,47 @@
      */
     public static
     MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
-        MethodType targetType = target.type();
+        filterArgumentsCheckArity(target, pos, filters);
         MethodHandle adapter = target;
-        MethodType adapterType = null;
-        assert((adapterType = targetType) != null);
-        int maxPos = targetType.parameterCount();
-        if (pos + filters.length > maxPos)
-            throw newIllegalArgumentException("too many filters");
         int curPos = pos-1;  // pre-incremented
         for (MethodHandle filter : filters) {
             curPos += 1;
             if (filter == null)  continue;  // ignore null elements of filters
             adapter = filterArgument(adapter, curPos, filter);
-            assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
         }
-        assert(adapterType.equals(adapter.type()));
         return adapter;
     }
 
     /*non-public*/ static
     MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
+        filterArgumentChecks(target, pos, filter);
+        if (USE_LAMBDA_FORM_EDITOR) {
+            MethodType targetType = target.type();
+            MethodType filterType = filter.type();
+            BoundMethodHandle result = target.rebind();
+            Class<?> newParamType = filterType.parameterType(0);
+            LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
+            MethodType newType = targetType.changeParameterType(pos, newParamType);
+            result = result.copyWithExtendL(newType, lform, filter);
+            return result;
+        } else {
+            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
+        }
+    }
+
+    private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
+        MethodType targetType = target.type();
+        int maxPos = targetType.parameterCount();
+        if (pos + filters.length > maxPos)
+            throw newIllegalArgumentException("too many filters");
+    }
+
+    private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
         MethodType targetType = target.type();
         MethodType filterType = filter.type();
         if (filterType.parameterCount() != 1
             || filterType.returnType() != targetType.parameterType(pos))
             throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
-        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
     }
 
     /**
@@ -2537,12 +2777,36 @@
      */
     public static
     MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
+        MethodType newType = collectArgumentsChecks(target, pos, filter);
+        if (USE_LAMBDA_FORM_EDITOR) {
+            MethodType collectorType = filter.type();
+            BoundMethodHandle result = target.rebind();
+            LambdaForm lform;
+            if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) {
+                lform = result.editor().collectArgumentArrayForm(1 + pos, filter);
+                if (lform != null) {
+                    return result.copyWith(newType, lform);
+                }
+            }
+            lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType());
+            return result.copyWithExtendL(newType, lform, filter);
+        } else {
+            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
+        }
+    }
+
+    private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
         MethodType targetType = target.type();
         MethodType filterType = filter.type();
-        if (filterType.returnType() != void.class &&
-            filterType.returnType() != targetType.parameterType(pos))
+        Class<?> rtype = filterType.returnType();
+        List<Class<?>> filterArgs = filterType.parameterList();
+        if (rtype == void.class) {
+            return targetType.insertParameterTypes(pos, filterArgs);
+        }
+        if (rtype != targetType.parameterType(pos)) {
             throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
-        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
+        }
+        return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs);
     }
 
     /**
@@ -2606,15 +2870,26 @@
     MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
         MethodType targetType = target.type();
         MethodType filterType = filter.type();
+        filterReturnValueChecks(targetType, filterType);
+        if (USE_LAMBDA_FORM_EDITOR) {
+            BoundMethodHandle result = target.rebind();
+            BasicType rtype = BasicType.basicType(filterType.returnType());
+            LambdaForm lform = result.editor().filterReturnForm(rtype, false);
+            MethodType newType = targetType.changeReturnType(filterType.returnType());
+            result = result.copyWithExtendL(newType, lform, filter);
+            return result;
+        } else {
+            return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
+        }
+    }
+
+    private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException {
         Class<?> rtype = targetType.returnType();
         int filterValues = filterType.parameterCount();
         if (filterValues == 0
                 ? (rtype != void.class)
                 : (rtype != filterType.parameterType(0)))
-            throw newIllegalArgumentException("target and filter types do not match", target, filter);
-        // result = fold( lambda(retval, arg...) { filter(retval) },
-        //                lambda(        arg...) { target(arg...) } )
-        return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
+            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
     }
 
     /**
@@ -2695,24 +2970,40 @@
      */
     public static
     MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
-        int pos = 0;
+        int foldPos = 0;
         MethodType targetType = target.type();
         MethodType combinerType = combiner.type();
-        int foldPos = pos;
-        int foldArgs = combinerType.parameterCount();
-        int foldVals = combinerType.returnType() == void.class ? 0 : 1;
+        Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
+        if (USE_LAMBDA_FORM_EDITOR) {
+            BoundMethodHandle result = target.rebind();
+            boolean dropResult = (rtype == void.class);
+            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
+            LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType());
+            MethodType newType = targetType;
+            if (!dropResult)
+                newType = newType.dropParameterTypes(foldPos, foldPos + 1);
+            result = result.copyWithExtendL(newType, lform, combiner);
+            return result;
+        } else {
+            return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
+        }
+    }
+
+    private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
+        int foldArgs   = combinerType.parameterCount();
+        Class<?> rtype = combinerType.returnType();
+        int foldVals = rtype == void.class ? 0 : 1;
         int afterInsertPos = foldPos + foldVals;
         boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
         if (ok && !(combinerType.parameterList()
                     .equals(targetType.parameterList().subList(afterInsertPos,
                                                                afterInsertPos + foldArgs))))
             ok = false;
-        if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
+        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
             ok = false;
         if (!ok)
             throw misMatchedTypes("target and combiner types", targetType, combinerType);
-        MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
-        return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
+        return rtype;
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Wed Jul 05 20:00:59 2017 +0200
@@ -467,6 +467,75 @@
         return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
     }
 
+    /** Replace the last arrayLength parameter types with the component type of arrayType.
+     * @param arrayType any array type
+     * @param arrayLength the number of parameter types to change
+     * @return the resulting type
+     */
+    /*non-public*/ MethodType asSpreaderType(Class<?> arrayType, int arrayLength) {
+        assert(parameterCount() >= arrayLength);
+        int spreadPos = ptypes.length - arrayLength;
+        if (arrayLength == 0)  return this;  // nothing to change
+        if (arrayType == Object[].class) {
+            if (isGeneric())  return this;  // nothing to change
+            if (spreadPos == 0) {
+                // no leading arguments to preserve; go generic
+                MethodType res = genericMethodType(arrayLength);
+                if (rtype != Object.class) {
+                    res = res.changeReturnType(rtype);
+                }
+                return res;
+            }
+        }
+        Class<?> elemType = arrayType.getComponentType();
+        assert(elemType != null);
+        for (int i = spreadPos; i < ptypes.length; i++) {
+            if (ptypes[i] != elemType) {
+                Class<?>[] fixedPtypes = ptypes.clone();
+                Arrays.fill(fixedPtypes, i, ptypes.length, elemType);
+                return methodType(rtype, fixedPtypes);
+            }
+        }
+        return this;  // arguments check out; no change
+    }
+
+    /** Return the leading parameter type, which must exist and be a reference.
+     *  @return the leading parameter type, after error checks
+     */
+    /*non-public*/ Class<?> leadingReferenceParameter() {
+        Class<?> ptype;
+        if (ptypes.length == 0 ||
+            (ptype = ptypes[0]).isPrimitive())
+            throw newIllegalArgumentException("no leading reference parameter");
+        return ptype;
+    }
+
+    /** Delete the last parameter type and replace it with arrayLength copies of the component type of arrayType.
+     * @param arrayType any array type
+     * @param arrayLength the number of parameter types to insert
+     * @return the resulting type
+     */
+    /*non-public*/ MethodType asCollectorType(Class<?> arrayType, int arrayLength) {
+        assert(parameterCount() >= 1);
+        assert(lastParameterType().isAssignableFrom(arrayType));
+        MethodType res;
+        if (arrayType == Object[].class) {
+            res = genericMethodType(arrayLength);
+            if (rtype != Object.class) {
+                res = res.changeReturnType(rtype);
+            }
+        } else {
+            Class<?> elemType = arrayType.getComponentType();
+            assert(elemType != null);
+            res = methodType(rtype, Collections.nCopies(arrayLength, elemType));
+        }
+        if (ptypes.length == 1) {
+            return res;
+        } else {
+            return res.insertParameterTypes(0, parameterList().subList(0, ptypes.length-1));
+        }
+    }
+
     /**
      * Finds or creates a method type with some parameter types omitted.
      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
@@ -574,6 +643,10 @@
         return genericMethodType(parameterCount());
     }
 
+    /*non-public*/ boolean isGeneric() {
+        return this == erase() && !hasPrimitives();
+    }
+
     /**
      * Converts all primitive types to their corresponding wrapper types.
      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
@@ -726,44 +799,137 @@
         return sj.toString();
     }
 
-
+    /** True if the old return type can always be viewed (w/o casting) under new return type,
+     *  and the new parameters can be viewed (w/o casting) under the old parameter types.
+     */
     /*non-public*/
-    boolean isViewableAs(MethodType newType) {
-        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
+    boolean isViewableAs(MethodType newType, boolean keepInterfaces) {
+        if (!VerifyType.isNullConversion(returnType(), newType.returnType(), keepInterfaces))
             return false;
+        return parametersAreViewableAs(newType, keepInterfaces);
+    }
+    /** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
+    /*non-public*/
+    boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
+        if (form == newType.form && form.erasedType == this)
+            return true;  // my reference parameters are all Object
+        if (ptypes == newType.ptypes)
+            return true;
         int argc = parameterCount();
         if (argc != newType.parameterCount())
             return false;
         for (int i = 0; i < argc; i++) {
-            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
+            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces))
                 return false;
         }
         return true;
     }
     /*non-public*/
-    boolean isCastableTo(MethodType newType) {
-        int argc = parameterCount();
-        if (argc != newType.parameterCount())
-            return false;
-        return true;
-    }
-    /*non-public*/
     boolean isConvertibleTo(MethodType newType) {
+        MethodTypeForm oldForm = this.form();
+        MethodTypeForm newForm = newType.form();
+        if (oldForm == newForm)
+            // same parameter count, same primitive/object mix
+            return true;
         if (!canConvert(returnType(), newType.returnType()))
             return false;
-        int argc = parameterCount();
-        if (argc != newType.parameterCount())
+        Class<?>[] srcTypes = newType.ptypes;
+        Class<?>[] dstTypes = ptypes;
+        if (srcTypes == dstTypes)
+            return true;
+        int argc;
+        if ((argc = srcTypes.length) != dstTypes.length)
             return false;
-        for (int i = 0; i < argc; i++) {
-            if (!canConvert(newType.parameterType(i), parameterType(i)))
+        if (argc <= 1) {
+            if (argc == 1 && !canConvert(srcTypes[0], dstTypes[0]))
                 return false;
+            return true;
+        }
+        if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
+            (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
+            // Somewhat complicated test to avoid a loop of 2 or more trips.
+            // If either type has only Object parameters, we know we can convert.
+            assert(canConvertParameters(srcTypes, dstTypes));
+            return true;
+        }
+        return canConvertParameters(srcTypes, dstTypes);
+    }
+
+    /** Returns true if MHs.explicitCastArguments produces the same result as MH.asType.
+     *  If the type conversion is impossible for either, the result should be false.
+     */
+    /*non-public*/
+    boolean explicitCastEquivalentToAsType(MethodType newType) {
+        if (this == newType)  return true;
+        if (!explicitCastEquivalentToAsType(rtype, newType.rtype)) {
+            return false;
+        }
+        Class<?>[] srcTypes = newType.ptypes;
+        Class<?>[] dstTypes = ptypes;
+        if (dstTypes == srcTypes) {
+            return true;
+        }
+        if (dstTypes.length != srcTypes.length) {
+            return false;
+        }
+        for (int i = 0; i < dstTypes.length; i++) {
+            if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
+                return false;
+            }
         }
         return true;
     }
+
+    /** Reports true if the src can be converted to the dst, by both asType and MHs.eCE,
+     *  and with the same effect.
+     *  MHs.eCA has the following "upgrades" to MH.asType:
+     *  1. interfaces are unchecked (that is, treated as if aliased to Object)
+     *     Therefore, {@code Object->CharSequence} is possible in both cases but has different semantics
+     *  2. the full matrix of primitive-to-primitive conversions is supported
+     *     Narrowing like {@code long->byte} and basic-typing like {@code boolean->int}
+     *     are not supported by asType, but anything supported by asType is equivalent
+     *     with MHs.eCE.
+     *  3a. unboxing conversions can be followed by the full matrix of primitive conversions
+     *  3b. unboxing of null is permitted (creates a zero primitive value)
+     *     Most unboxing conversions, like {@code Object->int}, has potentially
+     *     different behaviors for asType vs. MHs.eCE, because the dynamic value
+     *     might be a wrapper of a type that requires narrowing, like {@code (Object)1L->byte}.
+     *     The equivalence is only certain if the static src type is a wrapper,
+     *     and the conversion will be a widening one.
+     * Other than interfaces, reference-to-reference conversions are the same.
+     * Boxing primitives to references is the same for both operators.
+     */
+    private static boolean explicitCastEquivalentToAsType(Class<?> src, Class<?> dst) {
+        if (src == dst || dst == Object.class || dst == void.class)  return true;
+        if (src.isPrimitive()) {
+            // Could be a prim/prim conversion, where casting is a strict superset.
+            // Or a boxing conversion, which is always to an exact wrapper class.
+            return canConvert(src, dst);
+        } else if (dst.isPrimitive()) {
+            Wrapper dw = Wrapper.forPrimitiveType(dst);
+            // Watch out:  If src is Number or Object, we could get dynamic narrowing conversion.
+            // The conversion is known to be widening only if the wrapper type is statically visible.
+            return (Wrapper.isWrapperType(src) &&
+                    dw.isConvertibleFrom(Wrapper.forWrapperType(src)));
+        } else {
+            // R->R always works, but we have to avoid a check-cast to an interface.
+            return !dst.isInterface() || dst.isAssignableFrom(src);
+        }
+    }
+
+    private boolean canConvertParameters(Class<?>[] srcTypes, Class<?>[] dstTypes) {
+        for (int i = 0; i < srcTypes.length; i++) {
+            if (!canConvert(srcTypes[i], dstTypes[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /*non-public*/
     static boolean canConvert(Class<?> src, Class<?> dst) {
         // short-circuit a few cases:
-        if (src == dst || dst == Object.class)  return true;
+        if (src == dst || src == Object.class || dst == Object.class)  return true;
         // the remainder of this logic is documented in MethodHandle.asType
         if (src.isPrimitive()) {
             // can force void to an explicit null, a la reflect.Method.invoke
@@ -905,7 +1071,7 @@
         if (!descriptor.startsWith("(") ||  // also generates NPE if needed
             descriptor.indexOf(')') < 0 ||
             descriptor.indexOf('.') >= 0)
-            throw new IllegalArgumentException("not a method descriptor: "+descriptor);
+            throw newIllegalArgumentException("not a method descriptor: "+descriptor);
         List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
         Class<?> rtype = types.remove(types.size() - 1);
         checkSlotCount(types.size());
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java	Wed Jul 05 20:00:59 2017 +0200
@@ -47,15 +47,17 @@
     final int[] argToSlotTable, slotToArgTable;
     final long argCounts;               // packed slot & value counts
     final long primCounts;              // packed prim & double counts
-    final int vmslots;                  // total number of parameter slots
     final MethodType erasedType;        // the canonical erasure
     final MethodType basicType;         // the canonical erasure, with primitives simplified
 
     // Cached adapter information:
-    @Stable String typeString;           // argument type signature characters
-    @Stable MethodHandle genericInvoker; // JVM hook for inexact invoke
-    @Stable MethodHandle basicInvoker;   // cached instance of MH.invokeBasic
-    @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction
+    @Stable final MethodHandle[] methodHandles;
+    // Indexes into methodHandles:
+    static final int
+            MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
+            MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
+            MH_UNINIT_CS      =  2,  // uninitialized call site
+            MH_LIMIT          =  3;
 
     // Cached lambda form information, for basic types only:
     final @Stable LambdaForm[] lambdaForms;
@@ -68,26 +70,55 @@
             LF_INVINTERFACE   =  4,
             LF_INVSTATIC_INIT =  5,  // DMH invokeStatic with <clinit> barrier
             LF_INTERPRET      =  6,  // LF interpreter
-            LF_COUNTER        =  7,  // CMH wrapper
-            LF_REINVOKE       =  8,  // other wrapper
-            LF_EX_LINKER      =  9,  // invokeExact_MT
-            LF_EX_INVOKER     = 10,  // invokeExact MH
-            LF_GEN_LINKER     = 11,
-            LF_GEN_INVOKER    = 12,
+            LF_REBIND         =  7,  // BoundMethodHandle
+            LF_DELEGATE       =  8,  // DelegatingMethodHandle
+            LF_EX_LINKER      =  9,  // invokeExact_MT (for invokehandle)
+            LF_EX_INVOKER     = 10,  // MHs.invokeExact
+            LF_GEN_LINKER     = 11,  // generic invoke_MT (for invokehandle)
+            LF_GEN_INVOKER    = 12,  // generic MHs.invoke
             LF_CS_LINKER      = 13,  // linkToCallSite_CS
             LF_MH_LINKER      = 14,  // linkToCallSite_MH
-            LF_GWC            = 15,
-            LF_LIMIT          = 16;
+            LF_GWC            = 15,  // guardWithCatch (catchException)
+            LF_GWT            = 16,  // guardWithTest
+            LF_LIMIT          = 17;
 
+    /** Return the type corresponding uniquely (1-1) to this MT-form.
+     *  It might have any primitive returns or arguments, but will have no references except Object.
+     */
     public MethodType erasedType() {
         return erasedType;
     }
 
+    /** Return the basic type derived from the erased type of this MT-form.
+     *  A basic type is erased (all references Object) and also has all primitive
+     *  types (except int, long, float, double, void) normalized to int.
+     *  Such basic types correspond to low-level JVM calling sequences.
+     */
     public MethodType basicType() {
         return basicType;
     }
 
+    private boolean assertIsBasicType() {
+        // primitives must be flattened also
+        assert(erasedType == basicType)
+                : "erasedType: " + erasedType + " != basicType: " + basicType;
+        return true;
+    }
+
+    public MethodHandle cachedMethodHandle(int which) {
+        assert(assertIsBasicType());
+        return methodHandles[which];
+    }
+
+    synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = methodHandles[which];
+        if (prev != null)  return prev;
+        return methodHandles[which] = mh;
+    }
+
     public LambdaForm cachedLambdaForm(int which) {
+        assert(assertIsBasicType());
         return lambdaForms[which];
     }
 
@@ -98,28 +129,6 @@
         return lambdaForms[which] = form;
     }
 
-    public MethodHandle basicInvoker() {
-        assert(erasedType == basicType) : "erasedType: " + erasedType + " != basicType: " + basicType;  // primitives must be flattened also
-        MethodHandle invoker = basicInvoker;
-        if (invoker != null)  return invoker;
-        invoker = DirectMethodHandle.make(invokeBasicMethod(basicType));
-        basicInvoker = invoker;
-        return invoker;
-    }
-
-    // This next one is called from LambdaForm.NamedFunction.<init>.
-    /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
-        assert(basicType == basicType.basicType());
-        try {
-            // Do approximately the same as this public API call:
-            //   Lookup.findVirtual(MethodHandle.class, name, type);
-            // But bypass access and corner case checks, since we know exactly what we need.
-            return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
-         } catch (ReflectiveOperationException ex) {
-            throw newInternalError("JVM cannot find invoker for "+basicType, ex);
-        }
-    }
-
     /**
      * Build an MTF for a given type, which must have all references erased to Object.
      * This MTF will stand for that type and all un-erased variations.
@@ -172,6 +181,16 @@
             this.basicType = erasedType;
         } else {
             this.basicType = MethodType.makeImpl(bt, bpts, true);
+            // fill in rest of data from the basic type:
+            MethodTypeForm that = this.basicType.form();
+            assert(this != that);
+            this.primCounts = that.primCounts;
+            this.argCounts = that.argCounts;
+            this.argToSlotTable = that.argToSlotTable;
+            this.slotToArgTable = that.slotToArgTable;
+            this.methodHandles = null;
+            this.lambdaForms = null;
+            return;
         }
         if (lac != 0) {
             int slot = ptypeCount + lac;
@@ -187,10 +206,14 @@
                 argToSlotTab[1+i]  = slot;
             }
             assert(slot == 0);  // filled the table
-        }
-        this.primCounts = pack(lrc, prc, lac, pac);
-        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
-        if (slotToArgTab == null) {
+        } else if (pac != 0) {
+            // have primitives but no long primitives; share slot counts with generic
+            assert(ptypeCount == pslotCount);
+            MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
+            assert(this != that);
+            slotToArgTab = that.slotToArgTable;
+            argToSlotTab = that.argToSlotTable;
+        } else {
             int slot = ptypeCount; // first arg is deepest in stack
             slotToArgTab = new int[slot+1];
             argToSlotTab = new int[1+ptypeCount];
@@ -201,19 +224,17 @@
                 argToSlotTab[1+i]  = slot;
             }
         }
+        this.primCounts = pack(lrc, prc, lac, pac);
+        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
         this.argToSlotTable = argToSlotTab;
         this.slotToArgTable = slotToArgTab;
 
         if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 
-        // send a few bits down to the JVM:
-        this.vmslots = parameterSlotCount();
-
-        if (basicType == erasedType) {
-            lambdaForms = new LambdaForm[LF_LIMIT];
-        } else {
-            lambdaForms = null;  // could be basicType.form().lambdaForms;
-        }
+        // Initialize caches, but only for basic types
+        assert(basicType == erasedType);
+        this.lambdaForms = new LambdaForm[LF_LIMIT];
+        this.methodHandles = new MethodHandle[MH_LIMIT];
     }
 
     private static long pack(int a, int b, int c, int d) {
@@ -300,7 +321,7 @@
      */
     public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
         Class<?>[] ptypes = mt.ptypes();
-        Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
+        Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
         Class<?> rtype = mt.returnType();
         Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
         if (ptc == null && rtc == null) {
@@ -368,7 +389,7 @@
     /** Canonicalize each param type in the given array.
      *  Return null if all types are already canonicalized.
      */
-    static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
+    static Class<?>[] canonicalizeAll(Class<?>[] ts, int how) {
         Class<?>[] cs = null;
         for (int imax = ts.length, i = 0; i < imax; i++) {
             Class<?> c = canonicalize(ts[i], how);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,38 +25,77 @@
 
 package java.lang.invoke;
 
-import static java.lang.invoke.LambdaForm.*;
 import static java.lang.invoke.LambdaForm.BasicType.*;
+import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
  * A method handle whose behavior is determined only by its LambdaForm.
  * @author jrose
  */
-final class SimpleMethodHandle extends MethodHandle {
+final class SimpleMethodHandle extends BoundMethodHandle {
     private SimpleMethodHandle(MethodType type, LambdaForm form) {
         super(type, form);
     }
 
-    /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
+    /*non-public*/ static BoundMethodHandle make(MethodType type, LambdaForm form) {
         return new SimpleMethodHandle(type, form);
     }
 
+    /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
+
+    /*non-public*/ public SpeciesData speciesData() {
+            return SPECIES_DATA;
+    }
+
     @Override
-    MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
-        MethodType type2 = type().dropParameterTypes(pos, pos+1);
-        LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
-        return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
+    /*non-public*/ BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
+        return make(mt, lf);
+    }
+
+    @Override
+    String internalProperties() {
+        return "\n& Class="+getClass().getSimpleName();
+    }
+
+    @Override
+    /*non-public*/ public int fieldCount() {
+        return 0;
     }
 
     @Override
-    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
-        LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
-        return new SimpleMethodHandle(srcType, newForm);
+    /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
+        return BoundMethodHandle.bindSingle(mt, lf, narg); // Use known fast path.
+    }
+    @Override
+    /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
+        try {
+            return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, narg);
+        } catch (Throwable ex) {
+            throw uncaughtException(ex);
+        }
     }
-
+    @Override
+    /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
+        try {
+            return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, narg);
+        } catch (Throwable ex) {
+            throw uncaughtException(ex);
+        }
+    }
     @Override
-    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
-        LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList()));
-        return new SimpleMethodHandle(newType, form2);
+    /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
+        try {
+            return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, narg);
+        } catch (Throwable ex) {
+            throw uncaughtException(ex);
+        }
+    }
+    @Override
+    /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
+        try {
+            return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, narg);
+        } catch (Throwable ex) {
+            throw uncaughtException(ex);
+        }
     }
 }
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java	Wed Jul 05 20:00:59 2017 +0200
@@ -94,9 +94,20 @@
     // For sharing of ConstructorAccessors. This branching structure
     // is currently only two levels deep (i.e., one root Constructor
     // and potentially many Constructor objects pointing to it.)
+    //
+    // If this branching structure would ever contain cycles, deadlocks can
+    // occur in annotation code.
     private Constructor<T>      root;
 
     /**
+     * Used by Excecutable for annotation sharing.
+     */
+    @Override
+    Executable getRoot() {
+        return root;
+    }
+
+    /**
      * Package-private constructor used by ReflectAccess to enable
      * instantiation of these objects in Java code from the java.lang
      * package via sun.reflect.LangReflectAccess.
@@ -132,6 +143,9 @@
         // which implicitly requires that new java.lang.reflect
         // objects be fabricated for each reflective call on Class
         // objects.)
+        if (this.root != null)
+            throw new IllegalArgumentException("Can not copy a non-root Constructor");
+
         Constructor<T> res = new Constructor<>(clazz,
                                                parameterTypes,
                                                exceptionTypes, modifiers, slot,
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java	Wed Jul 05 20:00:59 2017 +0200
@@ -53,6 +53,11 @@
     abstract byte[] getAnnotationBytes();
 
     /**
+     * Accessor method to allow code sharing
+     */
+    abstract Executable getRoot();
+
+    /**
      * Does the Executable have generic information.
      */
     abstract boolean hasGenericInformation();
@@ -540,11 +545,16 @@
 
     private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
         if (declaredAnnotations == null) {
-            declaredAnnotations = AnnotationParser.parseAnnotations(
-                getAnnotationBytes(),
-                sun.misc.SharedSecrets.getJavaLangAccess().
-                getConstantPool(getDeclaringClass()),
-                getDeclaringClass());
+            Executable root = getRoot();
+            if (root != null) {
+                declaredAnnotations = root.declaredAnnotations();
+            } else {
+                declaredAnnotations = AnnotationParser.parseAnnotations(
+                    getAnnotationBytes(),
+                    sun.misc.SharedSecrets.getJavaLangAccess().
+                    getConstantPool(getDeclaringClass()),
+                    getDeclaringClass());
+            }
         }
         return declaredAnnotations;
     }
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java	Wed Jul 05 20:00:59 2017 +0200
@@ -81,6 +81,9 @@
     // For sharing of FieldAccessors. This branching structure is
     // currently only two levels deep (i.e., one root Field and
     // potentially many Field objects pointing to it.)
+    //
+    // If this branching structure would ever contain cycles, deadlocks can
+    // occur in annotation code.
     private Field               root;
 
     // Generics infrastructure
@@ -141,6 +144,9 @@
         // which implicitly requires that new java.lang.reflect
         // objects be fabricated for each reflective call on Class
         // objects.)
+        if (this.root != null)
+            throw new IllegalArgumentException("Can not copy a non-root Field");
+
         Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
         res.root = this;
         // Might as well eagerly propagate this if already present
@@ -1137,10 +1143,15 @@
 
     private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
         if (declaredAnnotations == null) {
-            declaredAnnotations = AnnotationParser.parseAnnotations(
-                annotations, sun.misc.SharedSecrets.getJavaLangAccess().
-                getConstantPool(getDeclaringClass()),
-                getDeclaringClass());
+            Field root = this.root;
+            if (root != null) {
+                declaredAnnotations = root.declaredAnnotations();
+            } else {
+                declaredAnnotations = AnnotationParser.parseAnnotations(
+                        annotations,
+                        sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),
+                        getDeclaringClass());
+            }
         }
         return declaredAnnotations;
     }
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java	Wed Jul 05 20:00:59 2017 +0200
@@ -79,6 +79,9 @@
     // For sharing of MethodAccessors. This branching structure is
     // currently only two levels deep (i.e., one root Method and
     // potentially many Method objects pointing to it.)
+    //
+    // If this branching structure would ever contain cycles, deadlocks can
+    // occur in annotation code.
     private Method              root;
 
     // Generics infrastructure
@@ -144,6 +147,9 @@
         // which implicitly requires that new java.lang.reflect
         // objects be fabricated for each reflective call on Class
         // objects.)
+        if (this.root != null)
+            throw new IllegalArgumentException("Can not copy a non-root Method");
+
         Method res = new Method(clazz, name, parameterTypes, returnType,
                                 exceptionTypes, modifiers, slot, signature,
                                 annotations, parameterAnnotations, annotationDefault);
@@ -153,6 +159,14 @@
         return res;
     }
 
+    /**
+     * Used by Excecutable for annotation sharing.
+     */
+    @Override
+    Executable getRoot() {
+        return root;
+    }
+
     @Override
     boolean hasGenericInformation() {
         return (getGenericSignature() != null);
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Wed Jul 05 20:00:59 2017 +0200
@@ -354,10 +354,11 @@
      * @exception NullPointerException if {@code name} is {@code null}.
      */
     protected Class<?> findClass(final String name)
-         throws ClassNotFoundException
+        throws ClassNotFoundException
     {
+        final Class<?> result;
         try {
-            return AccessController.doPrivileged(
+            result = AccessController.doPrivileged(
                 new PrivilegedExceptionAction<Class<?>>() {
                     public Class<?> run() throws ClassNotFoundException {
                         String path = name.replace('.', '/').concat(".class");
@@ -369,13 +370,17 @@
                                 throw new ClassNotFoundException(name, e);
                             }
                         } else {
-                            throw new ClassNotFoundException(name);
+                            return null;
                         }
                     }
                 }, acc);
         } catch (java.security.PrivilegedActionException pae) {
             throw (ClassNotFoundException) pae.getException();
         }
+        if (result == null) {
+            throw new ClassNotFoundException(name);
+        }
+        return result;
     }
 
     /*
--- a/jdk/src/java.base/share/classes/java/time/Duration.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java	Wed Jul 05 20:00:59 2017 +0200
@@ -424,7 +424,7 @@
             return 0;
         }
         try {
-            long val = Long.parseLong(text, 10, start, end);
+            long val = Long.parseLong(text, start, end, 10);
             return Math.multiplyExact(val, multiplier);
         } catch (NumberFormatException | ArithmeticException ex) {
             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);
@@ -437,7 +437,7 @@
             return 0;
         }
         try {
-            int fraction = Integer.parseInt(text, 10, start, end);
+            int fraction = Integer.parseInt(text, start, end, 10);
 
             // for number strings smaller than 9 digits, interpret as if there
             // were trailing zeros
--- a/jdk/src/java.base/share/classes/java/time/Period.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/time/Period.java	Wed Jul 05 20:00:59 2017 +0200
@@ -358,7 +358,7 @@
         if (start < 0 || end < 0) {
             return 0;
         }
-        int val = Integer.parseInt(text, 10, start, end);
+        int val = Integer.parseInt(text, start, end, 10);
         try {
             return Math.multiplyExact(val, negate);
         } catch (ArithmeticException ex) {
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 20:00:59 2017 +0200
@@ -3865,7 +3865,7 @@
 
         @Override
         public boolean contains(Object o) {
-            return indexOf(o) != -1;
+            return indexOf(o) >= 0;
         }
 
         @Override
--- a/jdk/src/java.base/share/classes/java/util/LinkedList.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/LinkedList.java	Wed Jul 05 20:00:59 2017 +0200
@@ -314,7 +314,7 @@
      * @return {@code true} if this list contains the specified element
      */
     public boolean contains(Object o) {
-        return indexOf(o) != -1;
+        return indexOf(o) >= 0;
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java	Wed Jul 05 20:00:59 2017 +0200
@@ -406,7 +406,7 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        return indexOf(o) != -1;
+        return indexOf(o) >= 0;
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/UUID.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/UUID.java	Wed Jul 05 20:00:59 2017 +0200
@@ -194,7 +194,8 @@
      *
      */
     public static UUID fromString(String name) {
-        if (name.length() > 36) {
+        int len = name.length();
+        if (len > 36) {
             throw new IllegalArgumentException("UUID string too large");
         }
 
@@ -214,15 +215,14 @@
             throw new IllegalArgumentException("Invalid UUID string: " + name);
         }
 
-        long mostSigBits = Long.parseLong(name, 16, 0, dash1) & 0xffffffffL;
+        long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL;
         mostSigBits <<= 16;
-        mostSigBits |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL;
+        mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL;
         mostSigBits <<= 16;
-        mostSigBits |= Long.parseLong(name, 16, dash2 + 1, dash3) & 0xffffL;
-
-        long leastSigBits = Long.parseLong(name, 16, dash3 + 1, dash4) & 0xffffL;
+        mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL;
+        long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL;
         leastSigBits <<= 48;
-        leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL;
+        leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL;
 
         return new UUID(mostSigBits, leastSigBits);
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 20:00:59 2017 +0200
@@ -49,6 +49,7 @@
 import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
 import java.security.AccessControlContext;
 import java.security.ProtectionDomain;
 import java.security.Permissions;
@@ -80,9 +81,9 @@
  *
  * <p>For applications that require separate or custom pools, a {@code
  * ForkJoinPool} may be constructed with a given target parallelism
- * level; by default, equal to the number of available processors. The
- * pool attempts to maintain enough active (or available) threads by
- * dynamically adding, suspending, or resuming internal worker
+ * level; by default, equal to the number of available processors.
+ * The pool attempts to maintain enough active (or available) threads
+ * by dynamically adding, suspending, or resuming internal worker
  * threads, even if some tasks are stalled waiting to join others.
  * However, no such adjustments are guaranteed in the face of blocked
  * I/O or other unmanaged synchronization. The nested {@link
@@ -142,6 +143,9 @@
  * - the class name of a {@link ForkJoinWorkerThreadFactory}
  * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
  * - the class name of a {@link UncaughtExceptionHandler}
+ * <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
+ * - the maximum number of allowed extra threads to maintain target
+ * parallelism (default 256).
  * </ul>
  * If a {@link SecurityManager} is present and no factory is
  * specified, then the default pool uses a factory supplying
@@ -178,7 +182,14 @@
      * that may be stolen by other workers.  Preference rules give
      * first priority to processing tasks from their own queues (LIFO
      * or FIFO, depending on mode), then to randomized FIFO steals of
-     * tasks in other queues.
+     * tasks in other queues.  This framework began as vehicle for
+     * supporting tree-structured parallelism using work-stealing.
+     * Over time, its scalability advantages led to extensions and
+     * changes to better support more diverse usage contexts.  Because
+     * most internal methods and nested classes are interrelated,
+     * their main rationale and descriptions are presented here;
+     * individual methods and nested classes contain only brief
+     * comments about details.
      *
      * WorkQueues
      * ==========
@@ -198,201 +209,318 @@
      * (http://research.sun.com/scalable/pubs/index.html) and
      * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
      * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
-     * See also "Correct and Efficient Work-Stealing for Weak Memory
-     * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
-     * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
-     * analysis of memory ordering (atomic, volatile etc) issues.  The
-     * main differences ultimately stem from GC requirements that we
-     * null out taken slots as soon as we can, to maintain as small a
-     * footprint as possible even in programs generating huge numbers
-     * of tasks. To accomplish this, we shift the CAS arbitrating pop
-     * vs poll (steal) from being on the indices ("base" and "top") to
-     * the slots themselves.  So, both a successful pop and poll
-     * mainly entail a CAS of a slot from non-null to null.  Because
-     * we rely on CASes of references, we do not need tag bits on base
-     * or top.  They are simple ints as used in any circular
+     * The main differences ultimately stem from GC requirements that
+     * we null out taken slots as soon as we can, to maintain as small
+     * a footprint as possible even in programs generating huge
+     * numbers of tasks. To accomplish this, we shift the CAS
+     * arbitrating pop vs poll (steal) from being on the indices
+     * ("base" and "top") to the slots themselves.
+     *
+     * Adding tasks then takes the form of a classic array push(task):
+     *    q.array[q.top] = task; ++q.top;
+     *
+     * (The actual code needs to null-check and size-check the array,
+     * properly fence the accesses, and possibly signal waiting
+     * workers to start scanning -- see below.)  Both a successful pop
+     * and poll mainly entail a CAS of a slot from non-null to null.
+     *
+     * The pop operation (always performed by owner) is:
+     *   if ((base != top) and
+     *        (the task at top slot is not null) and
+     *        (CAS slot to null))
+     *           decrement top and return task;
+     *
+     * And the poll operation (usually by a stealer) is
+     *    if ((base != top) and
+     *        (the task at base slot is not null) and
+     *        (base has not changed) and
+     *        (CAS slot to null))
+     *           increment base and return task;
+     *
+     * Because we rely on CASes of references, we do not need tag bits
+     * on base or top.  They are simple ints as used in any circular
      * array-based queue (see for example ArrayDeque).  Updates to the
-     * indices must still be ordered in a way that guarantees that top
-     * == base means the queue is empty, but otherwise may err on the
-     * side of possibly making the queue appear nonempty when a push,
-     * pop, or poll have not fully committed. Note that this means
-     * that the poll operation, considered individually, is not
-     * wait-free. One thief cannot successfully continue until another
-     * in-progress one (or, if previously empty, a push) completes.
-     * However, in the aggregate, we ensure at least probabilistic
+     * indices guarantee that top == base means the queue is empty,
+     * but otherwise may err on the side of possibly making the queue
+     * appear nonempty when a push, pop, or poll have not fully
+     * committed. (Method isEmpty() checks the case of a partially
+     * completed removal of the last element.)  Because of this, the
+     * poll operation, considered individually, is not wait-free. One
+     * thief cannot successfully continue until another in-progress
+     * one (or, if previously empty, a push) completes.  However, in
+     * the aggregate, we ensure at least probabilistic
      * non-blockingness.  If an attempted steal fails, a thief always
      * chooses a different random victim target to try next. So, in
      * order for one thief to progress, it suffices for any
      * in-progress poll or new push on any empty queue to
      * complete. (This is why we normally use method pollAt and its
      * variants that try once at the apparent base index, else
-     * consider alternative actions, rather than method poll.)
+     * consider alternative actions, rather than method poll, which
+     * retries.)
      *
-     * This approach also enables support of a user mode in which local
-     * task processing is in FIFO, not LIFO order, simply by using
-     * poll rather than pop.  This can be useful in message-passing
-     * frameworks in which tasks are never joined.  However neither
-     * mode considers affinities, loads, cache localities, etc, so
-     * rarely provide the best possible performance on a given
-     * machine, but portably provide good throughput by averaging over
-     * these factors.  (Further, even if we did try to use such
-     * information, we do not usually have a basis for exploiting it.
-     * For example, some sets of tasks profit from cache affinities,
-     * but others are harmed by cache pollution effects.)
+     * This approach also enables support of a user mode in which
+     * local task processing is in FIFO, not LIFO order, simply by
+     * using poll rather than pop.  This can be useful in
+     * message-passing frameworks in which tasks are never joined.
+     * However neither mode considers affinities, loads, cache
+     * localities, etc, so rarely provide the best possible
+     * performance on a given machine, but portably provide good
+     * throughput by averaging over these factors.  Further, even if
+     * we did try to use such information, we do not usually have a
+     * basis for exploiting it.  For example, some sets of tasks
+     * profit from cache affinities, but others are harmed by cache
+     * pollution effects. Additionally, even though it requires
+     * scanning, long-term throughput is often best using random
+     * selection rather than directed selection policies, so cheap
+     * randomization of sufficient quality is used whenever
+     * applicable.  Various Marsaglia XorShifts (some with different
+     * shift constants) are inlined at use points.
      *
      * WorkQueues are also used in a similar way for tasks submitted
      * to the pool. We cannot mix these tasks in the same queues used
-     * for work-stealing (this would contaminate lifo/fifo
-     * processing). Instead, we randomly associate submission queues
+     * by workers. Instead, we randomly associate submission queues
      * with submitting threads, using a form of hashing.  The
      * ThreadLocalRandom probe value serves as a hash code for
      * choosing existing queues, and may be randomly repositioned upon
      * contention with other submitters.  In essence, submitters act
      * like workers except that they are restricted to executing local
      * tasks that they submitted (or in the case of CountedCompleters,
-     * others with the same root task).  However, because most
-     * shared/external queue operations are more expensive than
-     * internal, and because, at steady state, external submitters
-     * will compete for CPU with workers, ForkJoinTask.join and
-     * related methods disable them from repeatedly helping to process
-     * tasks if all workers are active.  Insertion of tasks in shared
+     * others with the same root task).  Insertion of tasks in shared
      * mode requires a lock (mainly to protect in the case of
-     * resizing) but we use only a simple spinlock (using bits in
-     * field qlock), because submitters encountering a busy queue move
-     * on to try or create other queues -- they block only when
-     * creating and registering new queues.
+     * resizing) but we use only a simple spinlock (using field
+     * qlock), because submitters encountering a busy queue move on to
+     * try or create other queues -- they block only when creating and
+     * registering new queues. Additionally, "qlock" saturates to an
+     * unlockable value (-1) at shutdown. Unlocking still can be and
+     * is performed by cheaper ordered writes of "qlock" in successful
+     * cases, but uses CAS in unsuccessful cases.
      *
      * Management
      * ==========
      *
      * The main throughput advantages of work-stealing stem from
      * decentralized control -- workers mostly take tasks from
-     * themselves or each other. We cannot negate this in the
-     * implementation of other management responsibilities. The main
-     * tactic for avoiding bottlenecks is packing nearly all
-     * essentially atomic control state into two volatile variables
-     * that are by far most often read (not written) as status and
-     * consistency checks.
+     * themselves or each other, at rates that can exceed a billion
+     * per second.  The pool itself creates, activates (enables
+     * scanning for and running tasks), deactivates, blocks, and
+     * terminates threads, all with minimal central information.
+     * There are only a few properties that we can globally track or
+     * maintain, so we pack them into a small number of variables,
+     * often maintaining atomicity without blocking or locking.
+     * Nearly all essentially atomic control state is held in two
+     * volatile variables that are by far most often read (not
+     * written) as status and consistency checks. (Also, field
+     * "config" holds unchanging configuration state.)
      *
-     * Field "ctl" contains 64 bits holding all the information needed
-     * to atomically decide to add, inactivate, enqueue (on an event
+     * Field "ctl" contains 64 bits holding information needed to
+     * atomically decide to add, inactivate, enqueue (on an event
      * queue), dequeue, and/or re-activate workers.  To enable this
      * packing, we restrict maximum parallelism to (1<<15)-1 (which is
      * far in excess of normal operating range) to allow ids, counts,
      * and their negations (used for thresholding) to fit into 16bit
-     * fields.
+     * subfields.
      *
-     * Field "plock" is a form of sequence lock with a saturating
-     * shutdown bit (similarly for per-queue "qlocks"), mainly
-     * protecting updates to the workQueues array, as well as to
-     * enable shutdown.  When used as a lock, it is normally only very
-     * briefly held, so is nearly always available after at most a
-     * brief spin, but we use a monitor-based backup strategy to
-     * block when needed.
+     * Field "runState" holds lockable state bits (STARTED, STOP, etc)
+     * also protecting updates to the workQueues array.  When used as
+     * a lock, it is normally held only for a few instructions (the
+     * only exceptions are one-time array initialization and uncommon
+     * resizing), so is nearly always available after at most a brief
+     * spin. But to be extra-cautious, after spinning, method
+     * awaitRunStateLock (called only if an initial CAS fails), uses a
+     * wait/notify mechanics on a builtin monitor to block when
+     * (rarely) needed. This would be a terrible idea for a highly
+     * contended lock, but most pools run without the lock ever
+     * contending after the spin limit, so this works fine as a more
+     * conservative alternative. Because we don't otherwise have an
+     * internal Object to use as a monitor, the "stealCounter" (an
+     * AtomicLong) is used when available (it too must be lazily
+     * initialized; see externalSubmit).
+     *
+     * Usages of "runState" vs "ctl" interact in only one case:
+     * deciding to add a worker thread (see tryAddWorker), in which
+     * case the ctl CAS is performed while the lock is held.
      *
      * Recording WorkQueues.  WorkQueues are recorded in the
-     * "workQueues" array that is created upon first use and expanded
-     * if necessary.  Updates to the array while recording new workers
-     * and unrecording terminated ones are protected from each other
-     * by a lock but the array is otherwise concurrently readable, and
-     * accessed directly.  To simplify index-based operations, the
-     * array size is always a power of two, and all readers must
-     * tolerate null slots. Worker queues are at odd indices. Shared
-     * (submission) queues are at even indices, up to a maximum of 64
-     * slots, to limit growth even if array needs to expand to add
-     * more workers. Grouping them together in this way simplifies and
-     * speeds up task scanning.
+     * "workQueues" array. The array is created upon first use (see
+     * externalSubmit) and expanded if necessary.  Updates to the
+     * array while recording new workers and unrecording terminated
+     * ones are protected from each other by the runState lock, but
+     * the array is otherwise concurrently readable, and accessed
+     * directly. We also ensure that reads of the array reference
+     * itself never become too stale. To simplify index-based
+     * operations, the array size is always a power of two, and all
+     * readers must tolerate null slots. Worker queues are at odd
+     * indices. Shared (submission) queues are at even indices, up to
+     * a maximum of 64 slots, to limit growth even if array needs to
+     * expand to add more workers. Grouping them together in this way
+     * simplifies and speeds up task scanning.
      *
      * All worker thread creation is on-demand, triggered by task
      * submissions, replacement of terminated workers, and/or
      * compensation for blocked workers. However, all other support
      * code is set up to work with other policies.  To ensure that we
-     * do not hold on to worker references that would prevent GC, ALL
+     * do not hold on to worker references that would prevent GC, All
      * accesses to workQueues are via indices into the workQueues
      * array (which is one source of some of the messy code
      * constructions here). In essence, the workQueues array serves as
-     * a weak reference mechanism. Thus for example the wait queue
-     * field of ctl stores indices, not references.  Access to the
-     * workQueues in associated methods (for example signalWork) must
-     * both index-check and null-check the IDs. All such accesses
-     * ignore bad IDs by returning out early from what they are doing,
-     * since this can only be associated with termination, in which
-     * case it is OK to give up.  All uses of the workQueues array
-     * also check that it is non-null (even if previously
-     * non-null). This allows nulling during termination, which is
-     * currently not necessary, but remains an option for
-     * resource-revocation-based shutdown schemes. It also helps
-     * reduce JIT issuance of uncommon-trap code, which tends to
-     * unnecessarily complicate control flow in some methods.
+     * a weak reference mechanism. Thus for example the stack top
+     * subfield of ctl stores indices, not references.
+     *
+     * Queuing Idle Workers. Unlike HPC work-stealing frameworks, we
+     * cannot let workers spin indefinitely scanning for tasks when
+     * none can be found immediately, and we cannot start/resume
+     * workers unless there appear to be tasks available.  On the
+     * other hand, we must quickly prod them into action when new
+     * tasks are submitted or generated. In many usages, ramp-up time
+     * to activate workers is the main limiting factor in overall
+     * performance, which is compounded at program start-up by JIT
+     * compilation and allocation. So we streamline this as much as
+     * possible.
+     *
+     * The "ctl" field atomically maintains active and total worker
+     * counts as well as a queue to place waiting threads so they can
+     * be located for signalling. Active counts also play the role of
+     * quiescence indicators, so are decremented when workers believe
+     * that there are no more tasks to execute. The "queue" is
+     * actually a form of Treiber stack.  A stack is ideal for
+     * activating threads in most-recently used order. This improves
+     * performance and locality, outweighing the disadvantages of
+     * being prone to contention and inability to release a worker
+     * unless it is topmost on stack.  We park/unpark workers after
+     * pushing on the idle worker stack (represented by the lower
+     * 32bit subfield of ctl) when they cannot find work.  The top
+     * stack state holds the value of the "scanState" field of the
+     * worker: its index and status, plus a version counter that, in
+     * addition to the count subfields (also serving as version
+     * stamps) provide protection against Treiber stack ABA effects.
+     *
+     * Field scanState is used by both workers and the pool to manage
+     * and track whether a worker is INACTIVE (possibly blocked
+     * waiting for a signal), or SCANNING for tasks (when neither hold
+     * it is busy running tasks).  When a worker is inactivated, its
+     * scanState field is set, and is prevented from executing tasks,
+     * even though it must scan once for them to avoid queuing
+     * races. Note that scanState updates lag queue CAS releases so
+     * usage requires care. When queued, the lower 16 bits of
+     * scanState must hold its pool index. So we place the index there
+     * upon initialization (see registerWorker) and otherwise keep it
+     * there or restore it when necessary.
      *
-     * Event Queuing. Unlike HPC work-stealing frameworks, we cannot
-     * let workers spin indefinitely scanning for tasks when none can
-     * be found immediately, and we cannot start/resume workers unless
-     * there appear to be tasks available.  On the other hand, we must
-     * quickly prod them into action when new tasks are submitted or
-     * generated. In many usages, ramp-up time to activate workers is
-     * the main limiting factor in overall performance (this is
-     * compounded at program start-up by JIT compilation and
-     * allocation). So we try to streamline this as much as possible.
-     * We park/unpark workers after placing in an event wait queue
-     * when they cannot find work. This "queue" is actually a simple
-     * Treiber stack, headed by the "id" field of ctl, plus a 15bit
-     * counter value (that reflects the number of times a worker has
-     * been inactivated) to avoid ABA effects (we need only as many
-     * version numbers as worker threads). Successors are held in
-     * field WorkQueue.nextWait.  Queuing deals with several intrinsic
-     * races, mainly that a task-producing thread can miss seeing (and
-     * signalling) another thread that gave up looking for work but
-     * has not yet entered the wait queue. We solve this by requiring
-     * a full sweep of all workers (via repeated calls to method
-     * scan()) both before and after a newly waiting worker is added
-     * to the wait queue.  Because enqueued workers may actually be
-     * rescanning rather than waiting, we set and clear the "parker"
+     * Memory ordering.  See "Correct and Efficient Work-Stealing for
+     * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
+     * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
+     * analysis of memory ordering requirements in work-stealing
+     * algorithms similar to the one used here.  We usually need
+     * stronger than minimal ordering because we must sometimes signal
+     * workers, requiring Dekker-like full-fences to avoid lost
+     * signals.  Arranging for enough ordering without expensive
+     * over-fencing requires tradeoffs among the supported means of
+     * expressing access constraints. The most central operations,
+     * taking from queues and updating ctl state, require full-fence
+     * CAS.  Array slots are read using the emulation of volatiles
+     * provided by Unsafe.  Access from other threads to WorkQueue
+     * base, top, and array requires a volatile load of the first of
+     * any of these read.  We use the convention of declaring the
+     * "base" index volatile, and always read it before other fields.
+     * The owner thread must ensure ordered updates, so writes use
+     * ordered intrinsics unless they can piggyback on those for other
+     * writes.  Similar conventions and rationales hold for other
+     * WorkQueue fields (such as "currentSteal") that are only written
+     * by owners but observed by others.
+     *
+     * Creating workers. To create a worker, we pre-increment total
+     * count (serving as a reservation), and attempt to construct a
+     * ForkJoinWorkerThread via its factory. Upon construction, the
+     * new thread invokes registerWorker, where it constructs a
+     * WorkQueue and is assigned an index in the workQueues array
+     * (expanding the array if necessary). The thread is then
+     * started. Upon any exception across these steps, or null return
+     * from factory, deregisterWorker adjusts counts and records
+     * accordingly.  If a null return, the pool continues running with
+     * fewer than the target number workers. If exceptional, the
+     * exception is propagated, generally to some external caller.
+     * Worker index assignment avoids the bias in scanning that would
+     * occur if entries were sequentially packed starting at the front
+     * of the workQueues array. We treat the array as a simple
+     * power-of-two hash table, expanding as needed. The seedIndex
+     * increment ensures no collisions until a resize is needed or a
+     * worker is deregistered and replaced, and thereafter keeps
+     * probability of collision low. We cannot use
+     * ThreadLocalRandom.getProbe() for similar purposes here because
+     * the thread has not started yet, but do so for creating
+     * submission queues for existing external threads.
+     *
+     * Deactivation and waiting. Queuing encounters several intrinsic
+     * races; most notably that a task-producing thread can miss
+     * seeing (and signalling) another thread that gave up looking for
+     * work but has not yet entered the wait queue.  When a worker
+     * cannot find a task to steal, it deactivates and enqueues. Very
+     * often, the lack of tasks is transient due to GC or OS
+     * scheduling. To reduce false-alarm deactivation, scanners
+     * compute checksums of queue states during sweeps.  (The
+     * stability checks used here and elsewhere are probabilistic
+     * variants of snapshot techniques -- see Herlihy & Shavit.)
+     * Workers give up and try to deactivate only after the sum is
+     * stable across scans. Further, to avoid missed signals, they
+     * repeat this scanning process after successful enqueuing until
+     * again stable.  In this state, the worker cannot take/run a task
+     * it sees until it is released from the queue, so the worker
+     * itself eventually tries to release itself or any successor (see
+     * tryRelease).  Otherwise, upon an empty scan, a deactivated
+     * worker uses an adaptive local spin construction (see awaitWork)
+     * before blocking (via park). Note the unusual conventions about
+     * Thread.interrupts surrounding parking and other blocking:
+     * Because interrupts are used solely to alert threads to check
+     * termination, which is checked anyway upon blocking, we clear
+     * status (using Thread.interrupted) before any call to park, so
+     * that park does not immediately return due to status being set
+     * via some other unrelated call to interrupt in user code.
+     *
+     * Signalling and activation.  Workers are created or activated
+     * only when there appears to be at least one task they might be
+     * able to find and execute.  Upon push (either by a worker or an
+     * external submission) to a previously (possibly) empty queue,
+     * workers are signalled if idle, or created if fewer exist than
+     * the given parallelism level.  These primary signals are
+     * buttressed by others whenever other threads remove a task from
+     * a queue and notice that there are other tasks there as well.
+     * On most platforms, signalling (unpark) overhead time is
+     * noticeably long, and the time between signalling a thread and
+     * it actually making progress can be very noticeably long, so it
+     * is worth offloading these delays from critical paths as much as
+     * possible. Also, because inactive workers are often rescanning
+     * or spinning rather than blocking, we set and clear the "parker"
      * field of WorkQueues to reduce unnecessary calls to unpark.
      * (This requires a secondary recheck to avoid missed signals.)
-     * Note the unusual conventions about Thread.interrupts
-     * surrounding parking and other blocking: Because interrupts are
-     * used solely to alert threads to check termination, which is
-     * checked anyway upon blocking, we clear status (using
-     * Thread.interrupted) before any call to park, so that park does
-     * not immediately return due to status being set via some other
-     * unrelated call to interrupt in user code.
-     *
-     * Signalling.  We create or wake up workers only when there
-     * appears to be at least one task they might be able to find and
-     * execute.  When a submission is added or another worker adds a
-     * task to a queue that has fewer than two tasks, they signal
-     * waiting workers (or trigger creation of new ones if fewer than
-     * the given parallelism level -- signalWork).  These primary
-     * signals are buttressed by others whenever other threads remove
-     * a task from a queue and notice that there are other tasks there
-     * as well.  So in general, pools will be over-signalled. On most
-     * platforms, signalling (unpark) overhead time is noticeably
-     * long, and the time between signalling a thread and it actually
-     * making progress can be very noticeably long, so it is worth
-     * offloading these delays from critical paths as much as
-     * possible. Additionally, workers spin-down gradually, by staying
-     * alive so long as they see the ctl state changing.  Similar
-     * stability-sensing techniques are also used before blocking in
-     * awaitJoin and helpComplete.
      *
      * Trimming workers. To release resources after periods of lack of
      * use, a worker starting to wait when the pool is quiescent will
-     * time out and terminate if the pool has remained quiescent for a
-     * given period -- a short period if there are more threads than
-     * parallelism, longer as the number of threads decreases. This
-     * will slowly propagate, eventually terminating all workers after
-     * periods of non-use.
+     * time out and terminate (see awaitWork) if the pool has remained
+     * quiescent for period IDLE_TIMEOUT, increasing the period as the
+     * number of threads decreases, eventually removing all workers.
+     * Also, when more than two spare threads exist, excess threads
+     * are immediately terminated at the next quiescent point.
+     * (Padding by two avoids hysteresis.)
      *
-     * Shutdown and Termination. A call to shutdownNow atomically sets
-     * a plock bit and then (non-atomically) sets each worker's
-     * qlock status, cancels all unprocessed tasks, and wakes up
-     * all waiting workers.  Detecting whether termination should
-     * commence after a non-abrupt shutdown() call requires more work
-     * and bookkeeping. We need consensus about quiescence (i.e., that
-     * there is no more work). The active count provides a primary
-     * indication but non-abrupt shutdown still requires a rechecking
-     * scan for any workers that are inactive but not queued.
+     * Shutdown and Termination. A call to shutdownNow invokes
+     * tryTerminate to atomically set a runState bit. The calling
+     * thread, as well as every other worker thereafter terminating,
+     * helps terminate others by setting their (qlock) status,
+     * cancelling their unprocessed tasks, and waking them up, doing
+     * so repeatedly until stable (but with a loop bounded by the
+     * number of workers).  Calls to non-abrupt shutdown() preface
+     * this by checking whether termination should commence. This
+     * relies primarily on the active count bits of "ctl" maintaining
+     * consensus -- tryTerminate is called from awaitWork whenever
+     * quiescent. However, external submitters do not take part in
+     * this consensus.  So, tryTerminate sweeps through queues (until
+     * stable) to ensure lack of in-flight submissions and workers
+     * about to process them before triggering the "STOP" phase of
+     * termination. (Note: there is an intrinsic conflict if
+     * helpQuiescePool is called when shutdown is enabled. Both wait
+     * for quiescence, but tryTerminate is biased to not trigger until
+     * helpQuiescePool completes.)
+     *
      *
      * Joining Tasks
      * =============
@@ -403,9 +531,9 @@
      * just let them block (as in Thread.join).  We also cannot just
      * reassign the joiner's run-time stack with another and replace
      * it later, which would be a form of "continuation", that even if
-     * possible is not necessarily a good idea since we sometimes need
-     * both an unblocked task and its continuation to progress.
-     * Instead we combine two tactics:
+     * possible is not necessarily a good idea since we may need both
+     * an unblocked task and its continuation to progress.  Instead we
+     * combine two tactics:
      *
      *   Helping: Arranging for the joiner to execute some task that it
      *      would be running if the steal had not occurred.
@@ -425,16 +553,16 @@
      * The ManagedBlocker extension API can't use helping so relies
      * only on compensation in method awaitBlocker.
      *
-     * The algorithm in tryHelpStealer entails a form of "linear"
-     * helping: Each worker records (in field currentSteal) the most
-     * recent task it stole from some other worker. Plus, it records
-     * (in field currentJoin) the task it is currently actively
-     * joining. Method tryHelpStealer uses these markers to try to
-     * find a worker to help (i.e., steal back a task from and execute
-     * it) that could hasten completion of the actively joined task.
-     * In essence, the joiner executes a task that would be on its own
-     * local deque had the to-be-joined task not been stolen. This may
-     * be seen as a conservative variant of the approach in Wagner &
+     * The algorithm in helpStealer entails a form of "linear
+     * helping".  Each worker records (in field currentSteal) the most
+     * recent task it stole from some other worker (or a submission).
+     * It also records (in field currentJoin) the task it is currently
+     * actively joining. Method helpStealer uses these markers to try
+     * to find a worker to help (i.e., steal back a task from and
+     * execute it) that could hasten completion of the actively joined
+     * task.  Thus, the joiner executes a task that would be on its
+     * own local deque had the to-be-joined task not been stolen. This
+     * is a conservative variant of the approach described in Wagner &
      * Calder "Leapfrogging: a portable technique for implementing
      * efficient futures" SIGPLAN Notices, 1993
      * (http://portal.acm.org/citation.cfm?id=155354). It differs in
@@ -452,37 +580,40 @@
      * which means that we miss links in the chain during long-lived
      * tasks, GC stalls etc (which is OK since blocking in such cases
      * is usually a good idea).  (4) We bound the number of attempts
-     * to find work (see MAX_HELP) and fall back to suspending the
+     * to find work using checksums and fall back to suspending the
      * worker and if necessary replacing it with another.
      *
-     * Helping actions for CountedCompleters are much simpler: Method
-     * helpComplete can take and execute any task with the same root
-     * as the task being waited on. However, this still entails some
-     * traversal of completer chains, so is less efficient than using
-     * CountedCompleters without explicit joins.
+     * Helping actions for CountedCompleters do not require tracking
+     * currentJoins: Method helpComplete takes and executes any task
+     * with the same root as the task being waited on (preferring
+     * local pops to non-local polls). However, this still entails
+     * some traversal of completer chains, so is less efficient than
+     * using CountedCompleters without explicit joins.
      *
-     * It is impossible to keep exactly the target parallelism number
-     * of threads running at any given time.  Determining the
-     * existence of conservatively safe helping targets, the
-     * availability of already-created spares, and the apparent need
-     * to create new spares are all racy, so we rely on multiple
-     * retries of each.  Compensation in the apparent absence of
-     * helping opportunities is challenging to control on JVMs, where
-     * GC and other activities can stall progress of tasks that in
-     * turn stall out many other dependent tasks, without us being
-     * able to determine whether they will ever require compensation.
-     * Even though work-stealing otherwise encounters little
-     * degradation in the presence of more threads than cores,
-     * aggressively adding new threads in such cases entails risk of
-     * unwanted positive feedback control loops in which more threads
-     * cause more dependent stalls (as well as delayed progress of
-     * unblocked threads to the point that we know they are available)
-     * leading to more situations requiring more threads, and so
-     * on. This aspect of control can be seen as an (analytically
-     * intractable) game with an opponent that may choose the worst
-     * (for us) active thread to stall at any time.  We take several
-     * precautions to bound losses (and thus bound gains), mainly in
-     * methods tryCompensate and awaitJoin.
+     * Compensation does not aim to keep exactly the target
+     * parallelism number of unblocked threads running at any given
+     * time. Some previous versions of this class employed immediate
+     * compensations for any blocked join. However, in practice, the
+     * vast majority of blockages are transient byproducts of GC and
+     * other JVM or OS activities that are made worse by replacement.
+     * Currently, compensation is attempted only after validating that
+     * all purportedly active threads are processing tasks by checking
+     * field WorkQueue.scanState, which eliminates most false
+     * positives.  Also, compensation is bypassed (tolerating fewer
+     * threads) in the most common case in which it is rarely
+     * beneficial: when a worker with an empty queue (thus no
+     * continuation tasks) blocks on a join and there still remain
+     * enough threads to ensure liveness.
+     *
+     * The compensation mechanism may be bounded.  Bounds for the
+     * commonPool (see commonMaxSpares) better enable JVMs to cope
+     * with programming errors and abuse before running out of
+     * resources to do so. In other cases, users may supply factories
+     * that limit thread construction. The effects of bounding in this
+     * pool (like all others) is imprecise.  Total worker counts are
+     * decremented when threads deregister, not when they exit and
+     * resources are reclaimed by the JVM and OS. So the number of
+     * simultaneously live threads may transiently exceed bounds.
      *
      * Common Pool
      * ===========
@@ -492,34 +623,52 @@
      * never be used, we minimize initial construction overhead and
      * footprint to the setup of about a dozen fields, with no nested
      * allocation. Most bootstrapping occurs within method
-     * fullExternalPush during the first submission to the pool.
+     * externalSubmit during the first submission to the pool.
      *
      * When external threads submit to the common pool, they can
-     * perform subtask processing (see externalHelpJoin and related
-     * methods).  This caller-helps policy makes it sensible to set
-     * common pool parallelism level to one (or more) less than the
-     * total number of available cores, or even zero for pure
-     * caller-runs.  We do not need to record whether external
-     * submissions are to the common pool -- if not, externalHelpJoin
-     * returns quickly (at the most helping to signal some common pool
-     * workers). These submitters would otherwise be blocked waiting
-     * for completion, so the extra effort (with liberally sprinkled
-     * task status checks) in inapplicable cases amounts to an odd
-     * form of limited spin-wait before blocking in ForkJoinTask.join.
+     * perform subtask processing (see externalHelpComplete and
+     * related methods) upon joins.  This caller-helps policy makes it
+     * sensible to set common pool parallelism level to one (or more)
+     * less than the total number of available cores, or even zero for
+     * pure caller-runs.  We do not need to record whether external
+     * submissions are to the common pool -- if not, external help
+     * methods return quickly. These submitters would otherwise be
+     * blocked waiting for completion, so the extra effort (with
+     * liberally sprinkled task status checks) in inapplicable cases
+     * amounts to an odd form of limited spin-wait before blocking in
+     * ForkJoinTask.join.
      *
      * As a more appropriate default in managed environments, unless
      * overridden by system properties, we use workers of subclass
      * InnocuousForkJoinWorkerThread when there is a SecurityManager
      * present. These workers have no permissions set, do not belong
      * to any user-defined ThreadGroup, and erase all ThreadLocals
-     * after executing any top-level task (see WorkQueue.runTask). The
-     * associated mechanics (mainly in ForkJoinWorkerThread) may be
-     * JVM-dependent and must access particular Thread class fields to
-     * achieve this effect.
+     * after executing any top-level task (see WorkQueue.runTask).
+     * The associated mechanics (mainly in ForkJoinWorkerThread) may
+     * be JVM-dependent and must access particular Thread class fields
+     * to achieve this effect.
      *
      * Style notes
      * ===========
      *
+     * Memory ordering relies mainly on Unsafe intrinsics that carry
+     * the further responsibility of explicitly performing null- and
+     * bounds- checks otherwise carried out implicitly by JVMs.  This
+     * can be awkward and ugly, but also reflects the need to control
+     * outcomes across the unusual cases that arise in very racy code
+     * with very few invariants. So these explicit checks would exist
+     * in some form anyway.  All fields are read into locals before
+     * use, and null-checked if they are references.  This is usually
+     * done in a "C"-like style of listing declarations at the heads
+     * of methods or blocks, and using inline assignments on first
+     * encounter.  Array bounds-checks are usually performed by
+     * masking with array.length-1, which relies on the invariant that
+     * these arrays are created with positive lengths, which is itself
+     * paranoically checked. Nearly all explicit checks lead to
+     * bypass/return, not exception throws, because they may
+     * legitimately arise due to cancellation/revocation during
+     * shutdown.
+     *
      * There is a lot of representation-level coupling among classes
      * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask.  The
      * fields of WorkQueue maintain data structures managed by
@@ -527,22 +676,13 @@
      * trying to reduce this, since any associated future changes in
      * representations will need to be accompanied by algorithmic
      * changes anyway. Several methods intrinsically sprawl because
-     * they must accumulate sets of consistent reads of volatiles held
-     * in local variables.  Methods signalWork() and scan() are the
-     * main bottlenecks, so are especially heavily
-     * micro-optimized/mangled.  There are lots of inline assignments
-     * (of form "while ((local = field) != 0)") which are usually the
-     * simplest way to ensure the required read orderings (which are
-     * sometimes critical). This leads to a "C"-like style of listing
-     * declarations of these locals at the heads of methods or blocks.
-     * There are several occurrences of the unusual "do {} while
-     * (!cas...)"  which is the simplest way to force an update of a
-     * CAS'ed variable. There are also other coding oddities (including
-     * several unnecessary-looking hoisted null checks) that help
-     * some methods perform reasonably even when interpreted (not
-     * compiled).
+     * they must accumulate sets of consistent reads of fields held in
+     * local variables.  There are also other coding oddities
+     * (including several unnecessary-looking hoisted null checks)
+     * that help some methods perform reasonably even when interpreted
+     * (not compiled).
      *
-     * The order of declarations in this file is:
+     * The order of declarations in this file is (with a few exceptions):
      * (1) Static utility functions
      * (2) Nested (static) classes
      * (3) Static fields
@@ -609,56 +749,37 @@
         public final boolean exec() { return true; }
     }
 
+    // Constants shared across ForkJoinPool and WorkQueue
+
+    // Bounds
+    static final int SMASK        = 0xffff;        // short bits == max index
+    static final int MAX_CAP      = 0x7fff;        // max #workers - 1
+    static final int EVENMASK     = 0xfffe;        // even short bits
+    static final int SQMASK       = 0x007e;        // max 64 (even) slots
+
+    // Masks and units for WorkQueue.scanState and ctl sp subfield
+    static final int SCANNING     = 1;             // false when running tasks
+    static final int INACTIVE     = 1 << 31;       // must be negative
+    static final int SS_SEQ       = 1 << 16;       // version count
+
+    // Mode bits for ForkJoinPool.config and WorkQueue.config
+    static final int MODE_MASK    = 0xffff << 16;  // top half of int
+    static final int LIFO_QUEUE   = 0;
+    static final int FIFO_QUEUE   = 1 << 16;
+    static final int SHARED_QUEUE = 1 << 31;       // must be negative
+
     /**
      * Queues supporting work-stealing as well as external task
-     * submission. See above for main rationale and algorithms.
-     * Implementation relies heavily on "Unsafe" intrinsics
-     * and selective use of "volatile":
-     *
-     * Field "base" is the index (mod array.length) of the least valid
-     * queue slot, which is always the next position to steal (poll)
-     * from if nonempty. Reads and writes require volatile orderings
-     * but not CAS, because updates are only performed after slot
-     * CASes.
-     *
-     * Field "top" is the index (mod array.length) of the next queue
-     * slot to push to or pop from. It is written only by owner thread
-     * for push, or under lock for external/shared push, and accessed
-     * by other threads only after reading (volatile) base.  Both top
-     * and base are allowed to wrap around on overflow, but (top -
-     * base) (or more commonly -(base - top) to force volatile read of
-     * base before top) still estimates size. The lock ("qlock") is
-     * forced to -1 on termination, causing all further lock attempts
-     * to fail. (Note: we don't need CAS for termination state because
-     * upon pool shutdown, all shared-queues will stop being used
-     * anyway.)  Nearly all lock bodies are set up so that exceptions
-     * within lock bodies are "impossible" (modulo JVM errors that
-     * would cause failure anyway.)
-     *
-     * The array slots are read and written using the emulation of
-     * volatiles/atomics provided by Unsafe. Insertions must in
-     * general use putOrderedObject as a form of releasing store to
-     * ensure that all writes to the task object are ordered before
-     * its publication in the queue.  All removals entail a CAS to
-     * null.  The array is always a power of two. To ensure safety of
-     * Unsafe array operations, all accesses perform explicit null
-     * checks and implicit bounds checks via power-of-two masking.
-     *
-     * In addition to basic queuing support, this class contains
-     * fields described elsewhere to control execution. It turns out
-     * to work better memory-layout-wise to include them in this class
-     * rather than a separate class.
-     *
+     * submission. See above for descriptions and algorithms.
      * Performance on most platforms is very sensitive to placement of
      * instances of both WorkQueues and their arrays -- we absolutely
      * do not want multiple WorkQueue instances or multiple queue
-     * arrays sharing cache lines. (It would be best for queue objects
-     * and their arrays to share, but there is nothing available to
-     * help arrange that). The @Contended annotation alerts JVMs to
-     * try to keep instances apart.
+     * arrays sharing cache lines. The @Contended annotation alerts
+     * JVMs to try to keep instances apart.
      */
     @sun.misc.Contended
     static final class WorkQueue {
+
         /**
          * Capacity of work-stealing queue array upon initialization.
          * Must be a power of two; at least 4, but should be larger to
@@ -679,13 +800,13 @@
          */
         static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 
-        volatile int eventCount;   // encoded inactivation count; < 0 if inactive
-        int nextWait;              // encoded record of next event waiter
+        // Instance fields
+        volatile int scanState;    // versioned, <0: inactive; odd:scanning
+        int stackPred;             // pool stack (ctl) predecessor
         int nsteals;               // number of steals
-        int hint;                  // steal index hint
-        short poolIndex;           // index of this queue in pool
-        final short mode;          // 0: lifo, > 0: fifo, < 0: shared
-        volatile int qlock;        // 1: locked, -1: terminate; else 0
+        int hint;                  // randomization and stealer index hint
+        int config;                // pool index and mode
+        volatile int qlock;        // 1: locked, < 0: terminate; else 0
         volatile int base;         // index of next slot for poll
         int top;                   // index of next slot for push
         ForkJoinTask<?>[] array;   // the elements (initially unallocated)
@@ -693,19 +814,23 @@
         final ForkJoinWorkerThread owner; // owning thread or null if shared
         volatile Thread parker;    // == owner during call to park; else null
         volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
-        ForkJoinTask<?> currentSteal; // current non-local task being executed
+        volatile ForkJoinTask<?> currentSteal; // mainly used by helpStealer
 
-        WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
-                  int seed) {
+        WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
             this.pool = pool;
             this.owner = owner;
-            this.mode = (short)mode;
-            this.hint = seed; // store initial seed for runWorker
             // Place indices in the center of array (that is not yet allocated)
             base = top = INITIAL_QUEUE_CAPACITY >>> 1;
         }
 
         /**
+         * Returns an exportable index (used by ForkJoinWorkerThread).
+         */
+        final int getPoolIndex() {
+            return (config & 0xffff) >>> 1; // ignore odd/even tag bit
+        }
+
+        /**
          * Returns the approximate number of tasks in the queue.
          */
         final int queueSize() {
@@ -719,12 +844,10 @@
          * near-empty queue has at least one unclaimed task.
          */
         final boolean isEmpty() {
-            ForkJoinTask<?>[] a; int m, s;
-            int n = base - (s = top);
-            return (n >= 0 ||
-                    (n == -1 &&
-                     ((a = array) == null ||
-                      (m = a.length - 1) < 0 ||
+            ForkJoinTask<?>[] a; int n, m, s;
+            return ((n = base - (s = top)) >= 0 ||
+                    (n == -1 &&           // possibly one task
+                     ((a = array) == null || (m = a.length - 1) < 0 ||
                       U.getObject
                       (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
         }
@@ -738,12 +861,15 @@
          */
         final void push(ForkJoinTask<?> task) {
             ForkJoinTask<?>[] a; ForkJoinPool p;
-            int s = top, n;
+            int b = base, s = top, n;
             if ((a = array) != null) {    // ignore if queue removed
-                int m = a.length - 1;
+                int m = a.length - 1;     // fenced write for task visibility
                 U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
-                if ((n = (top = s + 1) - base) <= 2)
-                    (p = pool).signalWork(p.workQueues, this);
+                U.putOrderedInt(this, QTOP, s + 1);
+                if ((n = s - b) <= 1) {
+                    if ((p = pool) != null)
+                        p.signalWork(p.workQueues, this);
+                }
                 else if (n >= m)
                     growArray();
             }
@@ -764,7 +890,7 @@
             if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
                 (t = top) - (b = base) > 0) {
                 int mask = size - 1;
-                do {
+                do { // emulate poll from old array, push to new array
                     ForkJoinTask<?> x;
                     int oldj = ((b & oldMask) << ASHIFT) + ABASE;
                     int j    = ((b &    mask) << ASHIFT) + ABASE;
@@ -789,7 +915,7 @@
                     if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
                         break;
                     if (U.compareAndSwapObject(a, j, t, null)) {
-                        top = s;
+                        U.putOrderedInt(this, QTOP, s);
                         return t;
                     }
                 }
@@ -800,7 +926,7 @@
         /**
          * Takes a task in FIFO order if b is base of queue and a task
          * can be claimed without contention. Specialized versions
-         * appear in ForkJoinPool methods scan and tryHelpStealer.
+         * appear in ForkJoinPool methods scan and helpStealer.
          */
         final ForkJoinTask<?> pollAt(int b) {
             ForkJoinTask<?> t; ForkJoinTask<?>[] a;
@@ -808,7 +934,7 @@
                 int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
                 if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
                     base == b && U.compareAndSwapObject(a, j, t, null)) {
-                    U.putOrderedInt(this, QBASE, b + 1);
+                    base = b + 1;
                     return t;
                 }
             }
@@ -823,16 +949,15 @@
             while ((b = base) - top < 0 && (a = array) != null) {
                 int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
                 t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
-                if (t != null) {
-                    if (U.compareAndSwapObject(a, j, t, null)) {
-                        U.putOrderedInt(this, QBASE, b + 1);
-                        return t;
+                if (base == b) {
+                    if (t != null) {
+                        if (U.compareAndSwapObject(a, j, t, null)) {
+                            base = b + 1;
+                            return t;
+                        }
                     }
-                }
-                else if (base == b) {
-                    if (b + 1 == top)
+                    else if (b + 1 == top) // now empty
                         break;
-                    Thread.yield(); // wait for lagging update (very rare)
                 }
             }
             return null;
@@ -842,7 +967,7 @@
          * Takes next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> nextLocalTask() {
-            return mode == 0 ? pop() : poll();
+            return (config & FIFO_QUEUE) == 0 ? pop() : poll();
         }
 
         /**
@@ -852,7 +977,7 @@
             ForkJoinTask<?>[] a = array; int m;
             if (a == null || (m = a.length - 1) < 0)
                 return null;
-            int i = mode == 0 ? top - 1 : base;
+            int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base;
             int j = ((i & m) << ASHIFT) + ABASE;
             return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
         }
@@ -860,13 +985,13 @@
         /**
          * Pops the given task only if it is at the current top.
          * (A shared version is available only via FJP.tryExternalUnpush)
-         */
+        */
         final boolean tryUnpush(ForkJoinTask<?> t) {
             ForkJoinTask<?>[] a; int s;
             if ((a = array) != null && (s = top) != base &&
                 U.compareAndSwapObject
                 (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
-                top = s;
+                U.putOrderedInt(this, QTOP, s);
                 return true;
             }
             return false;
@@ -876,9 +1001,16 @@
          * Removes and cancels all known tasks, ignoring any exceptions.
          */
         final void cancelAll() {
-            ForkJoinTask.cancelIgnoringExceptions(currentJoin);
-            ForkJoinTask.cancelIgnoringExceptions(currentSteal);
-            for (ForkJoinTask<?> t; (t = poll()) != null; )
+            ForkJoinTask<?> t;
+            if ((t = currentJoin) != null) {
+                currentJoin = null;
+                ForkJoinTask.cancelIgnoringExceptions(t);
+            }
+            if ((t = currentSteal) != null) {
+                currentSteal = null;
+                ForkJoinTask.cancelIgnoringExceptions(t);
+            }
+            while ((t = poll()) != null)
                 ForkJoinTask.cancelIgnoringExceptions(t);
         }
 
@@ -893,167 +1025,186 @@
         }
 
         /**
-         * Executes a top-level task and any local tasks remaining
-         * after execution.
+         * Removes and executes all local tasks. If LIFO, invokes
+         * pollAndExecAll. Otherwise implements a specialized pop loop
+         * to exec until empty.
+         */
+        final void execLocalTasks() {
+            int b = base, m, s;
+            ForkJoinTask<?>[] a = array;
+            if (b - (s = top - 1) <= 0 && a != null &&
+                (m = a.length - 1) >= 0) {
+                if ((config & FIFO_QUEUE) == 0) {
+                    for (ForkJoinTask<?> t;;) {
+                        if ((t = (ForkJoinTask<?>)U.getAndSetObject
+                             (a, ((m & s) << ASHIFT) + ABASE, null)) == null)
+                            break;
+                        U.putOrderedInt(this, QTOP, s);
+                        t.doExec();
+                        if (base - (s = top - 1) > 0)
+                            break;
+                    }
+                }
+                else
+                    pollAndExecAll();
+            }
+        }
+
+        /**
+         * Executes the given task and any remaining local tasks.
          */
         final void runTask(ForkJoinTask<?> task) {
-            if ((currentSteal = task) != null) {
-                ForkJoinWorkerThread thread;
-                task.doExec();
-                ForkJoinTask<?>[] a = array;
-                int md = mode;
-                ++nsteals;
-                currentSteal = null;
-                if (md != 0)
-                    pollAndExecAll();
-                else if (a != null) {
-                    int s, m = a.length - 1;
-                    ForkJoinTask<?> t;
-                    while ((s = top - 1) - base >= 0 &&
-                           (t = (ForkJoinTask<?>)U.getAndSetObject
-                            (a, ((m & s) << ASHIFT) + ABASE, null)) != null) {
-                        top = s;
-                        t.doExec();
-                    }
-                }
-                if ((thread = owner) != null) // no need to do in finally clause
+            if (task != null) {
+                scanState &= ~SCANNING; // mark as busy
+                (currentSteal = task).doExec();
+                U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC
+                execLocalTasks();
+                ForkJoinWorkerThread thread = owner;
+                if (++nsteals < 0)      // collect on overflow
+                    transferStealCount(pool);
+                scanState |= SCANNING;
+                if (thread != null)
                     thread.afterTopLevelExec();
             }
         }
 
         /**
+         * Adds steal count to pool stealCounter if it exists, and resets.
+         */
+        final void transferStealCount(ForkJoinPool p) {
+            AtomicLong sc;
+            if (p != null && (sc = p.stealCounter) != null) {
+                int s = nsteals;
+                nsteals = 0;            // if negative, correct for overflow
+                sc.getAndAdd((long)(s < 0 ? Integer.MAX_VALUE : s));
+            }
+        }
+
+        /**
          * If present, removes from queue and executes the given task,
-         * or any other cancelled task. Returns (true) on any CAS
-         * or consistency check failure so caller can retry.
+         * or any other cancelled task. Used only by awaitJoin.
          *
-         * @return false if no progress can be made, else true
+         * @return true if queue empty and task not known to be done
          */
         final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
-            boolean stat;
             ForkJoinTask<?>[] a; int m, s, b, n;
-            if (task != null && (a = array) != null && (m = a.length - 1) >= 0 &&
-                (n = (s = top) - (b = base)) > 0) {
-                boolean removed = false, empty = true;
-                stat = true;
-                for (ForkJoinTask<?> t;;) {           // traverse from s to b
-                    long j = ((--s & m) << ASHIFT) + ABASE;
-                    t = (ForkJoinTask<?>)U.getObject(a, j);
-                    if (t == null)                    // inconsistent length
-                        break;
-                    else if (t == task) {
-                        if (s + 1 == top) {           // pop
-                            if (!U.compareAndSwapObject(a, j, task, null))
-                                break;
-                            top = s;
-                            removed = true;
+            if ((a = array) != null && (m = a.length - 1) >= 0 &&
+                task != null) {
+                while ((n = (s = top) - (b = base)) > 0) {
+                    for (ForkJoinTask<?> t;;) {      // traverse from s to b
+                        long j = ((--s & m) << ASHIFT) + ABASE;
+                        if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
+                            return s + 1 == top;     // shorter than expected
+                        else if (t == task) {
+                            boolean removed = false;
+                            if (s + 1 == top) {      // pop
+                                if (U.compareAndSwapObject(a, j, task, null)) {
+                                    U.putOrderedInt(this, QTOP, s);
+                                    removed = true;
+                                }
+                            }
+                            else if (base == b)      // replace with proxy
+                                removed = U.compareAndSwapObject(
+                                    a, j, task, new EmptyTask());
+                            if (removed)
+                                task.doExec();
+                            break;
                         }
-                        else if (base == b)           // replace with proxy
-                            removed = U.compareAndSwapObject(a, j, task,
-                                                             new EmptyTask());
-                        break;
-                    }
-                    else if (t.status >= 0)
-                        empty = false;
-                    else if (s + 1 == top) {          // pop and throw away
-                        if (U.compareAndSwapObject(a, j, t, null))
-                            top = s;
-                        break;
+                        else if (t.status < 0 && s + 1 == top) {
+                            if (U.compareAndSwapObject(a, j, t, null))
+                                U.putOrderedInt(this, QTOP, s);
+                            break;                  // was cancelled
+                        }
+                        if (--n == 0)
+                            return false;
                     }
-                    if (--n == 0) {
-                        if (!empty && base == b)
-                            stat = false;
-                        break;
-                    }
+                    if (task.status < 0)
+                        return false;
                 }
-                if (removed)
-                    task.doExec();
             }
-            else
-                stat = false;
-            return stat;
+            return true;
         }
 
         /**
-         * Tries to poll for and execute the given task or any other
-         * task in its CountedCompleter computation.
+         * Pops task if in the same CC computation as the given task,
+         * in either shared or owned mode. Used only by helpComplete.
          */
-        final boolean pollAndExecCC(CountedCompleter<?> root) {
-            ForkJoinTask<?>[] a; int b; Object o; CountedCompleter<?> t, r;
-            if ((b = base) - top < 0 && (a = array) != null) {
-                long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                if ((o = U.getObjectVolatile(a, j)) == null)
-                    return true; // retry
-                if (o instanceof CountedCompleter) {
-                    for (t = (CountedCompleter<?>)o, r = t;;) {
-                        if (r == root) {
-                            if (base == b &&
-                                U.compareAndSwapObject(a, j, t, null)) {
-                                U.putOrderedInt(this, QBASE, b + 1);
-                                t.doExec();
-                            }
-                            return true;
-                        }
-                        else if ((r = r.completer) == null)
-                            break; // not part of root computation
-                    }
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Tries to pop and execute the given task or any other task
-         * in its CountedCompleter computation.
-         */
-        final boolean externalPopAndExecCC(CountedCompleter<?> root) {
-            ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
+        final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
+            int s; ForkJoinTask<?>[] a; Object o;
             if (base - (s = top) < 0 && (a = array) != null) {
                 long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
-                if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
-                    for (t = (CountedCompleter<?>)o, r = t;;) {
-                        if (r == root) {
-                            if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                                if (top == s && array == a &&
-                                    U.compareAndSwapObject(a, j, t, null)) {
-                                    top = s - 1;
-                                    qlock = 0;
-                                    t.doExec();
+                if ((o = U.getObjectVolatile(a, j)) != null &&
+                    (o instanceof CountedCompleter)) {
+                    CountedCompleter<?> t = (CountedCompleter<?>)o;
+                    for (CountedCompleter<?> r = t;;) {
+                        if (r == task) {
+                            if (mode < 0) { // must lock
+                                if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+                                    if (top == s && array == a &&
+                                        U.compareAndSwapObject(a, j, t, null)) {
+                                        U.putOrderedInt(this, QTOP, s - 1);
+                                        U.putOrderedInt(this, QLOCK, 0);
+                                        return t;
+                                    }
+                                    U.compareAndSwapInt(this, QLOCK, 1, 0);
                                 }
-                                else
-                                    qlock = 0;
                             }
-                            return true;
+                            else if (U.compareAndSwapObject(a, j, t, null)) {
+                                U.putOrderedInt(this, QTOP, s - 1);
+                                return t;
+                            }
+                            break;
                         }
-                        else if ((r = r.completer) == null)
+                        else if ((r = r.completer) == null) // try parent
                             break;
                     }
                 }
             }
-            return false;
+            return null;
         }
 
         /**
-         * Internal version
+         * Steals and runs a task in the same CC computation as the
+         * given task if one exists and can be taken without
+         * contention. Otherwise returns a checksum/control value for
+         * use by method helpComplete.
+         *
+         * @return 1 if successful, 2 if retryable (lost to another
+         * stealer), -1 if non-empty but no matching task found, else
+         * the base index, forced negative.
          */
-        final boolean internalPopAndExecCC(CountedCompleter<?> root) {
-            ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
-            if (base - (s = top) < 0 && (a = array) != null) {
-                long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
-                if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
-                    for (t = (CountedCompleter<?>)o, r = t;;) {
-                        if (r == root) {
-                            if (U.compareAndSwapObject(a, j, t, null)) {
-                                top = s - 1;
+        final int pollAndExecCC(CountedCompleter<?> task) {
+            int b, h; ForkJoinTask<?>[] a; Object o;
+            if ((b = base) - top >= 0 || (a = array) == null)
+                h = b | Integer.MIN_VALUE;  // to sense movement on re-poll
+            else {
+                long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                if ((o = U.getObjectVolatile(a, j)) == null)
+                    h = 2;                  // retryable
+                else if (!(o instanceof CountedCompleter))
+                    h = -1;                 // unmatchable
+                else {
+                    CountedCompleter<?> t = (CountedCompleter<?>)o;
+                    for (CountedCompleter<?> r = t;;) {
+                        if (r == task) {
+                            if (base == b &&
+                                U.compareAndSwapObject(a, j, t, null)) {
+                                base = b + 1;
                                 t.doExec();
+                                h = 1;      // success
                             }
-                            return true;
+                            else
+                                h = 2;      // lost CAS
+                            break;
                         }
-                        else if ((r = r.completer) == null)
+                        else if ((r = r.completer) == null) {
+                            h = -1;         // unmatched
                             break;
+                        }
                     }
                 }
             }
-            return false;
+            return h;
         }
 
         /**
@@ -1061,28 +1212,31 @@
          */
         final boolean isApparentlyUnblocked() {
             Thread wt; Thread.State s;
-            return (eventCount >= 0 &&
+            return (scanState >= 0 &&
                     (wt = owner) != null &&
                     (s = wt.getState()) != Thread.State.BLOCKED &&
                     s != Thread.State.WAITING &&
                     s != Thread.State.TIMED_WAITING);
         }
 
-        // Unsafe mechanics
+        // Unsafe mechanics. Note that some are (and must be) the same as in FJP
         private static final sun.misc.Unsafe U;
-        private static final long QBASE;
+        private static final int  ABASE;
+        private static final int  ASHIFT;
+        private static final long QTOP;
         private static final long QLOCK;
-        private static final int ABASE;
-        private static final int ASHIFT;
+        private static final long QCURRENTSTEAL;
         static {
             try {
                 U = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = WorkQueue.class;
+                Class<?> wk = WorkQueue.class;
                 Class<?> ak = ForkJoinTask[].class;
-                QBASE = U.objectFieldOffset
-                    (k.getDeclaredField("base"));
+                QTOP = U.objectFieldOffset
+                    (wk.getDeclaredField("top"));
                 QLOCK = U.objectFieldOffset
-                    (k.getDeclaredField("qlock"));
+                    (wk.getDeclaredField("qlock"));
+                QCURRENTSTEAL = U.objectFieldOffset
+                    (wk.getDeclaredField("currentSteal"));
                 ABASE = U.arrayBaseOffset(ak);
                 int scale = U.arrayIndexScale(ak);
                 if ((scale & (scale - 1)) != 0)
@@ -1126,6 +1280,11 @@
     static final int commonParallelism;
 
     /**
+     * Limit on spare thread construction in tryCompensate.
+     */
+    private static int commonMaxSpares;
+
+    /**
      * Sequence number for creating workerNamePrefix.
      */
     private static int poolNumberSequence;
@@ -1138,7 +1297,7 @@
         return ++poolNumberSequence;
     }
 
-    // static constants
+    // static configuration constants
 
     /**
      * Initial timeout value (in nanoseconds) for the thread
@@ -1148,27 +1307,34 @@
      * aggressive shrinkage during most transient stalls (long GCs
      * etc).
      */
-    private static final long IDLE_TIMEOUT      = 2000L * 1000L * 1000L; // 2sec
-
-    /**
-     * Timeout value when there are more threads than parallelism level
-     */
-    private static final long FAST_IDLE_TIMEOUT =  200L * 1000L * 1000L;
+    private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec
 
     /**
      * Tolerance for idle timeouts, to cope with timer undershoots
      */
-    private static final long TIMEOUT_SLOP = 2000000L;
+    private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L;  // 20ms
 
     /**
-     * The maximum stolen->joining link depth allowed in method
-     * tryHelpStealer.  Must be a power of two.  Depths for legitimate
-     * chains are unbounded, but we use a fixed constant to avoid
-     * (otherwise unchecked) cycles and to bound staleness of
-     * traversal parameters at the expense of sometimes blocking when
-     * we could be helping.
+     * The initial value for commonMaxSpares during static
+     * initialization unless overridden using System property
+     * "java.util.concurrent.ForkJoinPool.common.maximumSpares".  The
+     * default value is far in excess of normal requirements, but also
+     * far short of MAX_CAP and typical OS thread limits, so allows
+     * JVMs to catch misuse/abuse before running out of resources
+     * needed to do so.
      */
-    private static final int MAX_HELP = 64;
+    private static final int DEFAULT_COMMON_MAX_SPARES = 256;
+
+    /**
+     * Number of times to spin-wait before blocking. The spins (in
+     * awaitRunStateLock and awaitWork) currently use randomized
+     * spins. If/when MWAIT-like intrinsics becomes available, they
+     * may allow quieter spinning. The value of SPINS must be a power
+     * of two, at least 4. The current value causes spinning for a
+     * small fraction of typical context-switch times, well worthwhile
+     * given the typical likelihoods that blocking is not necessary.
+     */
+    private static final int SPINS  = 1 << 11;
 
     /**
      * Increment for seed generators. See class ThreadLocal for
@@ -1177,209 +1343,212 @@
     private static final int SEED_INCREMENT = 0x9e3779b9;
 
     /*
-     * Bits and masks for control variables
-     *
-     * Field ctl is a long packed with:
-     * AC: Number of active running workers minus target parallelism (16 bits)
-     * TC: Number of total workers minus target parallelism (16 bits)
-     * ST: true if pool is terminating (1 bit)
-     * EC: the wait count of top waiting thread (15 bits)
-     * ID: poolIndex of top of Treiber stack of waiters (16 bits)
+     * Bits and masks for field ctl, packed with 4 16 bit subfields:
+     * AC: Number of active running workers minus target parallelism
+     * TC: Number of total workers minus target parallelism
+     * SS: version count and status of top waiting thread
+     * ID: poolIndex of top of Treiber stack of waiters
      *
-     * When convenient, we can extract the upper 32 bits of counts and
-     * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
-     * (int)ctl.  The ec field is never accessed alone, but always
-     * together with id and st. The offsets of counts by the target
-     * parallelism and the positionings of fields makes it possible to
-     * perform the most common checks via sign tests of fields: When
-     * ac is negative, there are not enough active workers, when tc is
-     * negative, there are not enough total workers, and when e is
-     * negative, the pool is terminating.  To deal with these possibly
-     * negative fields, we use casts in and out of "short" and/or
-     * signed shifts to maintain signedness.
+     * When convenient, we can extract the lower 32 stack top bits
+     * (including version bits) as sp=(int)ctl.  The offsets of counts
+     * by the target parallelism and the positionings of fields makes
+     * it possible to perform the most common checks via sign tests of
+     * fields: When ac is negative, there are not enough active
+     * workers, when tc is negative, there are not enough total
+     * workers.  When sp is non-zero, there are waiting workers.  To
+     * deal with possibly negative fields, we use casts in and out of
+     * "short" and/or signed shifts to maintain signedness.
      *
-     * When a thread is queued (inactivated), its eventCount field is
-     * set negative, which is the only way to tell if a worker is
-     * prevented from executing tasks, even though it must continue to
-     * scan for them to avoid queuing races. Note however that
-     * eventCount updates lag releases so usage requires care.
-     *
-     * Field plock is an int packed with:
-     * SHUTDOWN: true if shutdown is enabled (1 bit)
-     * SEQ:  a sequence lock, with PL_LOCK bit set if locked (30 bits)
-     * SIGNAL: set when threads may be waiting on the lock (1 bit)
-     *
-     * The sequence number enables simple consistency checks:
-     * Staleness of read-only operations on the workQueues array can
-     * be checked by comparing plock before vs after the reads.
+     * Because it occupies uppermost bits, we can add one active count
+     * using getAndAddLong of AC_UNIT, rather than CAS, when returning
+     * from a blocked join.  Other updates entail multiple subfields
+     * and masking, requiring CAS.
      */
 
-    // bit positions/shifts for fields
-    private static final int  AC_SHIFT   = 48;
-    private static final int  TC_SHIFT   = 32;
-    private static final int  ST_SHIFT   = 31;
-    private static final int  EC_SHIFT   = 16;
+    // Lower and upper word masks
+    private static final long SP_MASK    = 0xffffffffL;
+    private static final long UC_MASK    = ~SP_MASK;
 
-    // bounds
-    private static final int  SMASK      = 0xffff;  // short bits
-    private static final int  MAX_CAP    = 0x7fff;  // max #workers - 1
-    private static final int  EVENMASK   = 0xfffe;  // even short bits
-    private static final int  SQMASK     = 0x007e;  // max 64 (even) slots
-    private static final int  SHORT_SIGN = 1 << 15;
-    private static final int  INT_SIGN   = 1 << 31;
-
-    // masks
-    private static final long STOP_BIT   = 0x0001L << ST_SHIFT;
-    private static final long AC_MASK    = ((long)SMASK) << AC_SHIFT;
-    private static final long TC_MASK    = ((long)SMASK) << TC_SHIFT;
-
-    // units for incrementing and decrementing
-    private static final long TC_UNIT    = 1L << TC_SHIFT;
-    private static final long AC_UNIT    = 1L << AC_SHIFT;
+    // Active counts
+    private static final int  AC_SHIFT   = 48;
+    private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
+    private static final long AC_MASK    = 0xffffL << AC_SHIFT;
 
-    // masks and units for dealing with u = (int)(ctl >>> 32)
-    private static final int  UAC_SHIFT  = AC_SHIFT - 32;
-    private static final int  UTC_SHIFT  = TC_SHIFT - 32;
-    private static final int  UAC_MASK   = SMASK << UAC_SHIFT;
-    private static final int  UTC_MASK   = SMASK << UTC_SHIFT;
-    private static final int  UAC_UNIT   = 1 << UAC_SHIFT;
-    private static final int  UTC_UNIT   = 1 << UTC_SHIFT;
+    // Total counts
+    private static final int  TC_SHIFT   = 32;
+    private static final long TC_UNIT    = 0x0001L << TC_SHIFT;
+    private static final long TC_MASK    = 0xffffL << TC_SHIFT;
+    private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
 
-    // masks and units for dealing with e = (int)ctl
-    private static final int E_MASK      = 0x7fffffff; // no STOP_BIT
-    private static final int E_SEQ       = 1 << EC_SHIFT;
-
-    // plock bits
-    private static final int SHUTDOWN    = 1 << 31;
-    private static final int PL_LOCK     = 2;
-    private static final int PL_SIGNAL   = 1;
-    private static final int PL_SPINS    = 1 << 8;
-
-    // access mode for WorkQueue
-    static final int LIFO_QUEUE          =  0;
-    static final int FIFO_QUEUE          =  1;
-    static final int SHARED_QUEUE        = -1;
+    // runState bits: SHUTDOWN must be negative, others arbitrary powers of two
+    private static final int  RSLOCK     = 1;
+    private static final int  RSIGNAL    = 1 << 1;
+    private static final int  STARTED    = 1 << 2;
+    private static final int  STOP       = 1 << 29;
+    private static final int  TERMINATED = 1 << 30;
+    private static final int  SHUTDOWN   = 1 << 31;
 
     // Instance fields
-    volatile long stealCount;                  // collects worker counts
-    volatile long ctl;                         // main pool control
-    volatile int plock;                        // shutdown status and seqLock
-    volatile int indexSeed;                    // worker/submitter index seed
-    final short parallelism;                   // parallelism level
-    final short mode;                          // LIFO/FIFO
-    WorkQueue[] workQueues;                    // main registry
+    volatile long ctl;                   // main pool control
+    volatile int runState;               // lockable status
+    final int config;                    // parallelism, mode
+    int indexSeed;                       // to generate worker index
+    volatile WorkQueue[] workQueues;     // main registry
     final ForkJoinWorkerThreadFactory factory;
-    final UncaughtExceptionHandler ueh;        // per-worker UEH
-    final String workerNamePrefix;             // to create worker name string
+    final UncaughtExceptionHandler ueh;  // per-worker UEH
+    final String workerNamePrefix;       // to create worker name string
+    volatile AtomicLong stealCounter;    // also used as sync monitor
+
+    /**
+     * Acquires the runState lock; returns current (locked) runState.
+     */
+    private int lockRunState() {
+        int rs;
+        return ((((rs = runState) & RSLOCK) != 0 ||
+                 !U.compareAndSwapInt(this, RUNSTATE, rs, rs |= RSLOCK)) ?
+                awaitRunStateLock() : rs);
+    }
 
     /**
-     * Acquires the plock lock to protect worker array and related
-     * updates. This method is called only if an initial CAS on plock
-     * fails. This acts as a spinlock for normal cases, but falls back
-     * to builtin monitor to block when (rarely) needed. This would be
-     * a terrible idea for a highly contended lock, but works fine as
-     * a more conservative alternative to a pure spinlock.
+     * Spins and/or blocks until runstate lock is available.  See
+     * above for explanation.
      */
-    private int acquirePlock() {
-        int spins = PL_SPINS, ps, nps;
-        for (;;) {
-            if (((ps = plock) & PL_LOCK) == 0 &&
-                U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK))
-                return nps;
-            else if (spins >= 0) {
-                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
+    private int awaitRunStateLock() {
+        Object lock;
+        boolean wasInterrupted = false;
+        for (int spins = SPINS, r = 0, rs, ns;;) {
+            if (((rs = runState) & RSLOCK) == 0) {
+                if (U.compareAndSwapInt(this, RUNSTATE, rs, ns = rs | RSLOCK)) {
+                    if (wasInterrupted) {
+                        try {
+                            Thread.currentThread().interrupt();
+                        } catch (SecurityException ignore) {
+                        }
+                    }
+                    return ns;
+                }
+            }
+            else if (r == 0)
+                r = ThreadLocalRandom.nextSecondarySeed();
+            else if (spins > 0) {
+                r ^= r << 6; r ^= r >>> 21; r ^= r << 7; // xorshift
+                if (r >= 0)
                     --spins;
             }
-            else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) {
-                synchronized (this) {
-                    if ((plock & PL_SIGNAL) != 0) {
+            else if ((rs & STARTED) == 0 || (lock = stealCounter) == null)
+                Thread.yield();   // initialization race
+            else if (U.compareAndSwapInt(this, RUNSTATE, rs, rs | RSIGNAL)) {
+                synchronized (lock) {
+                    if ((runState & RSIGNAL) != 0) {
                         try {
-                            wait();
+                            lock.wait();
                         } catch (InterruptedException ie) {
-                            try {
-                                Thread.currentThread().interrupt();
-                            } catch (SecurityException ignore) {
-                            }
+                            if (!(Thread.currentThread() instanceof
+                                  ForkJoinWorkerThread))
+                                wasInterrupted = true;
                         }
                     }
                     else
-                        notifyAll();
+                        lock.notifyAll();
                 }
             }
         }
     }
 
     /**
-     * Unlocks and signals any thread waiting for plock. Called only
-     * when CAS of seq value for unlock fails.
+     * Unlocks and sets runState to newRunState.
+     *
+     * @param oldRunState a value returned from lockRunState
+     * @param newRunState the next value (must have lock bit clear).
      */
-    private void releasePlock(int ps) {
-        plock = ps;
-        synchronized (this) { notifyAll(); }
+    private void unlockRunState(int oldRunState, int newRunState) {
+        if (!U.compareAndSwapInt(this, RUNSTATE, oldRunState, newRunState)) {
+            Object lock = stealCounter;
+            runState = newRunState;              // clears RSIGNAL bit
+            if (lock != null)
+                synchronized (lock) { lock.notifyAll(); }
+        }
+    }
+
+    // Creating, registering and deregistering workers
+
+    /**
+     * Tries to construct and start one worker. Assumes that total
+     * count has already been incremented as a reservation.  Invokes
+     * deregisterWorker on any failure.
+     *
+     * @return true if successful
+     */
+    private boolean createWorker() {
+        ForkJoinWorkerThreadFactory fac = factory;
+        Throwable ex = null;
+        ForkJoinWorkerThread wt = null;
+        try {
+            if (fac != null && (wt = fac.newThread(this)) != null) {
+                wt.start();
+                return true;
+            }
+        } catch (Throwable rex) {
+            ex = rex;
+        }
+        deregisterWorker(wt, ex);
+        return false;
     }
 
     /**
-     * Tries to create and start one worker if fewer than target
-     * parallelism level exist. Adjusts counts etc on failure.
+     * Tries to add one worker, incrementing ctl counts before doing
+     * so, relying on createWorker to back out on failure.
+     *
+     * @param c incoming ctl value, with total count negative and no
+     * idle workers.  On CAS failure, c is refreshed and retried if
+     * this holds (otherwise, a new worker is not needed).
      */
-    private void tryAddWorker() {
-        long c; int u, e;
-        while ((u = (int)((c = ctl) >>> 32)) < 0 &&
-               (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) {
-            long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) |
-                              ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e;
-            if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                ForkJoinWorkerThreadFactory fac;
-                Throwable ex = null;
-                ForkJoinWorkerThread wt = null;
-                try {
-                    if ((fac = factory) != null &&
-                        (wt = fac.newThread(this)) != null) {
-                        wt.start();
-                        break;
-                    }
-                } catch (Throwable rex) {
-                    ex = rex;
+    private void tryAddWorker(long c) {
+        boolean add = false;
+        do {
+            long nc = ((AC_MASK & (c + AC_UNIT)) |
+                       (TC_MASK & (c + TC_UNIT)));
+            if (ctl == c) {
+                int rs, stop;                 // check if terminating
+                if ((stop = (rs = lockRunState()) & STOP) == 0)
+                    add = U.compareAndSwapLong(this, CTL, c, nc);
+                unlockRunState(rs, rs & ~RSLOCK);
+                if (stop != 0)
+                    break;
+                if (add) {
+                    createWorker();
+                    break;
                 }
-                deregisterWorker(wt, ex);
-                break;
             }
-        }
+        } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
     }
 
-    //  Registering and deregistering workers
-
     /**
-     * Callback from ForkJoinWorkerThread to establish and record its
-     * WorkQueue. To avoid scanning bias due to packing entries in
-     * front of the workQueues array, we treat the array as a simple
-     * power-of-two hash table using per-thread seed as hash,
-     * expanding as needed.
+     * Callback from ForkJoinWorkerThread constructor to establish and
+     * record its WorkQueue.
      *
      * @param wt the worker thread
      * @return the worker's queue
      */
     final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
-        UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps;
-        wt.setDaemon(true);
+        UncaughtExceptionHandler handler;
+        wt.setDaemon(true);                           // configure thread
         if ((handler = ueh) != null)
             wt.setUncaughtExceptionHandler(handler);
-        do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed,
-                                          s += SEED_INCREMENT) ||
-                     s == 0); // skip 0
-        WorkQueue w = new WorkQueue(this, wt, mode, s);
-        if (((ps = plock) & PL_LOCK) != 0 ||
-            !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
-            ps = acquirePlock();
-        int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+        WorkQueue w = new WorkQueue(this, wt);
+        int i = 0;                                    // assign a pool index
+        int mode = config & MODE_MASK;
+        int rs = lockRunState();
         try {
-            if ((ws = workQueues) != null) {    // skip if shutting down
-                int n = ws.length, m = n - 1;
-                int r = (s << 1) | 1;           // use odd-numbered indices
-                if (ws[r &= m] != null) {       // collision
-                    int probes = 0;             // step by approx half size
+            WorkQueue[] ws; int n;                    // skip if no array
+            if ((ws = workQueues) != null && (n = ws.length) > 0) {
+                int s = indexSeed += SEED_INCREMENT;  // unlikely to collide
+                int m = n - 1;
+                i = ((s << 1) | 1) & m;               // odd-numbered indices
+                if (ws[i] != null) {                  // collision
+                    int probes = 0;                   // step by approx half n
                     int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
-                    while (ws[r = (r + step) & m] != null) {
+                    while (ws[i = (i + step) & m] != null) {
                         if (++probes >= n) {
                             workQueues = ws = Arrays.copyOf(ws, n <<= 1);
                             m = n - 1;
@@ -1387,15 +1556,15 @@
                         }
                     }
                 }
-                w.poolIndex = (short)r;
-                w.eventCount = r; // volatile write orders
-                ws[r] = w;
+                w.hint = s;                           // use as random seed
+                w.config = i | mode;
+                w.scanState = i;                      // publication fence
+                ws[i] = w;
             }
         } finally {
-            if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
-                releasePlock(nps);
+            unlockRunState(rs, rs & ~RSLOCK);
         }
-        wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1)));
+        wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
         return w;
     }
 
@@ -1411,384 +1580,322 @@
     final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
         WorkQueue w = null;
         if (wt != null && (w = wt.workQueue) != null) {
-            int ps;
-            w.qlock = -1;                // ensure set
-            U.getAndAddLong(this, STEALCOUNT, w.nsteals); // collect steals
-            if (((ps = plock) & PL_LOCK) != 0 ||
-                !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
-                ps = acquirePlock();
-            int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
-            try {
-                int idx = w.poolIndex;
-                WorkQueue[] ws = workQueues;
-                if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w)
-                    ws[idx] = null;
-            } finally {
-                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
-                    releasePlock(nps);
-            }
+            WorkQueue[] ws;                           // remove index from array
+            int idx = w.config & SMASK;
+            int rs = lockRunState();
+            if ((ws = workQueues) != null && ws.length > idx && ws[idx] == w)
+                ws[idx] = null;
+            unlockRunState(rs, rs & ~RSLOCK);
         }
-
-        long c;                          // adjust ctl counts
+        long c;                                       // decrement counts
         do {} while (!U.compareAndSwapLong
-                     (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) |
-                                           ((c - TC_UNIT) & TC_MASK) |
-                                           (c & ~(AC_MASK|TC_MASK)))));
-
-        if (!tryTerminate(false, false) && w != null && w.array != null) {
-            w.cancelAll();               // cancel remaining tasks
-            WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e;
-            while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) {
-                if (e > 0) {             // activate or create replacement
-                    if ((ws = workQueues) == null ||
-                        (i = e & SMASK) >= ws.length ||
-                        (v = ws[i]) == null)
-                        break;
-                    long nc = (((long)(v.nextWait & E_MASK)) |
-                               ((long)(u + UAC_UNIT) << 32));
-                    if (v.eventCount != (e | INT_SIGN))
-                        break;
-                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                        v.eventCount = (e + E_SEQ) & E_MASK;
-                        if ((p = v.parker) != null)
-                            U.unpark(p);
-                        break;
-                    }
-                }
-                else {
-                    if ((short)u < 0)
-                        tryAddWorker();
+                     (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
+                                           (TC_MASK & (c - TC_UNIT)) |
+                                           (SP_MASK & c))));
+        if (w != null) {
+            w.qlock = -1;                             // ensure set
+            w.transferStealCount(this);
+            w.cancelAll();                            // cancel remaining tasks
+        }
+        for (;;) {                                    // possibly replace
+            WorkQueue[] ws; int m, sp;
+            if (tryTerminate(false, false) || w == null || w.array == null ||
+                (runState & STOP) != 0 || (ws = workQueues) == null ||
+                (m = ws.length - 1) < 0)              // already terminating
+                break;
+            if ((sp = (int)(c = ctl)) != 0) {         // wake up replacement
+                if (tryRelease(c, ws[sp & m], AC_UNIT))
                     break;
-                }
             }
+            else if (ex != null && (c & ADD_WORKER) != 0L) {
+                tryAddWorker(c);                      // create replacement
+                break;
+            }
+            else                                      // don't need replacement
+                break;
         }
-        if (ex == null)                     // help clean refs on way out
+        if (ex == null)                               // help clean on way out
             ForkJoinTask.helpExpungeStaleExceptions();
-        else                                // rethrow
+        else                                          // rethrow
             ForkJoinTask.rethrow(ex);
     }
 
-    // Submissions
-
-    /**
-     * Unless shutting down, adds the given task to a submission queue
-     * at submitter's current queue index (modulo submission
-     * range). Only the most common path is directly handled in this
-     * method. All others are relayed to fullExternalPush.
-     *
-     * @param task the task. Caller must ensure non-null.
-     */
-    final void externalPush(ForkJoinTask<?> task) {
-        WorkQueue q; int m, s, n, am; ForkJoinTask<?>[] a;
-        int r = ThreadLocalRandom.getProbe();
-        int ps = plock;
-        WorkQueue[] ws = workQueues;
-        if (ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 &&
-            (q = ws[m & r & SQMASK]) != null && r != 0 &&
-            U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
-            if ((a = q.array) != null &&
-                (am = a.length - 1) > (n = (s = q.top) - q.base)) {
-                int j = ((am & s) << ASHIFT) + ABASE;
-                U.putOrderedObject(a, j, task);
-                q.top = s + 1;                     // push on to deque
-                q.qlock = 0;
-                if (n <= 1)
-                    signalWork(ws, q);
-                return;
-            }
-            q.qlock = 0;
-        }
-        fullExternalPush(task);
-    }
-
-    /**
-     * Full version of externalPush. This method is called, among
-     * other times, upon the first submission of the first task to the
-     * pool, so must perform secondary initialization.  It also
-     * detects first submission by an external thread by looking up
-     * its ThreadLocal, and creates a new shared queue if the one at
-     * index if empty or contended. The plock lock body must be
-     * exception-free (so no try/finally) so we optimistically
-     * allocate new queues outside the lock and throw them away if
-     * (very rarely) not needed.
-     *
-     * Secondary initialization occurs when plock is zero, to create
-     * workQueue array and set plock to a valid value.  This lock body
-     * must also be exception-free. Because the plock seq value can
-     * eventually wrap around zero, this method harmlessly fails to
-     * reinitialize if workQueues exists, while still advancing plock.
-     */
-    private void fullExternalPush(ForkJoinTask<?> task) {
-        int r;
-        if ((r = ThreadLocalRandom.getProbe()) == 0) {
-            ThreadLocalRandom.localInit();
-            r = ThreadLocalRandom.getProbe();
-        }
-        for (;;) {
-            WorkQueue[] ws; WorkQueue q; int ps, m, k;
-            boolean move = false;
-            if ((ps = plock) < 0)
-                throw new RejectedExecutionException();
-            else if (ps == 0 || (ws = workQueues) == null ||
-                     (m = ws.length - 1) < 0) { // initialize workQueues
-                int p = parallelism;            // find power of two table size
-                int n = (p > 1) ? p - 1 : 1;    // ensure at least 2 slots
-                n |= n >>> 1; n |= n >>> 2;  n |= n >>> 4;
-                n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
-                WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ?
-                                   new WorkQueue[n] : null);
-                if (((ps = plock) & PL_LOCK) != 0 ||
-                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
-                    ps = acquirePlock();
-                if (((ws = workQueues) == null || ws.length == 0) && nws != null)
-                    workQueues = nws;
-                int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
-                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
-                    releasePlock(nps);
-            }
-            else if ((q = ws[k = r & m & SQMASK]) != null) {
-                if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
-                    ForkJoinTask<?>[] a = q.array;
-                    int s = q.top;
-                    boolean submitted = false;
-                    try {                      // locked version of push
-                        if ((a != null && a.length > s + 1 - q.base) ||
-                            (a = q.growArray()) != null) {   // must presize
-                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
-                            U.putOrderedObject(a, j, task);
-                            q.top = s + 1;
-                            submitted = true;
-                        }
-                    } finally {
-                        q.qlock = 0;  // unlock
-                    }
-                    if (submitted) {
-                        signalWork(ws, q);
-                        return;
-                    }
-                }
-                move = true; // move on failure
-            }
-            else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
-                q = new WorkQueue(this, null, SHARED_QUEUE, r);
-                q.poolIndex = (short)k;
-                if (((ps = plock) & PL_LOCK) != 0 ||
-                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
-                    ps = acquirePlock();
-                if ((ws = workQueues) != null && k < ws.length && ws[k] == null)
-                    ws[k] = q;
-                int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
-                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
-                    releasePlock(nps);
-            }
-            else
-                move = true; // move if busy
-            if (move)
-                r = ThreadLocalRandom.advanceProbe(r);
-        }
-    }
-
-    // Maintaining ctl counts
-
-    /**
-     * Increments active count; mainly called upon return from blocking.
-     */
-    final void incrementActiveCount() {
-        long c;
-        do {} while (!U.compareAndSwapLong
-                     (this, CTL, c = ctl, ((c & ~AC_MASK) |
-                                           ((c & AC_MASK) + AC_UNIT))));
-    }
+    // Signalling
 
     /**
      * Tries to create or activate a worker if too few are active.
      *
      * @param ws the worker array to use to find signallees
-     * @param q if non-null, the queue holding tasks to be processed
+     * @param q a WorkQueue --if non-null, don't retry if now empty
      */
     final void signalWork(WorkQueue[] ws, WorkQueue q) {
-        for (;;) {
-            long c; int e, u, i; WorkQueue w; Thread p;
-            if ((u = (int)((c = ctl) >>> 32)) >= 0)
-                break;
-            if ((e = (int)c) <= 0) {
-                if ((short)u < 0)
-                    tryAddWorker();
+        long c; int sp, i; WorkQueue v; Thread p;
+        while ((c = ctl) < 0L) {                       // too few active
+            if ((sp = (int)c) == 0) {                  // no idle workers
+                if ((c & ADD_WORKER) != 0L)            // too few workers
+                    tryAddWorker(c);
                 break;
             }
-            if (ws == null || ws.length <= (i = e & SMASK) ||
-                (w = ws[i]) == null)
+            if (ws == null)                            // unstarted/terminated
+                break;
+            if (ws.length <= (i = sp & SMASK))         // terminated
+                break;
+            if ((v = ws[i]) == null)                   // terminating
                 break;
-            long nc = (((long)(w.nextWait & E_MASK)) |
-                       ((long)(u + UAC_UNIT)) << 32);
-            int ne = (e + E_SEQ) & E_MASK;
-            if (w.eventCount == (e | INT_SIGN) &&
-                U.compareAndSwapLong(this, CTL, c, nc)) {
-                w.eventCount = ne;
-                if ((p = w.parker) != null)
+            int vs = (sp + SS_SEQ) & ~INACTIVE;        // next scanState
+            int d = sp - v.scanState;                  // screen CAS
+            long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred);
+            if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) {
+                v.scanState = vs;                      // activate v
+                if ((p = v.parker) != null)
                     U.unpark(p);
                 break;
             }
-            if (q != null && q.base >= q.top)
+            if (q != null && q.base == q.top)          // no more work
                 break;
         }
     }
 
+    /**
+     * Signals and releases worker v if it is top of idle worker
+     * stack.  This performs a one-shot version of signalWork only if
+     * there is (apparently) at least one idle worker.
+     *
+     * @param c incoming ctl value
+     * @param v if non-null, a worker
+     * @param inc the increment to active count (zero when compensating)
+     * @return true if successful
+     */
+    private boolean tryRelease(long c, WorkQueue v, long inc) {
+        int sp = (int)c, vs = (sp + SS_SEQ) & ~INACTIVE; Thread p;
+        if (v != null && v.scanState == sp) {          // v is at top of stack
+            long nc = (UC_MASK & (c + inc)) | (SP_MASK & v.stackPred);
+            if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                v.scanState = vs;
+                if ((p = v.parker) != null)
+                    U.unpark(p);
+                return true;
+            }
+        }
+        return false;
+    }
+
     // Scanning for tasks
 
     /**
      * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
      */
     final void runWorker(WorkQueue w) {
-        w.growArray(); // allocate queue
-        for (int r = w.hint; scan(w, r) == 0; ) {
+        w.growArray();                   // allocate queue
+        int seed = w.hint;               // initially holds randomization hint
+        int r = (seed == 0) ? 1 : seed;  // avoid 0 for xorShift
+        for (ForkJoinTask<?> t;;) {
+            if ((t = scan(w, r)) != null)
+                w.runTask(t);
+            else if (!awaitWork(w, r))
+                break;
             r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
         }
     }
 
     /**
-     * Scans for and, if found, runs one task, else possibly
-     * inactivates the worker. This method operates on single reads of
-     * volatile state and is designed to be re-invoked continuously,
-     * in part because it returns upon detecting inconsistencies,
-     * contention, or state changes that indicate possible success on
-     * re-invocation.
-     *
-     * The scan searches for tasks across queues starting at a random
-     * index, checking each at least twice.  The scan terminates upon
-     * either finding a non-empty queue, or completing the sweep. If
-     * the worker is not inactivated, it takes and runs a task from
-     * this queue. Otherwise, if not activated, it tries to activate
-     * itself or some other worker by signalling. On failure to find a
-     * task, returns (for retry) if pool state may have changed during
-     * an empty scan, or tries to inactivate if active, else possibly
-     * blocks or terminates via method awaitWork.
+     * Scans for and tries to steal a top-level task. Scans start at a
+     * random location, randomly moving on apparent contention,
+     * otherwise continuing linearly until reaching two consecutive
+     * empty passes over all queues with the same checksum (summing
+     * each base index of each queue, that moves on each steal), at
+     * which point the worker tries to inactivate and then re-scans,
+     * attempting to re-activate (itself or some other worker) if
+     * finding a task; otherwise returning null to await work.  Scans
+     * otherwise touch as little memory as possible, to reduce
+     * disruption on other scanning threads.
      *
      * @param w the worker (via its WorkQueue)
      * @param r a random seed
-     * @return worker qlock status if would have waited, else 0
+     * @return a task, or null if none found
      */
-    private final int scan(WorkQueue w, int r) {
+    private ForkJoinTask<?> scan(WorkQueue w, int r) {
         WorkQueue[] ws; int m;
-        long c = ctl;                            // for consistency check
-        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) {
-            for (int j = m + m + 1, ec = w.eventCount;;) {
-                WorkQueue q; int b, e; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
-                if ((q = ws[(r - j) & m]) != null &&
-                    (b = q.base) - q.top < 0 && (a = q.array) != null) {
-                    long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                    if ((t = ((ForkJoinTask<?>)
-                              U.getObjectVolatile(a, i))) != null) {
-                        if (ec < 0)
-                            helpRelease(c, ws, w, q, b);
-                        else if (q.base == b &&
-                                 U.compareAndSwapObject(a, i, t, null)) {
-                            U.putOrderedInt(q, QBASE, b + 1);
-                            if ((b + 1) - q.top < 0)
-                                signalWork(ws, q);
-                            w.runTask(t);
+        if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) {
+            int ss = w.scanState;                     // initially non-negative
+            for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
+                WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
+                int b, n; long c;
+                if ((q = ws[k]) != null) {
+                    if ((n = (b = q.base) - q.top) < 0 &&
+                        (a = q.array) != null) {      // non-empty
+                        long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                        if ((t = ((ForkJoinTask<?>)
+                                  U.getObjectVolatile(a, i))) != null &&
+                            q.base == b) {
+                            if (ss >= 0) {
+                                if (U.compareAndSwapObject(a, i, t, null)) {
+                                    q.base = b + 1;
+                                    if (n < -1)       // signal others
+                                        signalWork(ws, q);
+                                    return t;
+                                }
+                            }
+                            else if (oldSum == 0 &&   // try to activate
+                                     w.scanState < 0)
+                                tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
                         }
+                        if (ss < 0)                   // refresh
+                            ss = w.scanState;
+                        r ^= r << 1; r ^= r >>> 3; r ^= r << 10;
+                        origin = k = r & m;           // move and rescan
+                        oldSum = checkSum = 0;
+                        continue;
                     }
-                    break;
+                    checkSum += b;
                 }
-                else if (--j < 0) {
-                    if ((ec | (e = (int)c)) < 0) // inactive or terminating
-                        return awaitWork(w, c, ec);
-                    else if (ctl == c) {         // try to inactivate and enqueue
-                        long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
-                        w.nextWait = e;
-                        w.eventCount = ec | INT_SIGN;
-                        if (!U.compareAndSwapLong(this, CTL, c, nc))
-                            w.eventCount = ec;   // back out
+                if ((k = (k + 1) & m) == origin) {    // continue until stable
+                    if ((ss >= 0 || (ss == (ss = w.scanState))) &&
+                        oldSum == (oldSum = checkSum)) {
+                        if (ss < 0 || w.qlock < 0)    // already inactive
+                            break;
+                        int ns = ss | INACTIVE;       // try to inactivate
+                        long nc = ((SP_MASK & ns) |
+                                   (UC_MASK & ((c = ctl) - AC_UNIT)));
+                        w.stackPred = (int)c;         // hold prev stack top
+                        U.putInt(w, QSCANSTATE, ns);
+                        if (U.compareAndSwapLong(this, CTL, c, nc))
+                            ss = ns;
+                        else
+                            w.scanState = ss;         // back out
                     }
-                    break;
+                    checkSum = 0;
                 }
             }
         }
-        return 0;
+        return null;
     }
 
     /**
-     * A continuation of scan(), possibly blocking or terminating
-     * worker w. Returns without blocking if pool state has apparently
-     * changed since last invocation.  Also, if inactivating w has
-     * caused the pool to become quiescent, checks for pool
+     * Possibly blocks worker w waiting for a task to steal, or
+     * returns false if the worker should terminate.  If inactivating
+     * w has caused the pool to become quiescent, checks for pool
      * termination, and, so long as this is not the only worker, waits
-     * for event for up to a given duration.  On timeout, if ctl has
-     * not changed, terminates the worker, which will in turn wake up
+     * for up to a given duration.  On timeout, if ctl has not
+     * changed, terminates the worker, which will in turn wake up
      * another worker to possibly repeat this process.
      *
      * @param w the calling worker
-     * @param c the ctl value on entry to scan
-     * @param ec the worker's eventCount on entry to scan
+     * @param r a random seed (for spins)
+     * @return false if the worker should terminate
      */
-    private final int awaitWork(WorkQueue w, long c, int ec) {
-        int stat, ns; long parkTime, deadline;
-        if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c &&
-            !Thread.interrupted()) {
-            int e = (int)c;
-            int u = (int)(c >>> 32);
-            int d = (u >> UAC_SHIFT) + parallelism; // active count
-
-            if (e < 0 || (d <= 0 && tryTerminate(false, false)))
-                stat = w.qlock = -1;          // pool is terminating
-            else if ((ns = w.nsteals) != 0) { // collect steals and retry
-                w.nsteals = 0;
-                U.getAndAddLong(this, STEALCOUNT, (long)ns);
+    private boolean awaitWork(WorkQueue w, int r) {
+        if (w == null || w.qlock < 0)                 // w is terminating
+            return false;
+        for (int pred = w.stackPred, spins = SPINS, ss;;) {
+            if ((ss = w.scanState) >= 0)
+                break;
+            else if (spins > 0) {
+                r ^= r << 6; r ^= r >>> 21; r ^= r << 7;
+                if (r >= 0 && --spins == 0) {         // randomize spins
+                    WorkQueue v; WorkQueue[] ws; int s, j; AtomicLong sc;
+                    if (pred != 0 && (ws = workQueues) != null &&
+                        (j = pred & SMASK) < ws.length &&
+                        (v = ws[j]) != null &&        // see if pred parking
+                        (v.parker == null || v.scanState >= 0))
+                        spins = SPINS;                // continue spinning
+                }
             }
-            else {
-                long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L :
-                           ((long)(w.nextWait & E_MASK)) | // ctl to restore
-                           ((long)(u + UAC_UNIT)) << 32);
-                if (pc != 0L) {               // timed wait if last waiter
-                    int dc = -(short)(c >>> TC_SHIFT);
-                    parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT:
-                                (dc + 1) * IDLE_TIMEOUT);
+            else if (w.qlock < 0)                     // recheck after spins
+                return false;
+            else if (!Thread.interrupted()) {
+                long c, prevctl, parkTime, deadline;
+                int ac = (int)((c = ctl) >> AC_SHIFT) + (config & SMASK);
+                if ((ac <= 0 && tryTerminate(false, false)) ||
+                    (runState & STOP) != 0)           // pool terminating
+                    return false;
+                if (ac <= 0 && ss == (int)c) {        // is last waiter
+                    prevctl = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & pred);
+                    int t = (short)(c >>> TC_SHIFT);  // shrink excess spares
+                    if (t > 2 && U.compareAndSwapLong(this, CTL, c, prevctl))
+                        return false;                 // else use timed wait
+                    parkTime = IDLE_TIMEOUT * ((t >= 0) ? 1 : 1 - t);
                     deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
                 }
                 else
-                    parkTime = deadline = 0L;
-                if (w.eventCount == ec && ctl == c) {
-                    Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
-                    w.parker = wt;            // emulate LockSupport.park
-                    if (w.eventCount == ec && ctl == c)
-                        U.park(false, parkTime);  // must recheck before park
-                    w.parker = null;
-                    U.putObject(wt, PARKBLOCKER, null);
-                    if (parkTime != 0L && ctl == c &&
-                        deadline - System.nanoTime() <= 0L &&
-                        U.compareAndSwapLong(this, CTL, c, pc))
-                        stat = w.qlock = -1;  // shrink pool
+                    prevctl = parkTime = deadline = 0L;
+                Thread wt = Thread.currentThread();
+                U.putObject(wt, PARKBLOCKER, this);   // emulate LockSupport
+                w.parker = wt;
+                if (w.scanState < 0 && ctl == c)      // recheck before park
+                    U.park(false, parkTime);
+                U.putOrderedObject(w, QPARKER, null);
+                U.putObject(wt, PARKBLOCKER, null);
+                if (w.scanState >= 0)
+                    break;
+                if (parkTime != 0L && ctl == c &&
+                    deadline - System.nanoTime() <= 0L &&
+                    U.compareAndSwapLong(this, CTL, c, prevctl))
+                    return false;                     // shrink pool
+            }
+        }
+        return true;
+    }
+
+    // Joining tasks
+
+    /**
+     * Tries to steal and run tasks within the target's computation.
+     * Uses a variant of the top-level algorithm, restricted to tasks
+     * with the given task as ancestor: It prefers taking and running
+     * eligible tasks popped from the worker's own queue (via
+     * popCC). Otherwise it scans others, randomly moving on
+     * contention or execution, deciding to give up based on a
+     * checksum (via return codes frob pollAndExecCC). The maxTasks
+     * argument supports external usages; internal calls use zero,
+     * allowing unbounded steps (external calls trap non-positive
+     * values).
+     *
+     * @param w caller
+     * @param maxTasks if non-zero, the maximum number of other tasks to run
+     * @return task status on exit
+     */
+    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
+                           int maxTasks) {
+        WorkQueue[] ws; int s = 0, m;
+        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+            task != null && w != null) {
+            int mode = w.config;                 // for popCC
+            int r = w.hint ^ w.top;              // arbitrary seed for origin
+            int origin = r & m;                  // first queue to scan
+            int h = 1;                           // 1:ran, >1:contended, <0:hash
+            for (int k = origin, oldSum = 0, checkSum = 0;;) {
+                CountedCompleter<?> p; WorkQueue q;
+                if ((s = task.status) < 0)
+                    break;
+                if (h == 1 && (p = w.popCC(task, mode)) != null) {
+                    p.doExec();                  // run local task
+                    if (maxTasks != 0 && --maxTasks == 0)
+                        break;
+                    origin = k;                  // reset
+                    oldSum = checkSum = 0;
+                }
+                else {                           // poll other queues
+                    if ((q = ws[k]) == null)
+                        h = 0;
+                    else if ((h = q.pollAndExecCC(task)) < 0)
+                        checkSum += h;
+                    if (h > 0) {
+                        if (h == 1 && maxTasks != 0 && --maxTasks == 0)
+                            break;
+                        r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
+                        origin = k = r & m;      // move and restart
+                        oldSum = checkSum = 0;
+                    }
+                    else if ((k = (k + 1) & m) == origin) {
+                        if (oldSum == (oldSum = checkSum))
+                            break;
+                        checkSum = 0;
+                    }
                 }
             }
         }
-        return stat;
-    }
-
-    /**
-     * Possibly releases (signals) a worker. Called only from scan()
-     * when a worker with apparently inactive status finds a non-empty
-     * queue. This requires revalidating all of the associated state
-     * from caller.
-     */
-    private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w,
-                                   WorkQueue q, int b) {
-        WorkQueue v; int e, i; Thread p;
-        if (w != null && w.eventCount < 0 && (e = (int)c) > 0 &&
-            ws != null && ws.length > (i = e & SMASK) &&
-            (v = ws[i]) != null && ctl == c) {
-            long nc = (((long)(v.nextWait & E_MASK)) |
-                       ((long)((int)(c >>> 32) + UAC_UNIT)) << 32);
-            int ne = (e + E_SEQ) & E_MASK;
-            if (q != null && q.base == b && w.eventCount < 0 &&
-                v.eventCount == (e | INT_SIGN) &&
-                U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.eventCount = ne;
-                if ((p = v.parker) != null)
-                    U.unpark(p);
-            }
-        }
+        return s;
     }
 
     /**
@@ -1799,268 +1906,167 @@
      * execute tasks from. The first call to this method upon a
      * waiting join will often entail scanning/search, (which is OK
      * because the joiner has nothing better to do), but this method
-     * leaves hints in workers to speed up subsequent calls. The
-     * implementation is very branchy to cope with potential
-     * inconsistencies or loops encountering chains that are stale,
-     * unknown, or so long that they are likely cyclic.
+     * leaves hints in workers to speed up subsequent calls.
      *
-     * @param joiner the joining worker
+     * @param w caller
      * @param task the task to join
-     * @return 0 if no progress can be made, negative if task
-     * known complete, else positive
      */
-    private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
-        int stat = 0, steps = 0;                    // bound to avoid cycles
-        if (task != null && joiner != null &&
-            joiner.base - joiner.top >= 0) {        // hoist checks
-            restart: for (;;) {
-                ForkJoinTask<?> subtask = task;     // current target
-                for (WorkQueue j = joiner, v;;) {   // v is stealer of subtask
-                    WorkQueue[] ws; int m, s, h;
-                    if ((s = task.status) < 0) {
-                        stat = s;
-                        break restart;
-                    }
-                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
-                        break restart;              // shutting down
-                    if ((v = ws[h = (j.hint | 1) & m]) == null ||
-                        v.currentSteal != subtask) {
-                        for (int origin = h;;) {    // find stealer
-                            if (((h = (h + 2) & m) & 15) == 1 &&
-                                (subtask.status < 0 || j.currentJoin != subtask))
-                                continue restart;   // occasional staleness check
-                            if ((v = ws[h]) != null &&
-                                v.currentSteal == subtask) {
-                                j.hint = h;        // save hint
+    private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
+        WorkQueue[] ws = workQueues;
+        int oldSum = 0, checkSum, m;
+        if (ws != null && (m = ws.length - 1) >= 0 && w != null &&
+            task != null) {
+            do {                                       // restart point
+                checkSum = 0;                          // for stability check
+                ForkJoinTask<?> subtask;
+                WorkQueue j = w, v;                    // v is subtask stealer
+                descent: for (subtask = task; subtask.status >= 0; ) {
+                    for (int h = j.hint | 1, k = 0, i; ; k += 2) {
+                        if (k > m)                     // can't find stealer
+                            break descent;
+                        if ((v = ws[i = (h + k) & m]) != null) {
+                            if (v.currentSteal == subtask) {
+                                j.hint = i;
                                 break;
                             }
-                            if (h == origin)
-                                break restart;      // cannot find stealer
+                            checkSum += v.base;
                         }
                     }
-                    for (;;) { // help stealer or descend to its stealer
+                    for (;;) {                         // help v or descend
                         ForkJoinTask<?>[] a; int b;
-                        if (subtask.status < 0)     // surround probes with
-                            continue restart;       //   consistency checks
-                        if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
-                            int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                            ForkJoinTask<?> t =
-                                (ForkJoinTask<?>)U.getObjectVolatile(a, i);
-                            if (subtask.status < 0 || j.currentJoin != subtask ||
-                                v.currentSteal != subtask)
-                                continue restart;   // stale
-                            stat = 1;               // apparent progress
-                            if (v.base == b) {
-                                if (t == null)
-                                    break restart;
-                                if (U.compareAndSwapObject(a, i, t, null)) {
-                                    U.putOrderedInt(v, QBASE, b + 1);
-                                    ForkJoinTask<?> ps = joiner.currentSteal;
-                                    int jt = joiner.top;
-                                    do {
-                                        joiner.currentSteal = t;
-                                        t.doExec(); // clear local tasks too
-                                    } while (task.status >= 0 &&
-                                             joiner.top != jt &&
-                                             (t = joiner.pop()) != null);
-                                    joiner.currentSteal = ps;
-                                    break restart;
-                                }
-                            }
+                        checkSum += (b = v.base);
+                        ForkJoinTask<?> next = v.currentJoin;
+                        if (subtask.status < 0 || j.currentJoin != subtask ||
+                            v.currentSteal != subtask) // stale
+                            break descent;
+                        if (b - v.top >= 0 || (a = v.array) == null) {
+                            if ((subtask = next) == null)
+                                break descent;
+                            j = v;
+                            break;
                         }
-                        else {                      // empty -- try to descend
-                            ForkJoinTask<?> next = v.currentJoin;
-                            if (subtask.status < 0 || j.currentJoin != subtask ||
-                                v.currentSteal != subtask)
-                                continue restart;   // stale
-                            else if (next == null || ++steps == MAX_HELP)
-                                break restart;      // dead-end or maybe cyclic
-                            else {
-                                subtask = next;
-                                j = v;
-                                break;
+                        int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                        ForkJoinTask<?> t = ((ForkJoinTask<?>)
+                                             U.getObjectVolatile(a, i));
+                        if (v.base == b) {
+                            if (t == null)             // stale
+                                break descent;
+                            if (U.compareAndSwapObject(a, i, t, null)) {
+                                v.base = b + 1;
+                                ForkJoinTask<?> ps = w.currentSteal;
+                                int top = w.top;
+                                do {
+                                    U.putOrderedObject(w, QCURRENTSTEAL, t);
+                                    t.doExec();        // clear local tasks too
+                                } while (task.status >= 0 &&
+                                         w.top != top &&
+                                         (t = w.pop()) != null);
+                                U.putOrderedObject(w, QCURRENTSTEAL, ps);
+                                if (w.base != w.top)
+                                    return;            // can't further help
                             }
                         }
                     }
                 }
-            }
+            } while (task.status >= 0 && oldSum != (oldSum = checkSum));
         }
-        return stat;
-    }
-
-    /**
-     * Analog of tryHelpStealer for CountedCompleters. Tries to steal
-     * and run tasks within the target's computation.
-     *
-     * @param task the task to join
-     * @param maxTasks the maximum number of other tasks to run
-     */
-    final int helpComplete(WorkQueue joiner, CountedCompleter<?> task,
-                           int maxTasks) {
-        WorkQueue[] ws; int m;
-        int s = 0;
-        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
-            joiner != null && task != null) {
-            int j = joiner.poolIndex;
-            int scans = m + m + 1;
-            long c = 0L;              // for stability check
-            for (int k = scans; ; j += 2) {
-                WorkQueue q;
-                if ((s = task.status) < 0)
-                    break;
-                else if (joiner.internalPopAndExecCC(task)) {
-                    if (--maxTasks <= 0) {
-                        s = task.status;
-                        break;
-                    }
-                    k = scans;
-                }
-                else if ((s = task.status) < 0)
-                    break;
-                else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
-                    if (--maxTasks <= 0) {
-                        s = task.status;
-                        break;
-                    }
-                    k = scans;
-                }
-                else if (--k < 0) {
-                    if (c == (c = ctl))
-                        break;
-                    k = scans;
-                }
-            }
-        }
-        return s;
     }
 
     /**
      * Tries to decrement active count (sometimes implicitly) and
      * possibly release or create a compensating worker in preparation
-     * for blocking. Fails on contention or termination. Otherwise,
-     * adds a new thread if no idle workers are available and pool
-     * may become starved.
+     * for blocking. Returns false (retryable by caller), on
+     * contention, detected staleness, instability, or termination.
      *
-     * @param c the assumed ctl value
+     * @param w caller
      */
-    final boolean tryCompensate(long c) {
-        WorkQueue[] ws = workQueues;
-        int pc = parallelism, e = (int)c, m, tc;
-        if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) {
-            WorkQueue w = ws[e & m];
-            if (e != 0 && w != null) {
-                Thread p;
-                long nc = ((long)(w.nextWait & E_MASK) |
-                           (c & (AC_MASK|TC_MASK)));
-                int ne = (e + E_SEQ) & E_MASK;
-                if (w.eventCount == (e | INT_SIGN) &&
-                    U.compareAndSwapLong(this, CTL, c, nc)) {
-                    w.eventCount = ne;
-                    if ((p = w.parker) != null)
-                        U.unpark(p);
-                    return true;   // replace with idle worker
+    private boolean tryCompensate(WorkQueue w) {
+        boolean canBlock;
+        WorkQueue[] ws; long c; int m, pc, sp;
+        if (w == null || w.qlock < 0 ||           // caller terminating
+            (ws = workQueues) == null || (m = ws.length - 1) <= 0 ||
+            (pc = config & SMASK) == 0)           // parallelism disabled
+            canBlock = false;
+        else if ((sp = (int)(c = ctl)) != 0)      // release idle worker
+            canBlock = tryRelease(c, ws[sp & m], 0L);
+        else {
+            int ac = (int)(c >> AC_SHIFT) + pc;
+            int tc = (short)(c >> TC_SHIFT) + pc;
+            int nbusy = 0;                        // validate saturation
+            for (int i = 0; i <= m; ++i) {        // two passes of odd indices
+                WorkQueue v;
+                if ((v = ws[((i << 1) | 1) & m]) != null) {
+                    if ((v.scanState & SCANNING) != 0)
+                        break;
+                    ++nbusy;
                 }
             }
-            else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 &&
-                     (int)(c >> AC_SHIFT) + pc > 1) {
-                long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
-                if (U.compareAndSwapLong(this, CTL, c, nc))
-                    return true;   // no compensation
+            if (nbusy != (tc << 1) || ctl != c)
+                canBlock = false;                 // unstable or stale
+            else if (tc >= pc && ac > 1 && w.isEmpty()) {
+                long nc = ((AC_MASK & (c - AC_UNIT)) |
+                           (~AC_MASK & c));       // uncompensated
+                canBlock = U.compareAndSwapLong(this, CTL, c, nc);
             }
-            else if (tc + pc < MAX_CAP) {
-                long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
-                if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                    ForkJoinWorkerThreadFactory fac;
-                    Throwable ex = null;
-                    ForkJoinWorkerThread wt = null;
-                    try {
-                        if ((fac = factory) != null &&
-                            (wt = fac.newThread(this)) != null) {
-                            wt.start();
-                            return true;
-                        }
-                    } catch (Throwable rex) {
-                        ex = rex;
-                    }
-                    deregisterWorker(wt, ex); // clean up and return false
-                }
+            else if (tc >= MAX_CAP ||
+                     (this == common && tc >= pc + commonMaxSpares))
+                throw new RejectedExecutionException(
+                    "Thread limit exceeded replacing blocked worker");
+            else {                                // similar to tryAddWorker
+                boolean add = false; int rs;      // CAS within lock
+                long nc = ((AC_MASK & c) |
+                           (TC_MASK & (c + TC_UNIT)));
+                if (((rs = lockRunState()) & STOP) == 0)
+                    add = U.compareAndSwapLong(this, CTL, c, nc);
+                unlockRunState(rs, rs & ~RSLOCK);
+                canBlock = add && createWorker(); // throws on exception
             }
         }
-        return false;
+        return canBlock;
     }
 
     /**
-     * Helps and/or blocks until the given task is done.
+     * Helps and/or blocks until the given task is done or timeout.
      *
-     * @param joiner the joining worker
+     * @param w caller
      * @param task the task
+     * @param deadline for timed waits, if nonzero
      * @return task status on exit
      */
-    final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
+    final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
         int s = 0;
-        if (task != null && (s = task.status) >= 0 && joiner != null) {
-            ForkJoinTask<?> prevJoin = joiner.currentJoin;
-            joiner.currentJoin = task;
-            do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
-                         (s = task.status) >= 0);
-            if (s >= 0 && (task instanceof CountedCompleter))
-                s = helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
-            long cc = 0;        // for stability checks
-            while (s >= 0 && (s = task.status) >= 0) {
-                if ((s = tryHelpStealer(joiner, task)) == 0 &&
-                    (s = task.status) >= 0) {
-                    if (!tryCompensate(cc))
-                        cc = ctl;
-                    else {
-                        if (task.trySetSignal() && (s = task.status) >= 0) {
-                            synchronized (task) {
-                                if (task.status >= 0) {
-                                    try {                // see ForkJoinTask
-                                        task.wait();     //  for explanation
-                                    } catch (InterruptedException ie) {
-                                    }
-                                }
-                                else
-                                    task.notifyAll();
-                            }
-                        }
-                        long c; // reactivate
-                        do {} while (!U.compareAndSwapLong
-                                     (this, CTL, c = ctl,
-                                      ((c & ~AC_MASK) |
-                                       ((c & AC_MASK) + AC_UNIT))));
-                    }
+        if (task != null && w != null) {
+            ForkJoinTask<?> prevJoin = w.currentJoin;
+            U.putOrderedObject(w, QCURRENTJOIN, task);
+            CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
+                (CountedCompleter<?>)task : null;
+            for (;;) {
+                if ((s = task.status) < 0)
+                    break;
+                if (cc != null)
+                    helpComplete(w, cc, 0);
+                else if (w.base == w.top || w.tryRemoveAndExec(task))
+                    helpStealer(w, task);
+                if ((s = task.status) < 0)
+                    break;
+                long ms, ns;
+                if (deadline == 0L)
+                    ms = 0L;
+                else if ((ns = deadline - System.nanoTime()) <= 0L)
+                    break;
+                else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
+                    ms = 1L;
+                if (tryCompensate(w)) {
+                    task.internalWait(ms);
+                    U.getAndAddLong(this, CTL, AC_UNIT);
                 }
             }
-            joiner.currentJoin = prevJoin;
+            U.putOrderedObject(w, QCURRENTJOIN, prevJoin);
         }
         return s;
     }
 
-    /**
-     * Stripped-down variant of awaitJoin used by timed joins. Tries
-     * to help join only while there is continuous progress. (Caller
-     * will then enter a timed wait.)
-     *
-     * @param joiner the joining worker
-     * @param task the task
-     */
-    final void helpJoinOnce(WorkQueue joiner, ForkJoinTask<?> task) {
-        int s;
-        if (joiner != null && task != null && (s = task.status) >= 0) {
-            ForkJoinTask<?> prevJoin = joiner.currentJoin;
-            joiner.currentJoin = task;
-            do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
-                         (s = task.status) >= 0);
-            if (s >= 0) {
-                if (task instanceof CountedCompleter)
-                    helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
-                do {} while (task.status >= 0 &&
-                             tryHelpStealer(joiner, task) > 0);
-            }
-            joiner.currentJoin = prevJoin;
-        }
-    }
+    // Specialized scanning
 
     /**
      * Returns a (probably) non-empty steal queue, if one is found
@@ -2068,19 +2074,24 @@
      * caller if, by the time it tries to use the queue, it is empty.
      */
     private WorkQueue findNonEmptyStealQueue() {
+        WorkQueue[] ws; int m;  // one-shot version of scan loop
         int r = ThreadLocalRandom.nextSecondarySeed();
-        for (;;) {
-            int ps = plock, m; WorkQueue[] ws; WorkQueue q;
-            if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
-                for (int j = (m + 1) << 2; j >= 0; --j) {
-                    if ((q = ws[(((r - j) << 1) | 1) & m]) != null &&
-                        q.base - q.top < 0)
+        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+            for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
+                WorkQueue q; int b;
+                if ((q = ws[k]) != null) {
+                    if ((b = q.base) - q.top < 0)
                         return q;
+                    checkSum += b;
+                }
+                if ((k = (k + 1) & m) == origin) {
+                    if (oldSum == (oldSum = checkSum))
+                        break;
+                    checkSum = 0;
                 }
             }
-            if (plock == ps)
-                return null;
         }
+        return null;
     }
 
     /**
@@ -2090,35 +2101,34 @@
      * find tasks either.
      */
     final void helpQuiescePool(WorkQueue w) {
-        ForkJoinTask<?> ps = w.currentSteal;
+        ForkJoinTask<?> ps = w.currentSteal; // save context
         for (boolean active = true;;) {
             long c; WorkQueue q; ForkJoinTask<?> t; int b;
-            while ((t = w.nextLocalTask()) != null)
-                t.doExec();
+            w.execLocalTasks();     // run locals before each scan
             if ((q = findNonEmptyStealQueue()) != null) {
                 if (!active) {      // re-establish active count
                     active = true;
-                    do {} while (!U.compareAndSwapLong
-                                 (this, CTL, c = ctl,
-                                  ((c & ~AC_MASK) |
-                                   ((c & AC_MASK) + AC_UNIT))));
+                    U.getAndAddLong(this, CTL, AC_UNIT);
                 }
-                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
-                    w.runTask(t);
+                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
+                    U.putOrderedObject(w, QCURRENTSTEAL, t);
+                    t.doExec();
+                    if (++w.nsteals < 0)
+                        w.transferStealCount(this);
+                }
             }
             else if (active) {      // decrement active count without queuing
-                long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT);
-                if ((int)(nc >> AC_SHIFT) + parallelism == 0)
+                long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c);
+                if ((int)(nc >> AC_SHIFT) + (config & SMASK) <= 0)
                     break;          // bypass decrement-then-increment
                 if (U.compareAndSwapLong(this, CTL, c, nc))
                     active = false;
             }
-            else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 &&
-                     U.compareAndSwapLong
-                     (this, CTL, c, ((c & ~AC_MASK) |
-                                     ((c & AC_MASK) + AC_UNIT))))
+            else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) <= 0 &&
+                     U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
                 break;
         }
+        U.putOrderedObject(w, QCURRENTSTEAL, ps);
     }
 
     /**
@@ -2141,7 +2151,7 @@
     /**
      * Returns a cheap heuristic guide for task partitioning when
      * programmers, frameworks, tools, or languages have little or no
-     * idea about task granularity.  In essence by offering this
+     * idea about task granularity.  In essence, by offering this
      * method, we ask users only about tradeoffs in overhead vs
      * expected throughput and its variance, rather than how finely to
      * partition tasks.
@@ -2179,15 +2189,12 @@
      * many of these by further considering the number of "idle"
      * threads, that are known to have zero queued tasks, so
      * compensate by a factor of (#idle/#active) threads.
-     *
-     * Note: The approximation of #busy workers as #active workers is
-     * not very good under current signalling scheme, and should be
-     * improved.
      */
     static int getSurplusQueuedTaskCount() {
         Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
         if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
-            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).parallelism;
+            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).
+                config & SMASK;
             int n = (q = wt.workQueue).top - q.base;
             int a = (int)(pool.ctl >> AC_SHIFT) + p;
             return n - (a > (p >>>= 1) ? 0 :
@@ -2202,13 +2209,7 @@
     //  Termination
 
     /**
-     * Possibly initiates and/or completes termination.  The caller
-     * triggering termination runs three passes through workQueues:
-     * (0) Setting termination status, followed by wakeups of queued
-     * workers; (1) cancelling all tasks; (2) interrupting lagging
-     * threads (likely in external tasks, but possibly also blocked in
-     * joins).  Each pass repeats previous steps because of potential
-     * lagging thread creation.
+     * Possibly initiates and/or completes termination.
      *
      * @param now if true, unconditionally terminate, else only
      * if no work and no active workers
@@ -2216,166 +2217,256 @@
      * @return true if now terminating or terminated
      */
     private boolean tryTerminate(boolean now, boolean enable) {
-        int ps;
-        if (this == common)                        // cannot shut down
+        int rs;
+        if (this == common)                       // cannot shut down
             return false;
-        if ((ps = plock) >= 0) {                   // enable by setting plock
+        if ((rs = runState) >= 0) {
             if (!enable)
                 return false;
-            if ((ps & PL_LOCK) != 0 ||
-                !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
-                ps = acquirePlock();
-            int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN;
-            if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
-                releasePlock(nps);
+            rs = lockRunState();                  // enter SHUTDOWN phase
+            unlockRunState(rs, (rs & ~RSLOCK) | SHUTDOWN);
         }
-        for (long c;;) {
-            if (((c = ctl) & STOP_BIT) != 0) {     // already terminating
-                if ((short)(c >>> TC_SHIFT) + parallelism <= 0) {
-                    synchronized (this) {
-                        notifyAll();               // signal when 0 workers
-                    }
-                }
-                return true;
-            }
-            if (!now) {                            // check if idle & no tasks
-                WorkQueue[] ws; WorkQueue w;
-                if ((int)(c >> AC_SHIFT) + parallelism > 0)
-                    return false;
-                if ((ws = workQueues) != null) {
-                    for (int i = 0; i < ws.length; ++i) {
-                        if ((w = ws[i]) != null &&
-                            (!w.isEmpty() ||
-                             ((i & 1) != 0 && w.eventCount >= 0))) {
-                            signalWork(ws, w);
-                            return false;
+
+        if ((rs & STOP) == 0) {
+            if (!now) {                           // check quiescence
+                for (long oldSum = 0L;;) {        // repeat until stable
+                    WorkQueue[] ws; WorkQueue w; int m, b; long c;
+                    long checkSum = ctl;
+                    if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
+                        return false;             // still active workers
+                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
+                        break;                    // check queues
+                    for (int i = 0; i <= m; ++i) {
+                        if ((w = ws[i]) != null) {
+                            if ((b = w.base) != w.top || w.scanState >= 0 ||
+                                w.currentSteal != null) {
+                                tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
+                                return false;     // arrange for recheck
+                            }
+                            checkSum += b;
+                            if ((i & 1) == 0)
+                                w.qlock = -1;     // try to disable external
                         }
                     }
+                    if (oldSum == (oldSum = checkSum))
+                        break;
                 }
             }
-            if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) {
-                for (int pass = 0; pass < 3; ++pass) {
-                    WorkQueue[] ws; WorkQueue w; Thread wt;
-                    if ((ws = workQueues) != null) {
-                        int n = ws.length;
-                        for (int i = 0; i < n; ++i) {
-                            if ((w = ws[i]) != null) {
-                                w.qlock = -1;
-                                if (pass > 0) {
-                                    w.cancelAll();
-                                    if (pass > 1 && (wt = w.owner) != null) {
-                                        if (!wt.isInterrupted()) {
-                                            try {
-                                                wt.interrupt();
-                                            } catch (Throwable ignore) {
-                                            }
-                                        }
-                                        U.unpark(wt);
-                                    }
+            if ((runState & STOP) == 0) {
+                rs = lockRunState();              // enter STOP phase
+                unlockRunState(rs, (rs & ~RSLOCK) | STOP);
+            }
+        }
+
+        int pass = 0;                             // 3 passes to help terminate
+        for (long oldSum = 0L;;) {                // or until done or stable
+            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt; int m;
+            long checkSum = ctl;
+            if ((short)(checkSum >>> TC_SHIFT) + (config & SMASK) <= 0 ||
+                (ws = workQueues) == null || (m = ws.length - 1) <= 0) {
+                if ((runState & TERMINATED) == 0) {
+                    rs = lockRunState();          // done
+                    unlockRunState(rs, (rs & ~RSLOCK) | TERMINATED);
+                    synchronized (this) { notifyAll(); } // for awaitTermination
+                }
+                break;
+            }
+            for (int i = 0; i <= m; ++i) {
+                if ((w = ws[i]) != null) {
+                    checkSum += w.base;
+                    w.qlock = -1;                 // try to disable
+                    if (pass > 0) {
+                        w.cancelAll();            // clear queue
+                        if (pass > 1 && (wt = w.owner) != null) {
+                            if (!wt.isInterrupted()) {
+                                try {             // unblock join
+                                    wt.interrupt();
+                                } catch (Throwable ignore) {
                                 }
                             }
-                        }
-                        // Wake up workers parked on event queue
-                        int i, e; long cc; Thread p;
-                        while ((e = (int)(cc = ctl) & E_MASK) != 0 &&
-                               (i = e & SMASK) < n && i >= 0 &&
-                               (w = ws[i]) != null) {
-                            long nc = ((long)(w.nextWait & E_MASK) |
-                                       ((cc + AC_UNIT) & AC_MASK) |
-                                       (cc & (TC_MASK|STOP_BIT)));
-                            if (w.eventCount == (e | INT_SIGN) &&
-                                U.compareAndSwapLong(this, CTL, cc, nc)) {
-                                w.eventCount = (e + E_SEQ) & E_MASK;
-                                w.qlock = -1;
-                                if ((p = w.parker) != null)
-                                    U.unpark(p);
-                            }
+                            if (w.scanState < 0)
+                                U.unpark(wt);     // wake up
                         }
                     }
                 }
             }
+            if (checkSum != oldSum) {             // unstable
+                oldSum = checkSum;
+                pass = 0;
+            }
+            else if (pass > 3 && pass > m)        // can't further help
+                break;
+            else if (++pass > 1) {                // try to dequeue
+                long c; int j = 0, sp;            // bound attempts
+                while (j++ <= m && (sp = (int)(c = ctl)) != 0)
+                    tryRelease(c, ws[sp & m], AC_UNIT);
+            }
         }
+        return true;
     }
 
-    // external operations on common pool
+    // External operations
 
     /**
-     * Returns common pool queue for a thread that has submitted at
-     * least one task.
+     * Full version of externalPush, handling uncommon cases, as well
+     * as performing secondary initialization upon the first
+     * submission of the first task to the pool.  It also detects
+     * first submission by an external thread and creates a new shared
+     * queue if the one at index if empty or contended.
+     *
+     * @param task the task. Caller must ensure non-null.
      */
-    static WorkQueue commonSubmitterQueue() {
-        ForkJoinPool p; WorkQueue[] ws; int m, z;
-        return ((z = ThreadLocalRandom.getProbe()) != 0 &&
-                (p = common) != null &&
-                (ws = p.workQueues) != null &&
-                (m = ws.length - 1) >= 0) ?
-            ws[m & z & SQMASK] : null;
+    private void externalSubmit(ForkJoinTask<?> task) {
+        int r;                                    // initialize caller's probe
+        if ((r = ThreadLocalRandom.getProbe()) == 0) {
+            ThreadLocalRandom.localInit();
+            r = ThreadLocalRandom.getProbe();
+        }
+        for (;;) {
+            WorkQueue[] ws; WorkQueue q; int rs, m, k;
+            boolean move = false;
+            if ((rs = runState) < 0) {
+                tryTerminate(false, false);     // help terminate
+                throw new RejectedExecutionException();
+            }
+            else if ((rs & STARTED) == 0 ||     // initialize
+                     ((ws = workQueues) == null || (m = ws.length - 1) < 0)) {
+                int ns = 0;
+                rs = lockRunState();
+                try {
+                    if ((rs & STARTED) == 0) {
+                        U.compareAndSwapObject(this, STEALCOUNTER, null,
+                                               new AtomicLong());
+                        // create workQueues array with size a power of two
+                        int p = config & SMASK; // ensure at least 2 slots
+                        int n = (p > 1) ? p - 1 : 1;
+                        n |= n >>> 1; n |= n >>> 2;  n |= n >>> 4;
+                        n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
+                        workQueues = new WorkQueue[n];
+                        ns = STARTED;
+                    }
+                } finally {
+                    unlockRunState(rs, (rs & ~RSLOCK) | ns);
+                }
+            }
+            else if ((q = ws[k = r & m & SQMASK]) != null) {
+                if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+                    ForkJoinTask<?>[] a = q.array;
+                    int s = q.top;
+                    boolean submitted = false; // initial submission or resizing
+                    try {                      // locked version of push
+                        if ((a != null && a.length > s + 1 - q.base) ||
+                            (a = q.growArray()) != null) {
+                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
+                            U.putOrderedObject(a, j, task);
+                            U.putOrderedInt(q, QTOP, s + 1);
+                            submitted = true;
+                        }
+                    } finally {
+                        U.compareAndSwapInt(q, QLOCK, 1, 0);
+                    }
+                    if (submitted) {
+                        signalWork(ws, q);
+                        return;
+                    }
+                }
+                move = true;                   // move on failure
+            }
+            else if (((rs = runState) & RSLOCK) == 0) { // create new queue
+                q = new WorkQueue(this, null);
+                q.hint = r;
+                q.config = k | SHARED_QUEUE;
+                q.scanState = INACTIVE;
+                rs = lockRunState();           // publish index
+                if (rs > 0 &&  (ws = workQueues) != null &&
+                    k < ws.length && ws[k] == null)
+                    ws[k] = q;                 // else terminated
+                unlockRunState(rs, rs & ~RSLOCK);
+            }
+            else
+                move = true;                   // move if busy
+            if (move)
+                r = ThreadLocalRandom.advanceProbe(r);
+        }
     }
 
     /**
-     * Tries to pop the given task from submitter's queue in common pool.
+     * Tries to add the given task to a submission queue at
+     * submitter's current queue. Only the (vastly) most common path
+     * is directly handled in this method, while screening for need
+     * for externalSubmit.
+     *
+     * @param task the task. Caller must ensure non-null.
      */
-    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
-        WorkQueue joiner; ForkJoinTask<?>[] a; int m, s;
-        WorkQueue[] ws = workQueues;
-        int z = ThreadLocalRandom.getProbe();
-        boolean popped = false;
-        if (ws != null && (m = ws.length - 1) >= 0 &&
-            (joiner = ws[z & m & SQMASK]) != null &&
-            joiner.base != (s = joiner.top) &&
-            (a = joiner.array) != null) {
-            long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
-            if (U.getObject(a, j) == task &&
-                U.compareAndSwapInt(joiner, QLOCK, 0, 1)) {
-                if (joiner.top == s && joiner.array == a &&
-                    U.compareAndSwapObject(a, j, task, null)) {
-                    joiner.top = s - 1;
-                    popped = true;
-                }
-                joiner.qlock = 0;
+    final void externalPush(ForkJoinTask<?> task) {
+        WorkQueue[] ws; WorkQueue q; int m;
+        int r = ThreadLocalRandom.getProbe();
+        int rs = runState;
+        if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
+            (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
+            U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+            ForkJoinTask<?>[] a; int am, n, s;
+            if ((a = q.array) != null &&
+                (am = a.length - 1) > (n = (s = q.top) - q.base)) {
+                int j = ((am & s) << ASHIFT) + ABASE;
+                U.putOrderedObject(a, j, task);
+                U.putOrderedInt(q, QTOP, s + 1);
+                U.putOrderedInt(q, QLOCK, 0);
+                if (n <= 1)
+                    signalWork(ws, q);
+                return;
             }
+            U.compareAndSwapInt(q, QLOCK, 1, 0);
         }
-        return popped;
+        externalSubmit(task);
     }
 
-    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
-        WorkQueue joiner; int m;
-        WorkQueue[] ws = workQueues;
-        int j = ThreadLocalRandom.getProbe();
-        int s = 0;
-        if (ws != null && (m = ws.length - 1) >= 0 &&
-            (joiner = ws[j & m & SQMASK]) != null && task != null) {
-            int scans = m + m + 1;
-            long c = 0L;             // for stability check
-            j |= 1;                  // poll odd queues
-            for (int k = scans; ; j += 2) {
-                WorkQueue q;
-                if ((s = task.status) < 0)
-                    break;
-                else if (joiner.externalPopAndExecCC(task)) {
-                    if (--maxTasks <= 0) {
-                        s = task.status;
-                        break;
-                    }
-                    k = scans;
+    /**
+     * Returns common pool queue for an external thread.
+     */
+    static WorkQueue commonSubmitterQueue() {
+        ForkJoinPool p = common;
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; int m;
+        return (p != null && (ws = p.workQueues) != null &&
+                (m = ws.length - 1) >= 0) ?
+            ws[m & r & SQMASK] : null;
+    }
+
+    /**
+     * Performs tryUnpush for an external submitter: Finds queue,
+     * locks if apparently non-empty, validates upon locking, and
+     * adjusts top. Each check can fail but rarely does.
+     */
+    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
+        WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m, s;
+        int r = ThreadLocalRandom.getProbe();
+        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+            (w = ws[m & r & SQMASK]) != null &&
+            (a = w.array) != null && (s = w.top) != w.base) {
+            long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+            if (U.compareAndSwapInt(w, QLOCK, 0, 1)) {
+                if (w.top == s && w.array == a &&
+                    U.getObject(a, j) == task &&
+                    U.compareAndSwapObject(a, j, task, null)) {
+                    U.putOrderedInt(w, QTOP, s - 1);
+                    U.putOrderedInt(w, QLOCK, 0);
+                    return true;
                 }
-                else if ((s = task.status) < 0)
-                    break;
-                else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
-                    if (--maxTasks <= 0) {
-                        s = task.status;
-                        break;
-                    }
-                    k = scans;
-                }
-                else if (--k < 0) {
-                    if (c == (c = ctl))
-                        break;
-                    k = scans;
-                }
+                U.compareAndSwapInt(w, QLOCK, 1, 0);
             }
         }
-        return s;
+        return false;
+    }
+
+    /**
+     * Performs helpComplete for an external submitter.
+     */
+    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
+        WorkQueue[] ws; int n;
+        int r = ThreadLocalRandom.getProbe();
+        return ((ws = workQueues) == null || (n = ws.length) == 0) ? 0 :
+            helpComplete(ws[(n - 1) & r & SQMASK], task, maxTasks);
     }
 
     // Exported methods
@@ -2447,7 +2538,7 @@
         this(checkParallelism(parallelism),
              checkFactory(factory),
              handler,
-             (asyncMode ? FIFO_QUEUE : LIFO_QUEUE),
+             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
              "ForkJoinPool-" + nextPoolId() + "-worker-");
         checkPermission();
     }
@@ -2478,8 +2569,7 @@
         this.workerNamePrefix = workerNamePrefix;
         this.factory = factory;
         this.ueh = handler;
-        this.mode = (short)mode;
-        this.parallelism = (short)parallelism;
+        this.config = (parallelism & SMASK) | mode;
         long np = (long)(-parallelism); // offset ctl counts
         this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
     }
@@ -2624,7 +2714,7 @@
         // In previous versions of this class, this method constructed
         // a task to run ForkJoinTask.invokeAll, but now external
         // invocation of multiple tasks is at least as efficient.
-        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
 
         boolean done = false;
         try {
@@ -2670,7 +2760,7 @@
      */
     public int getParallelism() {
         int par;
-        return ((par = parallelism) > 0) ? par : 1;
+        return ((par = config & SMASK) > 0) ? par : 1;
     }
 
     /**
@@ -2692,7 +2782,7 @@
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return parallelism + (short)(ctl >>> TC_SHIFT);
+        return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
     }
 
     /**
@@ -2702,7 +2792,7 @@
      * @return {@code true} if this pool uses async mode
      */
     public boolean getAsyncMode() {
-        return mode == FIFO_QUEUE;
+        return (config & FIFO_QUEUE) != 0;
     }
 
     /**
@@ -2733,7 +2823,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        int r = parallelism + (int)(ctl >> AC_SHIFT);
+        int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
         return (r <= 0) ? 0 : r; // suppress momentarily negative values
     }
 
@@ -2749,7 +2839,7 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return parallelism + (int)(ctl >> AC_SHIFT) <= 0;
+        return (config & SMASK) + (int)(ctl >> AC_SHIFT) <= 0;
     }
 
     /**
@@ -2764,7 +2854,8 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        long count = stealCount;
+        AtomicLong sc = stealCounter;
+        long count = (sc == null) ? 0L : sc.get();
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
@@ -2894,7 +2985,8 @@
     public String toString() {
         // Use a single pass through workQueues to collect counts
         long qt = 0L, qs = 0L; int rc = 0;
-        long st = stealCount;
+        AtomicLong sc = stealCounter;
+        long st = (sc == null) ? 0L : sc.get();
         long c = ctl;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
@@ -2912,16 +3004,16 @@
                 }
             }
         }
-        int pc = parallelism;
+        int pc = (config & SMASK);
         int tc = pc + (short)(c >>> TC_SHIFT);
         int ac = pc + (int)(c >> AC_SHIFT);
         if (ac < 0) // ignore transient negative
             ac = 0;
-        String level;
-        if ((c & STOP_BIT) != 0)
-            level = (tc == 0) ? "Terminated" : "Terminating";
-        else
-            level = plock < 0 ? "Shutting down" : "Running";
+        int rs = runState;
+        String level = ((rs & TERMINATED) != 0 ? "Terminated" :
+                        (rs & STOP)       != 0 ? "Terminating" :
+                        (rs & SHUTDOWN)   != 0 ? "Shutting down" :
+                        "Running");
         return super.toString() +
             "[" + level +
             ", parallelism = " + pc +
@@ -2983,9 +3075,7 @@
      * @return {@code true} if all tasks have completed following shut down
      */
     public boolean isTerminated() {
-        long c = ctl;
-        return ((c & STOP_BIT) != 0L &&
-                (short)(c >>> TC_SHIFT) + parallelism <= 0);
+        return (runState & TERMINATED) != 0;
     }
 
     /**
@@ -3002,9 +3092,8 @@
      * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        long c = ctl;
-        return ((c & STOP_BIT) != 0L &&
-                (short)(c >>> TC_SHIFT) + parallelism > 0);
+        int rs = runState;
+        return (rs & STOP) != 0 && (rs & TERMINATED) == 0;
     }
 
     /**
@@ -3013,7 +3102,7 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return plock < 0;
+        return (runState & SHUTDOWN) != 0;
     }
 
     /**
@@ -3090,8 +3179,9 @@
             }
             found = false;
             for (int j = (m + 1) << 2; j >= 0; --j) {
-                ForkJoinTask<?> t; WorkQueue q; int b;
-                if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) {
+                ForkJoinTask<?> t; WorkQueue q; int b, k;
+                if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null &&
+                    (b = q.base) - q.top < 0) {
                     found = true;
                     if ((t = q.pollAt(b)) != null)
                         t.doExec();
@@ -3115,8 +3205,8 @@
      * in {@link ForkJoinPool}s.
      *
      * <p>A {@code ManagedBlocker} provides two methods.  Method
-     * {@code isReleasable} must return {@code true} if blocking is
-     * not necessary. Method {@code block} blocks the current thread
+     * {@link #isReleasable} must return {@code true} if blocking is
+     * not necessary. Method {@link #block} blocks the current thread
      * if necessary (perhaps internally invoking {@code isReleasable}
      * before actually blocking). These actions are performed by any
      * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}.
@@ -3185,37 +3275,46 @@
     }
 
     /**
-     * Blocks in accord with the given blocker.  If the current thread
-     * is a {@link ForkJoinWorkerThread}, this method possibly
-     * arranges for a spare thread to be activated if necessary to
-     * ensure sufficient parallelism while the current thread is blocked.
+     * Runs the given possibly blocking task.  When {@linkplain
+     * ForkJoinTask#inForkJoinPool() running in a ForkJoinPool}, this
+     * method possibly arranges for a spare thread to be activated if
+     * necessary to ensure sufficient parallelism while the current
+     * thread is blocked in {@link ManagedBlocker#block blocker.block()}.
      *
-     * <p>If the caller is not a {@link ForkJoinTask}, this method is
+     * <p>This method repeatedly calls {@code blocker.isReleasable()} and
+     * {@code blocker.block()} until either method returns {@code true}.
+     * Every call to {@code blocker.block()} is preceded by a call to
+     * {@code blocker.isReleasable()} that returned {@code false}.
+     *
+     * <p>If not running in a ForkJoinPool, this method is
      * behaviorally equivalent to
      *  <pre> {@code
      * while (!blocker.isReleasable())
      *   if (blocker.block())
-     *     return;
-     * }</pre>
+     *     break;}</pre>
      *
-     * If the caller is a {@code ForkJoinTask}, then the pool may
-     * first be expanded to ensure parallelism, and later adjusted.
+     * If running in a ForkJoinPool, the pool may first be expanded to
+     * ensure sufficient parallelism available during the call to
+     * {@code blocker.block()}.
      *
-     * @param blocker the blocker
-     * @throws InterruptedException if blocker.block did so
+     * @param blocker the blocker task
+     * @throws InterruptedException if {@code blocker.block()} did so
      */
     public static void managedBlock(ManagedBlocker blocker)
         throws InterruptedException {
+        ForkJoinPool p;
+        ForkJoinWorkerThread wt;
         Thread t = Thread.currentThread();
-        if (t instanceof ForkJoinWorkerThread) {
-            ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
+        if ((t instanceof ForkJoinWorkerThread) &&
+            (p = (wt = (ForkJoinWorkerThread)t).pool) != null) {
+            WorkQueue w = wt.workQueue;
             while (!blocker.isReleasable()) {
-                if (p.tryCompensate(p.ctl)) {
+                if (p.tryCompensate(w)) {
                     try {
                         do {} while (!blocker.isReleasable() &&
                                      !blocker.block());
                     } finally {
-                        p.incrementActiveCount();
+                        U.getAndAddLong(p, CTL, AC_UNIT);
                     }
                     break;
                 }
@@ -3241,15 +3340,18 @@
 
     // Unsafe mechanics
     private static final sun.misc.Unsafe U;
+    private static final int  ABASE;
+    private static final int  ASHIFT;
     private static final long CTL;
+    private static final long RUNSTATE;
+    private static final long STEALCOUNTER;
     private static final long PARKBLOCKER;
-    private static final int ABASE;
-    private static final int ASHIFT;
-    private static final long STEALCOUNT;
-    private static final long PLOCK;
-    private static final long INDEXSEED;
-    private static final long QBASE;
+    private static final long QTOP;
     private static final long QLOCK;
+    private static final long QSCANSTATE;
+    private static final long QPARKER;
+    private static final long QCURRENTSTEAL;
+    private static final long QCURRENTJOIN;
 
     static {
         // initialize field offsets for CAS etc
@@ -3258,20 +3360,26 @@
             Class<?> k = ForkJoinPool.class;
             CTL = U.objectFieldOffset
                 (k.getDeclaredField("ctl"));
-            STEALCOUNT = U.objectFieldOffset
-                (k.getDeclaredField("stealCount"));
-            PLOCK = U.objectFieldOffset
-                (k.getDeclaredField("plock"));
-            INDEXSEED = U.objectFieldOffset
-                (k.getDeclaredField("indexSeed"));
+            RUNSTATE = U.objectFieldOffset
+                (k.getDeclaredField("runState"));
+            STEALCOUNTER = U.objectFieldOffset
+                (k.getDeclaredField("stealCounter"));
             Class<?> tk = Thread.class;
             PARKBLOCKER = U.objectFieldOffset
                 (tk.getDeclaredField("parkBlocker"));
             Class<?> wk = WorkQueue.class;
-            QBASE = U.objectFieldOffset
-                (wk.getDeclaredField("base"));
+            QTOP = U.objectFieldOffset
+                (wk.getDeclaredField("top"));
             QLOCK = U.objectFieldOffset
                 (wk.getDeclaredField("qlock"));
+            QSCANSTATE = U.objectFieldOffset
+                (wk.getDeclaredField("scanState"));
+            QPARKER = U.objectFieldOffset
+                (wk.getDeclaredField("parker"));
+            QCURRENTSTEAL = U.objectFieldOffset
+                (wk.getDeclaredField("currentSteal"));
+            QCURRENTJOIN = U.objectFieldOffset
+                (wk.getDeclaredField("currentJoin"));
             Class<?> ak = ForkJoinTask[].class;
             ABASE = U.arrayBaseOffset(ak);
             int scale = U.arrayIndexScale(ak);
@@ -3282,6 +3390,7 @@
             throw new Error(e);
         }
 
+        commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
         defaultForkJoinWorkerThreadFactory =
             new DefaultForkJoinWorkerThreadFactory();
         modifyThreadPermission = new RuntimePermission("modifyThread");
@@ -3289,7 +3398,7 @@
         common = java.security.AccessController.doPrivileged
             (new java.security.PrivilegedAction<ForkJoinPool>() {
                 public ForkJoinPool run() { return makeCommonPool(); }});
-        int par = common.parallelism; // report 1 even if threads disabled
+        int par = common.config & SMASK; // report 1 even if threads disabled
         commonParallelism = par > 0 ? par : 1;
     }
 
@@ -3308,6 +3417,8 @@
                 ("java.util.concurrent.ForkJoinPool.common.threadFactory");
             String hp = System.getProperty
                 ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
+            String mp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.maximumSpares");
             if (pp != null)
                 parallelism = Integer.parseInt(pp);
             if (fp != null)
@@ -3316,6 +3427,8 @@
             if (hp != null)
                 handler = ((UncaughtExceptionHandler)ClassLoader.
                            getSystemClassLoader().loadClass(hp).newInstance());
+            if (mp != null)
+                commonMaxSpares = Integer.parseInt(mp);
         } catch (Exception ignore) {
         }
         if (factory == null) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 20:00:59 2017 +0200
@@ -297,15 +297,22 @@
     }
 
     /**
-     * Tries to set SIGNAL status unless already completed. Used by
-     * ForkJoinPool. Other variants are directly incorporated into
-     * externalAwaitDone etc.
+     * If not done, sets SIGNAL status and performs Object.wait(timeout).
+     * This task may or may not be done on exit. Ignores interrupts.
      *
-     * @return true if successful
+     * @param timeout using Object.wait conventions.
      */
-    final boolean trySetSignal() {
-        int s = status;
-        return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL);
+    final void internalWait(long timeout) {
+        int s;
+        if ((s = status) >= 0 && // force completer to issue notify
+            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+            synchronized (this) {
+                if (status >= 0)
+                    try { wait(timeout); } catch (InterruptedException ie) { }
+                else
+                    notifyAll();
+            }
+        }
     }
 
     /**
@@ -313,35 +320,29 @@
      * @return status upon completion
      */
     private int externalAwaitDone() {
-        int s;
-        ForkJoinPool cp = ForkJoinPool.common;
-        if ((s = status) >= 0) {
-            if (cp != null) {
-                if (this instanceof CountedCompleter)
-                    s = cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
-                else if (cp.tryExternalUnpush(this))
-                    s = doExec();
-            }
-            if (s >= 0 && (s = status) >= 0) {
-                boolean interrupted = false;
-                do {
-                    if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                        synchronized (this) {
-                            if (status >= 0) {
-                                try {
-                                    wait();
-                                } catch (InterruptedException ie) {
-                                    interrupted = true;
-                                }
+        int s = ((this instanceof CountedCompleter) ? // try helping
+                 ForkJoinPool.common.externalHelpComplete(
+                     (CountedCompleter<?>)this, 0) :
+                 ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
+        if (s >= 0 && (s = status) >= 0) {
+            boolean interrupted = false;
+            do {
+                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                    synchronized (this) {
+                        if (status >= 0) {
+                            try {
+                                wait(0L);
+                            } catch (InterruptedException ie) {
+                                interrupted = true;
                             }
-                            else
-                                notifyAll();
                         }
+                        else
+                            notifyAll();
                     }
-                } while ((s = status) >= 0);
-                if (interrupted)
-                    Thread.currentThread().interrupt();
-            }
+                }
+            } while ((s = status) >= 0);
+            if (interrupted)
+                Thread.currentThread().interrupt();
         }
         return s;
     }
@@ -351,22 +352,22 @@
      */
     private int externalInterruptibleAwaitDone() throws InterruptedException {
         int s;
-        ForkJoinPool cp = ForkJoinPool.common;
         if (Thread.interrupted())
             throw new InterruptedException();
-        if ((s = status) >= 0 && cp != null) {
-            if (this instanceof CountedCompleter)
-                cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
-            else if (cp.tryExternalUnpush(this))
-                doExec();
-        }
-        while ((s = status) >= 0) {
-            if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                synchronized (this) {
-                    if (status >= 0)
-                        wait();
-                    else
-                        notifyAll();
+        if ((s = status) >= 0 &&
+            (s = ((this instanceof CountedCompleter) ?
+                  ForkJoinPool.common.externalHelpComplete(
+                      (CountedCompleter<?>)this, 0) :
+                  ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
+                  0)) >= 0) {
+            while ((s = status) >= 0) {
+                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                    synchronized (this) {
+                        if (status >= 0)
+                            wait(0L);
+                        else
+                            notifyAll();
+                    }
                 }
             }
         }
@@ -386,7 +387,7 @@
             ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
             (w = (wt = (ForkJoinWorkerThread)t).workQueue).
             tryUnpush(this) && (s = doExec()) < 0 ? s :
-            wt.pool.awaitJoin(w, this) :
+            wt.pool.awaitJoin(w, this, 0L) :
             externalAwaitDone();
     }
 
@@ -399,7 +400,8 @@
         int s; Thread t; ForkJoinWorkerThread wt;
         return (s = doExec()) < 0 ? s :
             ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
-            (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) :
+            (wt = (ForkJoinWorkerThread)t).pool.
+            awaitJoin(wt.workQueue, this, 0L) :
             externalAwaitDone();
     }
 
@@ -577,7 +579,7 @@
         Throwable ex;
         if (e == null || (ex = e.ex) == null)
             return null;
-        if (false && e.thrower != Thread.currentThread().getId()) {
+        if (e.thrower != Thread.currentThread().getId()) {
             Class<? extends Throwable> ec = ex.getClass();
             try {
                 Constructor<?> noArgCtor = null;
@@ -587,13 +589,17 @@
                     Class<?>[] ps = c.getParameterTypes();
                     if (ps.length == 0)
                         noArgCtor = c;
-                    else if (ps.length == 1 && ps[0] == Throwable.class)
-                        return (Throwable)(c.newInstance(ex));
+                    else if (ps.length == 1 && ps[0] == Throwable.class) {
+                        Throwable wx = (Throwable)c.newInstance(ex);
+                        return (wx == null) ? ex : wx;
+                    }
                 }
                 if (noArgCtor != null) {
                     Throwable wx = (Throwable)(noArgCtor.newInstance());
-                    wx.initCause(ex);
-                    return wx;
+                    if (wx != null) {
+                        wx.initCause(ex);
+                        return wx;
+                    }
                 }
             } catch (Exception ignore) {
             }
@@ -1017,67 +1023,40 @@
      */
     public final V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
+        int s;
+        long nanos = unit.toNanos(timeout);
         if (Thread.interrupted())
             throw new InterruptedException();
-        // Messy in part because we measure in nanosecs, but wait in millisecs
-        int s; long ms;
-        long ns = unit.toNanos(timeout);
-        ForkJoinPool cp;
-        if ((s = status) >= 0 && ns > 0L) {
-            long deadline = System.nanoTime() + ns;
-            ForkJoinPool p = null;
-            ForkJoinPool.WorkQueue w = null;
+        if ((s = status) >= 0 && nanos > 0L) {
+            long d = System.nanoTime() + nanos;
+            long deadline = (d == 0L) ? 1L : d; // avoid 0
             Thread t = Thread.currentThread();
             if (t instanceof ForkJoinWorkerThread) {
                 ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
-                p = wt.pool;
-                w = wt.workQueue;
-                p.helpJoinOnce(w, this); // no retries on failure
-            }
-            else if ((cp = ForkJoinPool.common) != null) {
-                if (this instanceof CountedCompleter)
-                    cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
-                else if (cp.tryExternalUnpush(this))
-                    doExec();
+                s = wt.pool.awaitJoin(wt.workQueue, this, deadline);
             }
-            boolean canBlock = false;
-            boolean interrupted = false;
-            try {
-                while ((s = status) >= 0) {
-                    if (w != null && w.qlock < 0)
-                        cancelIgnoringExceptions(this);
-                    else if (!canBlock) {
-                        if (p == null || p.tryCompensate(p.ctl))
-                            canBlock = true;
-                    }
-                    else {
-                        if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
-                            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                            synchronized (this) {
-                                if (status >= 0) {
-                                    try {
-                                        wait(ms);
-                                    } catch (InterruptedException ie) {
-                                        if (p == null)
-                                            interrupted = true;
-                                    }
-                                }
-                                else
-                                    notifyAll();
-                            }
+            else if ((s = ((this instanceof CountedCompleter) ?
+                           ForkJoinPool.common.externalHelpComplete(
+                               (CountedCompleter<?>)this, 0) :
+                           ForkJoinPool.common.tryExternalUnpush(this) ?
+                           doExec() : 0)) >= 0) {
+                long ns, ms; // measure in nanosecs, but wait in millisecs
+                while ((s = status) >= 0 &&
+                       (ns = deadline - System.nanoTime()) > 0L) {
+                    if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
+                        U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                        synchronized (this) {
+                            if (status >= 0)
+                                wait(ms); // OK to throw InterruptedException
+                            else
+                                notifyAll();
                         }
-                        if ((s = status) < 0 || interrupted ||
-                            (ns = deadline - System.nanoTime()) <= 0L)
-                            break;
                     }
                 }
-            } finally {
-                if (p != null && canBlock)
-                    p.incrementActiveCount();
             }
-            if (interrupted)
-                throw new InterruptedException();
         }
+        if (s >= 0)
+            s = status;
         if ((s &= DONE_MASK) != NORMAL) {
             Throwable ex;
             if (s == CANCELLED)
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 20:00:59 2017 +0200
@@ -66,7 +66,7 @@
      * owning thread.
      *
      * Support for (non-public) subclass InnocuousForkJoinWorkerThread
-     * requires that we break quite a lot of encapulation (via Unsafe)
+     * requires that we break quite a lot of encapsulation (via Unsafe)
      * both here and in the subclass to access and set Thread fields.
      */
 
@@ -118,7 +118,7 @@
      * @return the index number
      */
     public int getPoolIndex() {
-        return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
+        return workQueue.getPoolIndex();
     }
 
     /**
@@ -171,7 +171,7 @@
     }
 
     /**
-     * Erases ThreadLocals by nulling out Thread maps
+     * Erases ThreadLocals by nulling out Thread maps.
      */
     final void eraseThreadLocals() {
         U.putObject(this, THREADLOCALS, null);
@@ -246,8 +246,8 @@
 
         /**
          * Returns a new group with the system ThreadGroup (the
-         * topmost, parentless group) as parent.  Uses Unsafe to
-         * traverse Thread group and ThreadGroup parent fields.
+         * topmost, parent-less group) as parent.  Uses Unsafe to
+         * traverse Thread.group and ThreadGroup.parent fields.
          */
         private static ThreadGroup createThreadGroup() {
             try {
@@ -274,4 +274,3 @@
     }
 
 }
-
--- a/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java	Wed Jul 05 20:00:59 2017 +0200
@@ -29,38 +29,34 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.EnumMap;
-import java.util.List;
 
 public class ValueConversions {
     private static final Class<?> THIS_CLASS = ValueConversions.class;
-    // Do not adjust this except for special platforms:
-    private static final int MAX_ARITY;
-    static {
-        final Object[] values = { 255 };
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                @Override
-                public Void run() {
-                    values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
-                    return null;
-                }
-            });
-        MAX_ARITY = (Integer) values[0];
+    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+
+    /** Thread-safe canonicalized mapping from Wrapper to MethodHandle
+     * with unsynchronized reads and synchronized writes.
+     * It's safe to publish MethodHandles by data race because they are immutable. */
+    private static class WrapperCache {
+        /** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */
+        private final EnumMap<Wrapper, MethodHandle> map = new EnumMap<>(Wrapper.class);
+
+        public MethodHandle get(Wrapper w) {
+            return map.get(w);
+        }
+        public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
+            // Simulate CAS to avoid racy duplication
+            MethodHandle prev = map.putIfAbsent(w, mh);
+            if (prev != null)  return prev;
+            return mh;
+        }
     }
 
-    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
-
-    private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
-        @SuppressWarnings("unchecked")  // generic array creation
-        EnumMap<Wrapper, MethodHandle>[] caches
-                = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap<?,?>[n];
+    private static WrapperCache[] newWrapperCaches(int n) {
+        WrapperCache[] caches = new WrapperCache[n];
         for (int i = 0; i < n; i++)
-            caches[i] = new EnumMap<>(Wrapper.class);
+            caches[i] = new WrapperCache();
         return caches;
     }
 
@@ -71,63 +67,92 @@
     //   implicit conversions sanctioned by JLS 5.1.2, etc.
     //   explicit conversions as allowed by explicitCastArguments
 
+    static int unboxInteger(Integer x) {
+        return x;
+    }
     static int unboxInteger(Object x, boolean cast) {
         if (x instanceof Integer)
-            return ((Integer) x).intValue();
+            return (Integer) x;
         return primitiveConversion(Wrapper.INT, x, cast).intValue();
     }
 
+    static byte unboxByte(Byte x) {
+        return x;
+    }
     static byte unboxByte(Object x, boolean cast) {
         if (x instanceof Byte)
-            return ((Byte) x).byteValue();
+            return (Byte) x;
         return primitiveConversion(Wrapper.BYTE, x, cast).byteValue();
     }
 
+    static short unboxShort(Short x) {
+        return x;
+    }
     static short unboxShort(Object x, boolean cast) {
         if (x instanceof Short)
-            return ((Short) x).shortValue();
+            return (Short) x;
         return primitiveConversion(Wrapper.SHORT, x, cast).shortValue();
     }
 
+    static boolean unboxBoolean(Boolean x) {
+        return x;
+    }
     static boolean unboxBoolean(Object x, boolean cast) {
         if (x instanceof Boolean)
-            return ((Boolean) x).booleanValue();
+            return (Boolean) x;
         return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0;
     }
 
+    static char unboxCharacter(Character x) {
+        return x;
+    }
     static char unboxCharacter(Object x, boolean cast) {
         if (x instanceof Character)
-            return ((Character) x).charValue();
+            return (Character) x;
         return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue();
     }
 
+    static long unboxLong(Long x) {
+        return x;
+    }
     static long unboxLong(Object x, boolean cast) {
         if (x instanceof Long)
-            return ((Long) x).longValue();
+            return (Long) x;
         return primitiveConversion(Wrapper.LONG, x, cast).longValue();
     }
 
+    static float unboxFloat(Float x) {
+        return x;
+    }
     static float unboxFloat(Object x, boolean cast) {
         if (x instanceof Float)
-            return ((Float) x).floatValue();
+            return (Float) x;
         return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue();
     }
 
+    static double unboxDouble(Double x) {
+        return x;
+    }
     static double unboxDouble(Object x, boolean cast) {
         if (x instanceof Double)
-            return ((Double) x).doubleValue();
+            return (Double) x;
         return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
     }
 
-    private static MethodType unboxType(Wrapper wrap) {
+    private static MethodType unboxType(Wrapper wrap, int kind) {
+        if (kind == 0)
+            return MethodType.methodType(wrap.primitiveType(), wrap.wrapperType());
         return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
     }
 
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            UNBOX_CONVERSIONS = newWrapperCaches(2);
+    private static final WrapperCache[] UNBOX_CONVERSIONS = newWrapperCaches(4);
 
-    private static MethodHandle unbox(Wrapper wrap, boolean cast) {
-        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)];
+    private static MethodHandle unbox(Wrapper wrap, int kind) {
+        // kind 0 -> strongly typed with NPE
+        // kind 1 -> strongly typed but zero for null,
+        // kind 2 -> asType rules: accept multiple box types but only widening conversions with NPE
+        // kind 3 -> explicitCastArguments rules: allow narrowing conversions, zero for null
+        WrapperCache cache = UNBOX_CONVERSIONS[kind];
         MethodHandle mh = cache.get(wrap);
         if (mh != null) {
             return mh;
@@ -135,41 +160,59 @@
         // slow path
         switch (wrap) {
             case OBJECT:
-                mh = IDENTITY; break;
             case VOID:
-                mh = IGNORE; break;
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
+                throw new IllegalArgumentException("unbox "+wrap);
         }
         // look up the method
         String name = "unbox" + wrap.wrapperSimpleName();
-        MethodType type = unboxType(wrap);
+        MethodType type = unboxType(wrap, kind);
         try {
             mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
         } catch (ReflectiveOperationException ex) {
             mh = null;
         }
         if (mh != null) {
-            mh = MethodHandles.insertArguments(mh, 1, cast);
-            cache.put(wrap, mh);
-            return mh;
+            if (kind > 0) {
+                boolean cast = (kind != 2);
+                mh = MethodHandles.insertArguments(mh, 1, cast);
+            }
+            if (kind == 1) {  // casting but exact (null -> zero)
+                mh = mh.asType(unboxType(wrap, 0));
+            }
+            return cache.put(wrap, mh);
         }
         throw new IllegalArgumentException("cannot find unbox adapter for " + wrap
-                + (cast ? " (cast)" : ""));
+                + (kind <= 1 ? " (exact)" : kind == 3 ? " (cast)" : ""));
+    }
+
+    /** Return an exact unboxer for the given primitive type. */
+    public static MethodHandle unboxExact(Wrapper type) {
+        return unbox(type, 0);
     }
 
-    public static MethodHandle unboxCast(Wrapper type) {
-        return unbox(type, true);
+    /** Return an exact unboxer for the given primitive type, with optional null-to-zero conversion.
+     *  The boolean says whether to throw an NPE on a null value (false means unbox a zero).
+     *  The type of the unboxer is of a form like (Integer)int.
+     */
+    public static MethodHandle unboxExact(Wrapper type, boolean throwNPE) {
+        return unbox(type, throwNPE ? 0 : 1);
     }
 
-    public static MethodHandle unbox(Class<?> type) {
-        return unbox(Wrapper.forPrimitiveType(type), false);
+    /** Return a widening unboxer for the given primitive type.
+     *  Widen narrower primitive boxes to the given type.
+     *  Do not narrow any primitive values or convert null to zero.
+     *  The type of the unboxer is of a form like (Object)int.
+     */
+    public static MethodHandle unboxWiden(Wrapper type) {
+        return unbox(type, 2);
     }
 
-    public static MethodHandle unboxCast(Class<?> type) {
-        return unbox(Wrapper.forPrimitiveType(type), true);
+    /** Return a casting unboxer for the given primitive type.
+     *  Widen or narrow primitive values to the given type, or convert null to zero, as needed.
+     *  The type of the unboxer is of a form like (Object)int.
+     */
+    public static MethodHandle unboxCast(Wrapper type) {
+        return unbox(type, 3);
     }
 
     static private final Integer ZERO_INT = 0, ONE_INT = 1;
@@ -266,57 +309,26 @@
         return MethodType.methodType(boxType, wrap.primitiveType());
     }
 
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            BOX_CONVERSIONS = newWrapperCaches(2);
+    private static final WrapperCache[] BOX_CONVERSIONS = newWrapperCaches(1);
 
-    private static MethodHandle box(Wrapper wrap, boolean exact) {
-        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)];
+    public static MethodHandle boxExact(Wrapper wrap) {
+        WrapperCache cache = BOX_CONVERSIONS[0];
         MethodHandle mh = cache.get(wrap);
         if (mh != null) {
             return mh;
         }
-        // slow path
-        switch (wrap) {
-            case OBJECT:
-                mh = IDENTITY; break;
-            case VOID:
-                mh = ZERO_OBJECT;
-                break;
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
         // look up the method
         String name = "box" + wrap.wrapperSimpleName();
         MethodType type = boxType(wrap);
-        if (exact) {
-            try {
-                mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
-            } catch (ReflectiveOperationException ex) {
-                mh = null;
-            }
-        } else {
-            mh = box(wrap, !exact).asType(type.erase());
+        try {
+            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
+        } catch (ReflectiveOperationException ex) {
+            mh = null;
         }
         if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
+            return cache.put(wrap, mh);
         }
-        throw new IllegalArgumentException("cannot find box adapter for "
-                + wrap + (exact ? " (exact)" : ""));
-    }
-
-    public static MethodHandle box(Class<?> type) {
-        boolean exact = false;
-        // e.g., boxShort(short)Short if exact,
-        // e.g., boxShort(short)Object if !exact
-        return box(Wrapper.forPrimitiveType(type), exact);
-    }
-
-    public static MethodHandle box(Wrapper type) {
-        boolean exact = false;
-        return box(type, exact);
+        throw new IllegalArgumentException("cannot find box adapter for " + wrap);
     }
 
     /// Constant functions
@@ -348,11 +360,10 @@
         return 0;
     }
 
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            CONSTANT_FUNCTIONS = newWrapperCaches(2);
+    private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2);
 
     public static MethodHandle zeroConstantFunction(Wrapper wrap) {
-        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
+        WrapperCache cache = CONSTANT_FUNCTIONS[0];
         MethodHandle mh = cache.get(wrap);
         if (mh != null) {
             return mh;
@@ -373,184 +384,37 @@
                 break;
         }
         if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
+            return cache.put(wrap, mh);
         }
 
         // use zeroInt and cast the result
         if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
             mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
-            cache.put(wrap, mh);
-            return mh;
+            return cache.put(wrap, mh);
         }
         throw new IllegalArgumentException("cannot find zero constant for " + wrap);
     }
 
-    /// Converting references to references.
-
-    /**
-     * Identity function.
-     * @param x an arbitrary reference value
-     * @return the same value x
-     */
-    static <T> T identity(T x) {
-        return x;
-    }
-
-    static <T> T[] identity(T[] x) {
-        return x;
-    }
-
-    /**
-     * Identity function on ints.
-     * @param x an arbitrary int value
-     * @return the same value x
-     */
-    static int identity(int x) {
-        return x;
-    }
-
-    static byte identity(byte x) {
-        return x;
-    }
-
-    static short identity(short x) {
-        return x;
-    }
-
-    static boolean identity(boolean x) {
-        return x;
-    }
-
-    static char identity(char x) {
-        return x;
-    }
-
-    /**
-     * Identity function on longs.
-     * @param x an arbitrary long value
-     * @return the same value x
-     */
-    static long identity(long x) {
-        return x;
-    }
-
-    static float identity(float x) {
-        return x;
-    }
-
-    static double identity(double x) {
-        return x;
-    }
-
-    private static ClassCastException newClassCastException(Class<?> t, Object obj) {
-        return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
-    }
-
-    private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
-            ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
+    private static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY;
     static {
         try {
             MethodType idType = MethodType.genericMethodType(1);
             MethodType ignoreType = idType.changeReturnType(void.class);
-            MethodType zeroObjectType = MethodType.genericMethodType(0);
-            IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
             CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
-            ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
             IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
             EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
-            ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
-            FILL_NEW_ARRAY = IMPL_LOOKUP
-                    .findStatic(THIS_CLASS, "fillNewArray",
-                          MethodType.methodType(Object[].class, Integer.class, Object[].class));
-            FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
-                    .findStatic(THIS_CLASS, "fillNewTypedArray",
-                          MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
         } catch (NoSuchMethodException | IllegalAccessException ex) {
             throw newInternalError("uncaught exception", ex);
         }
     }
 
-    // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
-    static class LazyStatics {
-        private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
-        static {
-            try {
-                //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
-                COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
-                COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
-                MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
-            } catch (ReflectiveOperationException ex) {
-                throw newInternalError("uncaught exception", ex);
-            }
-        }
+    public static MethodHandle ignore() {
+        return IGNORE;
     }
 
-    private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
-            = newWrapperCaches(1);
-
-    /** Return a method that casts its sole argument (an Object) to the given type
-     *  and returns it as the given type.
-     */
-    public static MethodHandle cast(Class<?> type) {
-        return cast(type, CAST_REFERENCE);
-    }
-    public static MethodHandle cast(Class<?> type, MethodHandle castReference) {
-        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
-        MethodHandle mh;
-        Wrapper wrap = null;
-        EnumMap<Wrapper, MethodHandle> cache = null;
-        if (Wrapper.isWrapperType(type)) {
-            wrap = Wrapper.forWrapperType(type);
-            cache = WRAPPER_CASTS[0];
-            mh = cache.get(wrap);
-            if (mh != null)  return mh;
-        }
-        mh = MethodHandles.insertArguments(castReference, 0, type);
-        if (cache != null)
-            cache.put(wrap, mh);
-        return mh;
-    }
-
-    public static MethodHandle identity() {
-        return IDENTITY;
-    }
-
-    public static MethodHandle identity(Class<?> type) {
-        if (!type.isPrimitive())
-            // Reference identity has been moved into MethodHandles:
-            return MethodHandles.identity(type);
-        return identity(Wrapper.findPrimitiveType(type));
-    }
-
-    public static MethodHandle identity(Wrapper wrap) {
-        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
-        MethodHandle mh = cache.get(wrap);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        MethodType type = MethodType.methodType(wrap.primitiveType());
-        if (wrap != Wrapper.VOID)
-            type = type.appendParameterTypes(wrap.primitiveType());
-        try {
-            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
-        } catch (ReflectiveOperationException ex) {
-            mh = null;
-        }
-        if (mh == null && wrap == Wrapper.VOID) {
-            mh = EMPTY;  // #(){} : #()void
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find identity for " + wrap);
+    /** Return a method that casts its second argument (an Object) to the given type (a Class). */
+    public static MethodHandle cast() {
+        return CAST_REFERENCE;
     }
 
     /// Primitive conversions.
@@ -759,11 +623,10 @@
         return (x ? (byte)1 : (byte)0);
     }
 
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
+    private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
 
     public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
-        EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
+        WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
         MethodHandle mh = cache.get(wdst);
         if (mh != null) {
             return mh;
@@ -771,17 +634,9 @@
         // slow path
         Class<?> src = wsrc.primitiveType();
         Class<?> dst = wdst.primitiveType();
-        MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
+        MethodType type = MethodType.methodType(dst, src);
         if (wsrc == wdst) {
-            mh = identity(src);
-        } else if (wsrc == Wrapper.VOID) {
-            mh = zeroConstantFunction(wdst);
-        } else if (wdst == Wrapper.VOID) {
-            mh = MethodHandles.dropArguments(EMPTY, 0, src);  // Defer back to MethodHandles.
-        } else if (wsrc == Wrapper.OBJECT) {
-            mh = unboxCast(dst);
-        } else if (wdst == Wrapper.OBJECT) {
-            mh = box(src);
+            mh = MethodHandles.identity(src);
         } else {
             assert(src.isPrimitive() && dst.isPrimitive());
             try {
@@ -792,8 +647,7 @@
         }
         if (mh != null) {
             assert(mh.type() == type) : mh;
-            cache.put(wdst, mh);
-            return mh;
+            return cache.put(wdst, mh);
         }
 
         throw new IllegalArgumentException("cannot find primitive conversion function for " +
@@ -808,363 +662,6 @@
         return Character.toUpperCase(x.charAt(0))+x.substring(1);
     }
 
-    /// Collection of multiple arguments.
-
-    public static Object convertArrayElements(Class<?> arrayType, Object array) {
-        Class<?> src = array.getClass().getComponentType();
-        Class<?> dst = arrayType.getComponentType();
-        if (src == null || dst == null)  throw new IllegalArgumentException("not array type");
-        Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
-        Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
-        int length;
-        if (sw == null) {
-            Object[] a = (Object[]) array;
-            length = a.length;
-            if (dw == null)
-                return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
-            Object res = dw.makeArray(length);
-            dw.copyArrayUnboxing(a, 0, res, 0, length);
-            return res;
-        }
-        length = java.lang.reflect.Array.getLength(array);
-        Object[] res;
-        if (dw == null) {
-            res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
-        } else {
-            res = new Object[length];
-        }
-        sw.copyArrayBoxing(array, 0, res, 0, length);
-        if (dw == null)  return res;
-        Object a = dw.makeArray(length);
-        dw.copyArrayUnboxing(res, 0, a, 0, length);
-        return a;
-    }
-
-    private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
-        MethodType type = MethodType.genericMethodType(nargs)
-                .changeReturnType(rtype)
-                .insertParameterTypes(0, ptypes);
-        try {
-            return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
-        } catch (ReflectiveOperationException ex) {
-            return null;
-        }
-    }
-
-    private static final Object[] NO_ARGS_ARRAY = {};
-    private static Object[] makeArray(Object... args) { return args; }
-    private static Object[] array() { return NO_ARGS_ARRAY; }
-    private static Object[] array(Object a0)
-                { return makeArray(a0); }
-    private static Object[] array(Object a0, Object a1)
-                { return makeArray(a0, a1); }
-    private static Object[] array(Object a0, Object a1, Object a2)
-                { return makeArray(a0, a1, a2); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
-                { return makeArray(a0, a1, a2, a3); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4)
-                { return makeArray(a0, a1, a2, a3, a4); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5)
-                { return makeArray(a0, a1, a2, a3, a4, a5); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6)
-                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7)
-                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7,
-                                  Object a8)
-                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7,
-                                  Object a8, Object a9)
-                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-    private static MethodHandle[] makeArrays() {
-        ArrayList<MethodHandle> mhs = new ArrayList<>();
-        for (;;) {
-            MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
-            if (mh == null)  break;
-            mhs.add(mh);
-        }
-        assert(mhs.size() == 11);  // current number of methods
-        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
-    }
-    private static final MethodHandle[] ARRAYS = makeArrays();
-
-    // filling versions of the above:
-    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
-    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
-        Object[] a = new Object[len];
-        fillWithArguments(a, 0, args);
-        return a;
-    }
-    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
-        Object[] a = Arrays.copyOf(example, len);
-        fillWithArguments(a, 0, args);
-        return a;
-    }
-    private static void fillWithArguments(Object[] a, int pos, Object... args) {
-        System.arraycopy(args, 0, a, pos, args.length);
-    }
-    // using Integer pos instead of int pos to avoid bootstrapping problems
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
-                { fillWithArguments(a, pos, a0); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
-                { fillWithArguments(a, pos, a0, a1); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
-                { fillWithArguments(a, pos, a0, a1, a2); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
-                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7,
-                                  Object a8)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
-    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
-                                  Object a4, Object a5, Object a6, Object a7,
-                                  Object a8, Object a9)
-                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
-    private static MethodHandle[] makeFillArrays() {
-        ArrayList<MethodHandle> mhs = new ArrayList<>();
-        mhs.add(null);  // there is no empty fill; at least a0 is required
-        for (;;) {
-            MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
-            if (mh == null)  break;
-            mhs.add(mh);
-        }
-        assert(mhs.size() == 11);  // current number of methods
-        return mhs.toArray(new MethodHandle[0]);
-    }
-    private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
-
-    private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
-        return Arrays.copyOf(a, a.length, arrayType);
-    }
-    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
-        Object a = w.makeArray(boxes.length);
-        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
-        return a;
-    }
-
-    /** Return a method handle that takes the indicated number of Object
-     *  arguments and returns an Object array of them, as if for varargs.
-     */
-    public static MethodHandle varargsArray(int nargs) {
-        MethodHandle mh = ARRAYS[nargs];
-        if (mh != null)  return mh;
-        mh = findCollector("array", nargs, Object[].class);
-        if (mh != null)  return ARRAYS[nargs] = mh;
-        mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
-        assert(assertCorrectArity(mh, nargs));
-        return ARRAYS[nargs] = mh;
-    }
-
-    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
-        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
-        return true;
-    }
-
-    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
-        // Build up the result mh as a sequence of fills like this:
-        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
-        // The various fill(_,10*I,___*[J]) are reusable.
-        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
-        int rightLen = nargs - leftLen;
-        MethodHandle leftCollector = newArray.bindTo(nargs);
-        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
-        MethodHandle mh = finisher;
-        if (rightLen > 0) {
-            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
-            if (mh == ARRAY_IDENTITY)
-                mh = rightFiller;
-            else
-                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
-        }
-        if (mh == ARRAY_IDENTITY)
-            mh = leftCollector;
-        else
-            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
-        return mh;
-    }
-
-    private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
-    private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
-    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
-     *  fills a[L]..a[N-1] with corresponding arguments,
-     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
-     */
-    private static MethodHandle fillToRight(int nargs) {
-        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
-        if (filler != null)  return filler;
-        filler = buildFiller(nargs);
-        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
-        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
-    }
-    private static MethodHandle buildFiller(int nargs) {
-        if (nargs <= LEFT_ARGS)
-            return ARRAY_IDENTITY;  // no args to fill; return the array unchanged
-        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
-        final int CHUNK = LEFT_ARGS;
-        int rightLen = nargs % CHUNK;
-        int midLen = nargs - rightLen;
-        if (rightLen == 0) {
-            midLen = nargs - (rightLen = CHUNK);
-            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
-                // build some precursors from left to right
-                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
-                    if (j > LEFT_ARGS)  fillToRight(j);
-            }
-        }
-        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
-        assert(rightLen > 0);
-        MethodHandle midFill = fillToRight(midLen);  // recursive fill
-        MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
-        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
-        assert(rightFill.type().parameterCount() == 1 + rightLen);
-
-        // Combine the two fills:
-        //   right(mid(a, x10..x19), x20..x23)
-        // The final product will look like this:
-        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
-        if (midLen == LEFT_ARGS)
-            return rightFill;
-        else
-            return MethodHandles.collectArguments(rightFill, 0, midFill);
-    }
-
-    // Type-polymorphic version of varargs maker.
-    private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
-        = new ClassValue<MethodHandle[]>() {
-            @Override
-            protected MethodHandle[] computeValue(Class<?> type) {
-                return new MethodHandle[256];
-            }
-    };
-
-    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
-
-    /** Return a method handle that takes the indicated number of
-     *  typed arguments and returns an array of them.
-     *  The type argument is the array type.
-     */
-    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
-        Class<?> elemType = arrayType.getComponentType();
-        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
-        // FIXME: Need more special casing and caching here.
-        if (nargs >= MAX_JVM_ARITY/2 - 1) {
-            int slots = nargs;
-            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
-            if (arrayType == double[].class || arrayType == long[].class)
-                slots *= 2;
-            if (slots > MAX_ARRAY_SLOTS)
-                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
-        }
-        if (elemType == Object.class)
-            return varargsArray(nargs);
-        // other cases:  primitive arrays, subtypes of Object[]
-        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
-        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
-        if (mh != null)  return mh;
-        if (elemType.isPrimitive()) {
-            MethodHandle builder = FILL_NEW_ARRAY;
-            MethodHandle producer = buildArrayProducer(arrayType);
-            mh = buildVarargsArray(builder, producer, nargs);
-        } else {
-            @SuppressWarnings("unchecked")
-            Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
-            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
-            MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
-            MethodHandle producer = ARRAY_IDENTITY;
-            mh = buildVarargsArray(builder, producer, nargs);
-        }
-        mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
-        assert(assertCorrectArity(mh, nargs));
-        if (nargs < cache.length)
-            cache[nargs] = mh;
-        return mh;
-    }
-
-    private static MethodHandle buildArrayProducer(Class<?> arrayType) {
-        Class<?> elemType = arrayType.getComponentType();
-        if (elemType.isPrimitive())
-            return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
-        else
-            return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
-    }
-
-    // List version of varargs maker.
-
-    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
-    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
-    private static List<Object> list() { return NO_ARGS_LIST; }
-    private static List<Object> list(Object a0)
-                { return makeList(a0); }
-    private static List<Object> list(Object a0, Object a1)
-                { return makeList(a0, a1); }
-    private static List<Object> list(Object a0, Object a1, Object a2)
-                { return makeList(a0, a1, a2); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
-                { return makeList(a0, a1, a2, a3); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4)
-                { return makeList(a0, a1, a2, a3, a4); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4, Object a5)
-                { return makeList(a0, a1, a2, a3, a4, a5); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4, Object a5, Object a6)
-                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4, Object a5, Object a6, Object a7)
-                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4, Object a5, Object a6, Object a7,
-                                     Object a8)
-                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
-                                     Object a4, Object a5, Object a6, Object a7,
-                                     Object a8, Object a9)
-                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-    private static MethodHandle[] makeLists() {
-        ArrayList<MethodHandle> mhs = new ArrayList<>();
-        for (;;) {
-            MethodHandle mh = findCollector("list", mhs.size(), List.class);
-            if (mh == null)  break;
-            mhs.add(mh);
-        }
-        assert(mhs.size() == 11);  // current number of methods
-        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
-    }
-    private static final MethodHandle[] LISTS = makeLists();
-
-    /** Return a method handle that takes the indicated number of Object
-     *  arguments and returns a List.
-     */
-    public static MethodHandle varargsList(int nargs) {
-        MethodHandle mh = LISTS[nargs];
-        if (mh != null)  return mh;
-        mh = findCollector("list", nargs, List.class);
-        if (mh != null)  return LISTS[nargs] = mh;
-        return LISTS[nargs] = buildVarargsList(nargs);
-    }
-    private static MethodHandle buildVarargsList(int nargs) {
-        return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
-    }
-
     // handy shared exception makers (they simplify the common case code)
     private static InternalError newInternalError(String message, Throwable cause) {
         return new InternalError(message, cause);
--- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java	Wed Jul 05 20:00:59 2017 +0200
@@ -40,18 +40,38 @@
     /**
      * True if a value can be stacked as the source type and unstacked as the
      * destination type, without violating the JVM's type consistency.
+     * <p>
+     * If both types are references, we apply the verifier's subclass check
+     * (or subtyping, if keepInterfaces).
+     * If the src type is a type guaranteed to be null (Void) it can be converted
+     * to any other reference type.
+     * <p>
+     * If both types are primitives, we apply the verifier's primitive conversions.
+     * These do not include Java conversions such as long to double, since those
+     * require computation and (in general) stack depth changes.
+     * But very simple 32-bit viewing changes, such as byte to int,
+     * are null conversions, because they do not require any computation.
+     * These conversions are from any type to a wider type up to 32 bits,
+     * as long as the conversion is not signed to unsigned (byte to char).
+     * <p>
+     * The primitive type 'void' does not interconvert with any other type,
+     * even though it is legal to drop any type from the stack and "return void".
+     * The stack effects, though are different between void and any other type,
+     * so it is safer to report a non-trivial conversion.
      *
      * @param src the type of a stacked value
      * @param dst the type by which we'd like to treat it
+     * @param keepInterfaces if false, we treat any interface as if it were Object
      * @return whether the retyping can be done without motion or reformatting
      */
-    public static boolean isNullConversion(Class<?> src, Class<?> dst) {
+    public static boolean isNullConversion(Class<?> src, Class<?> dst, boolean keepInterfaces) {
         if (src == dst)            return true;
         // Verifier allows any interface to be treated as Object:
-        if (dst.isInterface())     dst = Object.class;
-        if (src.isInterface())     src = Object.class;
-        if (src == dst)            return true;  // check again
-        if (dst == void.class)     return true;  // drop any return value
+        if (!keepInterfaces) {
+            if (dst.isInterface())  dst = Object.class;
+            if (src.isInterface())  src = Object.class;
+            if (src == dst)         return true;  // check again
+        }
         if (isNullType(src))       return !dst.isPrimitive();
         if (!src.isPrimitive())    return dst.isAssignableFrom(src);
         if (!dst.isPrimitive())    return false;
@@ -82,25 +102,13 @@
      * Is the given type java.lang.Null or an equivalent null-only type?
      */
     public static boolean isNullType(Class<?> type) {
-        if (type == null)  return false;
-        return type == NULL_CLASS
-            // This one may also be used as a null type.
-            // TO DO: Decide if we really want to legitimize it here.
-            // Probably we do, unless java.lang.Null really makes it into Java 7
-            //|| type == Void.class
-            // Locally known null-only class:
-            || type == Empty.class
-            ;
-    }
-    private static final Class<?> NULL_CLASS;
-    static {
-        Class<?> nullClass = null;
-        try {
-            nullClass = Class.forName("java.lang.Null");
-        } catch (ClassNotFoundException ex) {
-            // OK, we'll cope
-        }
-        NULL_CLASS = nullClass;
+        // Any reference statically typed as Void is guaranteed to be null.
+        // Therefore, it can be safely treated as a value of any
+        // other type that admits null, i.e., a reference type.
+        if (type == Void.class)  return true;
+        // Locally known null-only class:
+        if (type == Empty.class)  return true;
+        return false;
     }
 
     /**
@@ -111,14 +119,14 @@
      * @param recv the type of the method handle receiving the call
      * @return whether the retyping can be done without motion or reformatting
      */
-    public static boolean isNullConversion(MethodType call, MethodType recv) {
+    public static boolean isNullConversion(MethodType call, MethodType recv, boolean keepInterfaces) {
         if (call == recv)  return true;
         int len = call.parameterCount();
         if (len != recv.parameterCount())  return false;
         for (int i = 0; i < len; i++)
-            if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
+            if (!isNullConversion(call.parameterType(i), recv.parameterType(i), keepInterfaces))
                 return false;
-        return isNullConversion(recv.returnType(), call.returnType());
+        return isNullConversion(recv.returnType(), call.returnType(), keepInterfaces);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java	Wed Jul 05 20:00:59 2017 +0200
@@ -230,14 +230,6 @@
      */
     public <T> T zero(Class<T> type) { return convert(zero, type); }
 
-//    /** Produce a wrapper for the given wrapper or primitive type. */
-//    public static Wrapper valueOf(Class<?> type) {
-//        if (isPrimitiveType(type))
-//            return forPrimitiveType(type);
-//        else
-//            return forWrapperType(type);
-//    }
-
     /** Return the wrapper that wraps values of the given type.
      *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
      *  Otherwise, the type must be a primitive.
--- a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -69,33 +69,34 @@
     protected short codeIdx;
     protected short exceptionsIdx;
     // Boxing
+    protected short valueOfIdx;
     protected short booleanIdx;
-    protected short booleanCtorIdx;
+    protected short booleanBoxIdx;
     protected short booleanUnboxIdx;
     protected short byteIdx;
-    protected short byteCtorIdx;
+    protected short byteBoxIdx;
     protected short byteUnboxIdx;
     protected short characterIdx;
-    protected short characterCtorIdx;
+    protected short characterBoxIdx;
     protected short characterUnboxIdx;
     protected short doubleIdx;
-    protected short doubleCtorIdx;
+    protected short doubleBoxIdx;
     protected short doubleUnboxIdx;
     protected short floatIdx;
-    protected short floatCtorIdx;
+    protected short floatBoxIdx;
     protected short floatUnboxIdx;
     protected short integerIdx;
-    protected short integerCtorIdx;
+    protected short integerBoxIdx;
     protected short integerUnboxIdx;
     protected short longIdx;
-    protected short longCtorIdx;
+    protected short longBoxIdx;
     protected short longUnboxIdx;
     protected short shortIdx;
-    protected short shortCtorIdx;
+    protected short shortBoxIdx;
     protected short shortUnboxIdx;
 
     protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;
-    protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 72;
+    protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 73;
 
     // Requires that superClass has been set up
     protected void emitCommonConstantPoolEntries() {
@@ -181,9 +182,10 @@
     /** Constant pool entries required to be able to box/unbox primitive
         types. Note that we don't emit these if we don't need them. */
     protected void emitBoxingContantPoolEntries() {
+        //  *  [UTF-8] "valueOf"
         //  *  [UTF-8] "java/lang/Boolean"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(Z)V"
+        //  *  [UTF-8] "(Z)Ljava/lang/Boolean;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "booleanValue"
@@ -192,7 +194,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Byte"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(B)V"
+        //  *  [UTF-8] "(B)Ljava/lang/Byte;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "byteValue"
@@ -201,7 +203,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Character"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(C)V"
+        //  *  [UTF-8] "(C)Ljava/lang/Character;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "charValue"
@@ -210,7 +212,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Double"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(D)V"
+        //  *  [UTF-8] "(D)Ljava/lang/Double;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "doubleValue"
@@ -219,7 +221,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Float"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(F)V"
+        //  *  [UTF-8] "(F)Ljava/lang/Float;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "floatValue"
@@ -228,7 +230,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Integer"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(I)V"
+        //  *  [UTF-8] "(I)Ljava/lang/Integer;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "intValue"
@@ -237,7 +239,7 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Long"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(J)V"
+        //  *  [UTF-8] "(J)Ljava/lang/Long;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "longValue"
@@ -246,21 +248,26 @@
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "java/lang/Short"
         //  *  [CONSTANT_Class_info] for above
-        //  *  [UTF-8] "(S)V"
+        //  *  [UTF-8] "(S)Ljava/lang/Short;"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
         //  *  [UTF-8] "shortValue"
         //  *  [UTF-8] "()S"
         //  *  [CONSTANT_NameAndType_info] for above
         //  *  [CONSTANT_Methodref_info] for above
+
+        // valueOf-method name
+        asm.emitConstantPoolUTF8("valueOf");
+        valueOfIdx = asm.cpi();
+
         // Boolean
         asm.emitConstantPoolUTF8("java/lang/Boolean");
         asm.emitConstantPoolClass(asm.cpi());
         booleanIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(Z)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(Z)Ljava/lang/Boolean;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        booleanCtorIdx = asm.cpi();
+        booleanBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("booleanValue");
         asm.emitConstantPoolUTF8("()Z");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -271,10 +278,10 @@
         asm.emitConstantPoolUTF8("java/lang/Byte");
         asm.emitConstantPoolClass(asm.cpi());
         byteIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(B)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(B)Ljava/lang/Byte;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        byteCtorIdx = asm.cpi();
+        byteBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("byteValue");
         asm.emitConstantPoolUTF8("()B");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -285,10 +292,10 @@
         asm.emitConstantPoolUTF8("java/lang/Character");
         asm.emitConstantPoolClass(asm.cpi());
         characterIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(C)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(C)Ljava/lang/Character;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        characterCtorIdx = asm.cpi();
+        characterBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("charValue");
         asm.emitConstantPoolUTF8("()C");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -299,10 +306,10 @@
         asm.emitConstantPoolUTF8("java/lang/Double");
         asm.emitConstantPoolClass(asm.cpi());
         doubleIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(D)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(D)Ljava/lang/Double;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        doubleCtorIdx = asm.cpi();
+        doubleBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("doubleValue");
         asm.emitConstantPoolUTF8("()D");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -313,10 +320,10 @@
         asm.emitConstantPoolUTF8("java/lang/Float");
         asm.emitConstantPoolClass(asm.cpi());
         floatIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(F)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(F)Ljava/lang/Float;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        floatCtorIdx = asm.cpi();
+        floatBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("floatValue");
         asm.emitConstantPoolUTF8("()F");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -327,10 +334,10 @@
         asm.emitConstantPoolUTF8("java/lang/Integer");
         asm.emitConstantPoolClass(asm.cpi());
         integerIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(I)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(I)Ljava/lang/Integer;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        integerCtorIdx = asm.cpi();
+        integerBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("intValue");
         asm.emitConstantPoolUTF8("()I");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -341,10 +348,10 @@
         asm.emitConstantPoolUTF8("java/lang/Long");
         asm.emitConstantPoolClass(asm.cpi());
         longIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(J)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(J)Ljava/lang/Long;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        longCtorIdx = asm.cpi();
+        longBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("longValue");
         asm.emitConstantPoolUTF8("()J");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -355,10 +362,10 @@
         asm.emitConstantPoolUTF8("java/lang/Short");
         asm.emitConstantPoolClass(asm.cpi());
         shortIdx = asm.cpi();
-        asm.emitConstantPoolUTF8("(S)V");
-        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolUTF8("(S)Ljava/lang/Short;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
-        shortCtorIdx = asm.cpi();
+        shortBoxIdx = asm.cpi();
         asm.emitConstantPoolUTF8("shortValue");
         asm.emitConstantPoolUTF8("()S");
         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
@@ -515,23 +522,23 @@
         throw new InternalError("Should have found primitive type");
     }
 
-    protected short ctorIndexForPrimitiveType(Class<?> type) {
+    protected short boxingMethodForPrimitiveType(Class<?> type) {
         if (type == Boolean.TYPE) {
-            return booleanCtorIdx;
+            return booleanBoxIdx;
         } else if (type == Byte.TYPE) {
-            return byteCtorIdx;
+            return byteBoxIdx;
         } else if (type == Character.TYPE) {
-            return characterCtorIdx;
+            return characterBoxIdx;
         } else if (type == Double.TYPE) {
-            return doubleCtorIdx;
+            return doubleBoxIdx;
         } else if (type == Float.TYPE) {
-            return floatCtorIdx;
+            return floatBoxIdx;
         } else if (type == Integer.TYPE) {
-            return integerCtorIdx;
+            return integerBoxIdx;
         } else if (type == Long.TYPE) {
-            return longCtorIdx;
+            return longBoxIdx;
         } else if (type == Short.TYPE) {
-            return shortCtorIdx;
+            return shortBoxIdx;
         }
         throw new InternalError("Should have found primitive type");
     }
--- a/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -660,9 +660,9 @@
         if (!isConstructor) {
             // Box return value if necessary
             if (isPrimitive(returnType)) {
-                cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType),
-                                     typeSizeInStackSlots(returnType),
-                                     0);
+                cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType),
+                                    typeSizeInStackSlots(returnType),
+                                    0);
             } else if (returnType == Void.TYPE) {
                 cb.opc_aconst_null();
             }
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Boolean(getBoolean(obj));
+        return Boolean.valueOf(getBoolean(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Byte(getByte(obj));
+        return Byte.valueOf(getByte(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Character(getChar(obj));
+        return Character.valueOf(getChar(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Double(getDouble(obj));
+        return Double.valueOf(getDouble(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Float(getFloat(obj));
+        return Float.valueOf(getFloat(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Integer(getInt(obj));
+        return Integer.valueOf(getInt(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Long(getLong(obj));
+        return Long.valueOf(getLong(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Boolean(getBoolean(obj));
+        return Boolean.valueOf(getBoolean(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Byte(getByte(obj));
+        return Byte.valueOf(getByte(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Character(getChar(obj));
+        return Character.valueOf(getChar(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Double(getDouble(obj));
+        return Double.valueOf(getDouble(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Float(getFloat(obj));
+        return Float.valueOf(getFloat(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Integer(getInt(obj));
+        return Integer.valueOf(getInt(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Long(getLong(obj));
+        return Long.valueOf(getLong(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Short(getShort(obj));
+        return Short.valueOf(getShort(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Boolean(getBoolean(obj));
+        return Boolean.valueOf(getBoolean(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Byte(getByte(obj));
+        return Byte.valueOf(getByte(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Character(getChar(obj));
+        return Character.valueOf(getChar(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Double(getDouble(obj));
+        return Double.valueOf(getDouble(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Float(getFloat(obj));
+        return Float.valueOf(getFloat(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Integer(getInt(obj));
+        return Integer.valueOf(getInt(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Long(getLong(obj));
+        return Long.valueOf(getLong(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,7 +35,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Short(getShort(obj));
+        return Short.valueOf(getShort(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Short(getShort(obj));
+        return Short.valueOf(getShort(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Boolean(getBoolean(obj));
+        return Boolean.valueOf(getBoolean(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Byte(getByte(obj));
+        return Byte.valueOf(getByte(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Character(getChar(obj));
+        return Character.valueOf(getChar(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Double(getDouble(obj));
+        return Double.valueOf(getDouble(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Float(getFloat(obj));
+        return Float.valueOf(getFloat(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Integer(getInt(obj));
+        return Integer.valueOf(getInt(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Long(getLong(obj));
+        return Long.valueOf(getLong(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,7 +33,7 @@
     }
 
     public Object get(Object obj) throws IllegalArgumentException {
-        return new Short(getShort(obj));
+        return Short.valueOf(getShort(obj));
     }
 
     public boolean getBoolean(Object obj) throws IllegalArgumentException {
--- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java	Wed Jul 05 20:00:59 2017 +0200
@@ -615,7 +615,9 @@
                 //                 startTime=86400000   <= 24 hours
                 // This:           startDayOfWeek=6
                 //                 startTime=0
-                // Below is the workaround, it probably slows down everyone a little
+                // Similar workaround needs to be applied to Africa/Cairo and
+                // its endDayOfWeek and endTime
+                // Below is the workarounds, it probably slows down everyone a little
                 if (params[2] == 6 && params[3] == 0 &&
                     (zoneId.equals("Asia/Amman") ||
                      zoneId.equals("Asia/Gaza") ||
@@ -623,6 +625,13 @@
                     params[2] = 5;
                     params[3] = 86400000;
                 }
+                //endDayOfWeek and endTime workaround
+                if (params[7] == 6 && params[8] == 0 &&
+                    (zoneId.equals("Africa/Cairo"))) {
+                    params[7] = 5;
+                    params[8] = 86400000;
+                }
+
             } else if (nTrans > 0) {  // only do this if there is something in table already
                 if (lastyear < LASTYEAR) {
                     // ZoneInfo has an ending entry for 2037
--- a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java	Wed Jul 05 20:00:59 2017 +0200
@@ -47,9 +47,9 @@
         String ACT[] = new String[] {"Acre Time", "ACT",
                                      "Acre Summer Time", "ACST",
                                      "Acre Time", "ACT"};
-        String ADELAIDE[] = new String[] {"Central Standard Time (South Australia)", "CST",
-                                          "Central Summer Time (South Australia)", "CST",
-                                          "Central Time (South Australia)", "CT"};
+        String ADELAIDE[] = new String[] {"Australian Central Standard Time (South Australia)", "ACST",
+                                          "Australian Central Daylight Time (South Australia)", "ACDT",
+                                          "Australian Central Time (South Australia)", "ACT"};
         String AGT[] = new String[] {"Argentine Time", "ART",
                                      "Argentine Summer Time", "ARST",
                                      "Argentine Time", "ART"};
@@ -71,12 +71,12 @@
         String BDT[] = new String[] {"Bangladesh Time", "BDT",
                                      "Bangladesh Summer Time", "BDST",
                                      "Bangladesh Time", "BDT"};
-        String BRISBANE[] = new String[] {"Eastern Standard Time (Queensland)", "EST",
-                                          "Eastern Summer Time (Queensland)", "EST",
-                                          "Eastern Time (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Central Standard Time (South Australia/New South Wales)", "CST",
-                                             "Central Summer Time (South Australia/New South Wales)", "CST",
-                                             "Central Time (South Australia/New South Wales)", "CT"};
+        String BRISBANE[] = new String[] {"Australian Eastern Standard Time (Queensland)", "AEST",
+                                          "Australian Eastern Daylight Time (Queensland)", "AEDT",
+                                          "Australian Eastern Time (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Australian Central Standard Time (South Australia/New South Wales)", "ACST",
+                                             "Australian Central Daylight Time (South Australia/New South Wales)", "ACDT",
+                                             "Australian Central Time (South Australia/New South Wales)", "ACT"};
         String BRT[] = new String[] {"Brasilia Time", "BRT",
                                      "Brasilia Summer Time", "BRST",
                                      "Brasilia Time", "BRT"};
@@ -110,9 +110,9 @@
         String CUBA[] = new String[] {"Cuba Standard Time", "CST",
                                       "Cuba Daylight Time", "CDT",
                                       "Cuba Time", "CT"};
-        String DARWIN[] = new String[] {"Central Standard Time (Northern Territory)", "CST",
-                                        "Central Summer Time (Northern Territory)", "CST",
-                                        "Central Time (Northern Territory)", "CT"};
+        String DARWIN[] = new String[] {"Australian Central Standard Time (Northern Territory)", "ACST",
+                                        "Australian Central Daylight Time (Northern Territory)", "ACDT",
+                                        "Australian Central Time (Northern Territory)", "ACT"};
         String DUBLIN[] = new String[] {"Greenwich Mean Time", "GMT",
                                         "Irish Summer Time", "IST",
                                         "Irish Time", "IT"};
@@ -131,9 +131,9 @@
         String EST[] = new String[] {"Eastern Standard Time", "EST",
                                      "Eastern Daylight Time", "EDT",
                                      "Eastern Time", "ET"};
-        String EST_NSW[] = new String[] {"Eastern Standard Time (New South Wales)", "EST",
-                                         "Eastern Summer Time (New South Wales)", "EST",
-                                         "Eastern Time (New South Wales)", "ET"};
+        String EST_NSW[] = new String[] {"Australian Eastern Standard Time (New South Wales)", "AEST",
+                                         "Australian Eastern Daylight Time (New South Wales)", "AEDT",
+                                         "Australian Eastern Time (New South Wales)", "AET"};
         String FET[] = new String[] {"Further-eastern European Time", "FET",
                                      "Further-eastern European Summer Time", "FEST",
                                      "Further-eastern European Time", "FET"};
@@ -167,6 +167,9 @@
         String IRT[] = new String[] {"Iran Standard Time", "IRST",
                                      "Iran Daylight Time", "IRDT",
                                      "Iran Time", "IRT"};
+        String IRKT[] = new String[] {"Irkutsk Time", "IRKT",
+                                      "Irkutsk Summer Time", "IRKST",
+                                      "Irkutsk Time", "IRKT"};
         String ISRAEL[] = new String[] {"Israel Standard Time", "IST",
                                         "Israel Daylight Time", "IDT",
                                         "Israel Time", "IT"};
@@ -176,11 +179,14 @@
         String JST[] = new String[] {"Japan Standard Time", "JST",
                                      "Japan Daylight Time", "JDT",
                                      "Japan Time", "JT"};
+        String KRAT[] = new String[] {"Krasnoyarsk Time", "KRAT",
+                                      "Krasnoyarsk Summer Time", "KRAST",
+                                      "Krasnoyarsk Time", "KRAT"};
         String KST[] = new String[] {"Korea Standard Time", "KST",
                                      "Korea Daylight Time", "KDT",
                                      "Korea Time", "KT"};
         String LORD_HOWE[] = new String[] {"Lord Howe Standard Time", "LHST",
-                                           "Lord Howe Summer Time", "LHST",
+                                           "Lord Howe Daylight Time", "LHDT",
                                            "Lord Howe Time", "LHT"};
         String MHT[] = new String[] {"Marshall Islands Time", "MHT",
                                      "Marshall Islands Summer Time", "MHST",
@@ -230,21 +236,15 @@
         String SGT[] = new String[] {"Singapore Time", "SGT",
                                      "Singapore Summer Time", "SGST",
                                      "Singapore Time", "SGT"};
-        String SLST[] = new String[] {"Greenwich Mean Time", "GMT",
-                                      "Sierra Leone Summer Time", "SLST",
-                                      "Sierra Leone Time", "SLT"};
-        String TASMANIA[] = new String[] {"Eastern Standard Time (Tasmania)", "EST",
-                                          "Eastern Summer Time (Tasmania)", "EST",
-                                          "Eastern Time (Tasmania)", "ET"};
+        String TASMANIA[] = new String[] {"Australian Eastern Standard Time (Tasmania)", "AEST",
+                                          "Australian Eastern Daylight Time (Tasmania)", "AEDT",
+                                          "Australian Eastern Time (Tasmania)", "AET"};
         String TMT[] = new String[] {"Turkmenistan Time", "TMT",
                                      "Turkmenistan Summer Time", "TMST",
                                      "Turkmenistan Time", "TMT"};
         String ULAT[]= new String[] {"Ulaanbaatar Time", "ULAT",
                                      "Ulaanbaatar Summer Time", "ULAST",
                                      "Ulaanbaatar Time", "ULAT"};
-        String WART[] = new String[] {"Western Argentine Time", "WART",
-                                      "Western Argentine Summer Time", "WARST",
-                                      "Western Argentine Time", "WART"};
         String WAT[] = new String[] {"Western African Time", "WAT",
                                      "Western African Summer Time", "WAST",
                                      "Western African Time", "WAT"};
@@ -254,27 +254,30 @@
         String WIT[] = new String[] {"West Indonesia Time", "WIB",
                                      "West Indonesia Summer Time", "WIST",
                                      "West Indonesia Time", "WIB"};
-        String WST_AUS[] = new String[] {"Western Standard Time (Australia)", "WST",
-                                         "Western Summer Time (Australia)", "WST",
-                                         "Western Time (Australia)", "WT"};
+        String WST_AUS[] = new String[] {"Australian Western Standard Time", "AWST",
+                                         "Australian Western Daylight Time", "AWDT",
+                                         "Australian Western Time", "AWT"};
         String SAMOA[] = new String[] {"Samoa Standard Time", "SST",
                                        "Samoa Daylight Time", "SDT",
                                        "Samoa Time", "ST"};
-        String WST_SAMOA[] = new String[] {"West Samoa Time", "WST",
+        String WST_SAMOA[] = new String[] {"West Samoa Standard Time", "WSST",
                                            "West Samoa Daylight Time", "WSDT",
                                            "West Samoa Time", "WST"};
         String ChST[] = new String[] {"Chamorro Standard Time", "ChST",
                                       "Chamorro Daylight Time", "ChDT",
                                       "Chamorro Time", "ChT"};
-        String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST",
-                                          "Eastern Summer Time (Victoria)", "EST",
-                                          "Eastern Time (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"Australian Eastern Standard Time (Victoria)", "AEST",
+                                          "Australian Eastern Daylight Time (Victoria)", "AEDT",
+                                          "Australian Eastern Time (Victoria)", "AET"};
         String UTC[] = new String[] {"Coordinated Universal Time", "UTC",
                                      "Coordinated Universal Time", "UTC",
                                      "Coordinated Universal Time", "UTC"};
         String UZT[] = new String[] {"Uzbekistan Time", "UZT",
                                      "Uzbekistan Summer Time", "UZST",
                                      "Uzbekistan Time", "UZT"};
+        String XJT[] = new String[] {"Xinjiang Standard Time", "XJT",
+                                     "Xinjiang Daylight Time", "XJDT",
+                                     "Xinjiang Time", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +339,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +440,7 @@
                                               "Western Greenland Summer Time", "WGST",
                                               "Western Greenland Time", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +487,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
-                                                 "Metlakatla Daylight Time", "MeDT",
-                                                 "Metlakatla Time", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Pierre & Miquelon Standard Time", "PMST",
                                                "Pierre & Miquelon Daylight Time", "PMDT",
@@ -555,8 +556,8 @@
             {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Time", "DDUT",
                                                         "Dumont-d'Urville Summer Time", "DDUST",
                                                         "Dumont-d'Urville Time", "DDUT"}},
-            {"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
-                                                   "Macquarie Island Summer Time", "MIST",
+            {"Antarctica/Macquarie", new String[] {"Macquarie Island Standard Time", "MIST",
+                                                   "Macquarie Island Daylight Time", "MIDT",
                                                    "Macquarie Island Time", "MIST"}},
             {"Antarctica/Mawson", new String[] {"Mawson Time", "MAWT",
                                                 "Mawson Summer Time", "MAWST",
@@ -607,6 +608,7 @@
                                           "Brunei Summer Time", "BNST",
                                           "Brunei Time", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Choibalsan Time", "CHOT",
                                               "Choibalsan Summer Time", "CHOST",
                                               "Choibalsan Time", "CHOT"}},
@@ -631,9 +633,7 @@
             {"Asia/Hovd", new String[] {"Hovd Time", "HOVT",
                                         "Hovd Summer Time", "HOVST",
                                         "Hovd Time", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Irkutsk Time", "IRKT",
-                                           "Irkutsk Summer Time", "IRKST",
-                                           "Irkutsk Time", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"East Indonesia Time", "WIT",
@@ -646,7 +646,7 @@
                                              "Petropavlovsk-Kamchatski Summer Time", "PETST",
                                              "Petropavlovsk-Kamchatski Time", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
@@ -654,9 +654,7 @@
                                             "Khandyga Time", "YAKT"}},
 
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Krasnoyarsk Time", "KRAT",
-                                               "Krasnoyarsk Summer Time", "KRAST",
-                                               "Krasnoyarsk Time", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -671,7 +669,7 @@
                                           "Philippines Time", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Oral Time", "ORAT",
                                         "Oral Summer Time", "ORAST",
@@ -697,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -709,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
                                             "Ust-Nera Summer Time", "VLAST",
                                             "Ust-Nera Time", "VLAT"}},
@@ -751,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST",
-                                              "Central Western Summer Time (Australia)", "CWST",
-                                              "Central Western Time (Australia)", "CWT"}},
+            {"Australia/Eucla", new String[] {"Australian Central Western Standard Time", "ACWST",
+                                              "Australian Central Western Daylight Time", "ACWDT",
+                                              "Australian Central Western Time", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -819,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -854,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Volgograd Time", "VOLT",
-                                               "Volgograd Summer Time", "VOLST",
-                                               "Volgograd Time", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/java.base/share/conf/security/sunpkcs11-solaris.cfg	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# Configuration file to allow the SunPKCS11 provider to utilize
-# the Solaris Cryptographic Framework, if it is available
-#
-
-name = Solaris
-
-description = SunPKCS11 accessing Solaris Cryptographic Framework
-
-library = /usr/lib/$ISA/libpkcs11.so
-
-handleStartupErrors = ignoreAll
-
-# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
-useEcX963Encoding = true
-
-attributes = compatibility
-
-disabledMechanisms = {
-  CKM_DSA_KEY_PAIR_GEN
-}
-
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Wed Jul 05 20:00:59 2017 +0200
@@ -37,6 +37,17 @@
     private WindowsNativeDispatcher() { }
 
     /**
+     * HANDLE CreateEvent(
+     *   LPSECURITY_ATTRIBUTES lpEventAttributes,
+     *   BOOL bManualReset,
+     *   BOOL bInitialState,
+     *   PCTSTR lpName
+     * );
+     */
+    static native long CreateEvent(boolean bManualReset, boolean bInitialState)
+        throws WindowsException;
+
+    /**
      * HANDLE CreateFile(
      *   LPCTSTR lpFileName,
      *   DWORD dwDesiredAccess,
@@ -1041,6 +1052,25 @@
                                              long pOverlapped)
         throws WindowsException;
 
+
+    /**
+     * CancelIo(
+     *   HANDLE hFile
+     * )
+     */
+    static native void CancelIo(long hFile) throws WindowsException;
+
+    /**
+     * GetOverlappedResult(
+     *   HANDLE hFile,
+     *   LPOVERLAPPED lpOverlapped,
+     *   LPDWORD lpNumberOfBytesTransferred,
+     *   BOOL bWait
+     * );
+     */
+    static native int GetOverlappedResult(long hFile, long lpOverlapped)
+        throws WindowsException;
+
     /**
      * BackupRead(
      *   HANDLE hFile,
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,9 +25,16 @@
 
 package sun.nio.fs;
 
-import java.nio.file.*;
 import java.io.IOException;
-import java.util.*;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 import com.sun.nio.file.ExtendedWatchEventModifier;
 import sun.misc.Unsafe;
 
@@ -42,7 +49,6 @@
     extends AbstractWatchService
 {
     private final static int WAKEUP_COMPLETION_KEY = 0;
-    private final Unsafe unsafe = Unsafe.getUnsafe();
 
     // background thread to service I/O completion port
     private final Poller poller;
@@ -82,7 +88,7 @@
     /**
      * Windows implementation of WatchKey.
      */
-    private class WindowsWatchKey extends AbstractWatchKey {
+    private static class WindowsWatchKey extends AbstractWatchKey {
         // file key (used to detect existing registrations)
         private final FileKey fileKey;
 
@@ -169,15 +175,9 @@
             return completionKey;
         }
 
-        // close directory and release buffer
-        void releaseResources() {
-            CloseHandle(handle);
-            buffer.cleaner().clean();
-        }
-
-        // Invalidate key by closing directory and releasing buffer
+        // Invalidate the key, assumes that resources have been released
         void invalidate() {
-            releaseResources();
+            ((WindowsWatchService)watcher()).poller.releaseResources(this);
             handle = INVALID_HANDLE_VALUE;
             buffer = null;
             countAddress = 0;
@@ -193,7 +193,7 @@
         public void cancel() {
             if (isValid()) {
                 // delegate to poller
-                poller.cancel(this);
+                ((WindowsWatchService)watcher()).poller.cancel(this);
             }
         }
     }
@@ -241,18 +241,25 @@
     /**
      * Background thread to service I/O completion port.
      */
-    private class Poller extends AbstractPoller {
+    private static class Poller extends AbstractPoller {
+        private final static Unsafe UNSAFE = Unsafe.getUnsafe();
+
         /*
          * typedef struct _OVERLAPPED {
-         *     DWORD  Internal;
-         *     DWORD  InternalHigh;
-         *     DWORD  Offset;
-         *     DWORD  OffsetHigh;
-         *     HANDLE hEvent;
+         *     ULONG_PTR  Internal;
+         *     ULONG_PTR  InternalHigh;
+         *     union {
+         *         struct { DWORD Offset; DWORD OffsetHigh; };
+         *         PVOID  Pointer;
+         *     };
+         *     HANDLE    hEvent;
          * } OVERLAPPED;
          */
         private static final short SIZEOF_DWORD         = 4;
         private static final short SIZEOF_OVERLAPPED    = 32; // 20 on 32-bit
+        private static final short OFFSETOF_HEVENT      =
+            (UNSAFE.addressSize() == 4) ? (short) 16 : 24;
+
 
         /*
          * typedef struct _FILE_NOTIFY_INFORMATION {
@@ -276,10 +283,10 @@
         private final long port;
 
         // maps completion key to WatchKey
-        private final Map<Integer,WindowsWatchKey> ck2key;
+        private final Map<Integer, WindowsWatchKey> ck2key;
 
         // maps file key to WatchKey
-        private final Map<FileKey,WindowsWatchKey> fk2key;
+        private final Map<FileKey, WindowsWatchKey> fk2key;
 
         // unique completion key for each directory
         // native completion key capacity is 64 bits on Win64.
@@ -393,8 +400,13 @@
                 long overlappedAddress = bufferAddress + size - SIZEOF_OVERLAPPED;
                 long countAddress = overlappedAddress - SIZEOF_DWORD;
 
+                // zero the overlapped structure
+                UNSAFE.setMemory(overlappedAddress, SIZEOF_OVERLAPPED, (byte)0);
+
                 // start async read of changes to directory
                 try {
+                    createAndAttachEvent(overlappedAddress);
+
                     ReadDirectoryChangesW(handle,
                                           bufferAddress,
                                           CHANGES_BUFFER_SIZE,
@@ -403,6 +415,7 @@
                                           countAddress,
                                           overlappedAddress);
                 } catch (WindowsException x) {
+                    closeAttachedEvent(overlappedAddress);
                     buffer.release();
                     return new IOException(x.getMessage());
                 }
@@ -421,7 +434,7 @@
                     // 2. release existing key's resources (handle/buffer)
                     // 3. re-initialize key with new handle/buffer
                     ck2key.remove(existing.completionKey());
-                    existing.releaseResources();
+                    releaseResources(existing);
                     watchKey = existing.init(handle, events, watchSubtree, buffer,
                         countAddress, overlappedAddress, completionKey);
                 }
@@ -436,6 +449,42 @@
             }
         }
 
+        /**
+         * Cancels the outstanding I/O operation on the directory
+         * associated with the given key and releases the associated
+         * resources.
+         */
+        private void releaseResources(WindowsWatchKey key) {
+            try {
+                CancelIo(key.handle());
+                GetOverlappedResult(key.handle(), key.overlappedAddress());
+            } catch (WindowsException expected) {
+                // expected as I/O operation has been cancelled
+            }
+            CloseHandle(key.handle());
+            closeAttachedEvent(key.overlappedAddress());
+            key.buffer().cleaner().clean();
+        }
+
+        /**
+         * Creates an unnamed event and set it as the hEvent field
+         * in the given OVERLAPPED structure
+         */
+        private void createAndAttachEvent(long ov) throws WindowsException {
+            long hEvent = CreateEvent(false, false);
+            UNSAFE.putAddress(ov + OFFSETOF_HEVENT, hEvent);
+        }
+
+        /**
+         * Closes the event attached to the given OVERLAPPED structure. A
+         * no-op if there isn't an event attached.
+         */
+        private void closeAttachedEvent(long ov) {
+            long hEvent = UNSAFE.getAddress(ov + OFFSETOF_HEVENT);
+            if (hEvent != 0 && hEvent != INVALID_HANDLE_VALUE)
+               CloseHandle(hEvent);
+        }
+
         // cancel single key
         @Override
         void implCancelKey(WatchKey obj) {
@@ -451,9 +500,8 @@
         @Override
         void implCloseAll() {
             // cancel all keys
-            for (Map.Entry<Integer, WindowsWatchKey> entry: ck2key.entrySet()) {
-                entry.getValue().invalidate();
-            }
+            ck2key.values().forEach(WindowsWatchKey::invalidate);
+
             fk2key.clear();
             ck2key.clear();
 
@@ -462,8 +510,7 @@
         }
 
         // Translate file change action into watch event
-        private WatchEvent.Kind<?> translateActionToEvent(int action)
-        {
+        private WatchEvent.Kind<?> translateActionToEvent(int action) {
             switch (action) {
                 case FILE_ACTION_MODIFIED :
                     return StandardWatchEventKinds.ENTRY_MODIFY;
@@ -487,18 +534,18 @@
 
             int nextOffset;
             do {
-                int action = unsafe.getInt(address + OFFSETOF_ACTION);
+                int action = UNSAFE.getInt(address + OFFSETOF_ACTION);
 
                 // map action to event
                 WatchEvent.Kind<?> kind = translateActionToEvent(action);
                 if (key.events().contains(kind)) {
                     // copy the name
-                    int nameLengthInBytes = unsafe.getInt(address + OFFSETOF_FILENAMELENGTH);
+                    int nameLengthInBytes = UNSAFE.getInt(address + OFFSETOF_FILENAMELENGTH);
                     if ((nameLengthInBytes % 2) != 0) {
-                        throw new AssertionError("FileNameLength.FileNameLength is not a multiple of 2");
+                        throw new AssertionError("FileNameLength is not a multiple of 2");
                     }
                     char[] nameAsArray = new char[nameLengthInBytes/2];
-                    unsafe.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray,
+                    UNSAFE.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray,
                         Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes);
 
                     // create FileName and queue event
@@ -508,7 +555,7 @@
                 }
 
                 // next event
-                nextOffset = unsafe.getInt(address + OFFSETOF_NEXTENTRYOFFSET);
+                nextOffset = UNSAFE.getInt(address + OFFSETOF_NEXTENTRYOFFSET);
                 address += (long)nextOffset;
             } while (nextOffset != 0);
         }
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Wed Jul 05 20:00:59 2017 +0200
@@ -493,6 +493,9 @@
                 }
             }
         } else {
+            /* NET_BindV6() closes both sockets upon a failure */
+            (*env)->SetObjectField(env, this, pdsi_fdID, NULL);
+            (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL);
             NET_ThrowCurrent (env, "Cannot bind");
             return;
         }
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Wed Jul 05 20:00:59 2017 +0200
@@ -467,6 +467,10 @@
                     (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
                 }
             }
+        } else {
+            /* NET_BindV6() closes both sockets upon a failure */
+            (*env)->SetObjectField(env, this, psi_fdID, NULL);
+            (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
         }
     } else {
         rv = NET_WinBind(fd, (struct sockaddr *)&him, len, exclBind);
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c	Wed Jul 05 20:00:59 2017 +0200
@@ -627,7 +627,7 @@
  * and returns SOCKET_ERROR. Used in NET_BindV6 only.
  */
 
-#define CLOSE_SOCKETS_AND_RETURN {      \
+#define CLOSE_SOCKETS_AND_RETURN do {   \
     if (fd != -1) {                     \
         closesocket (fd);               \
         fd = -1;                        \
@@ -646,7 +646,7 @@
     }                                   \
     b->ipv4_fd = b->ipv6_fd = -1;       \
     return SOCKET_ERROR;                \
-}
+} while(0)
 
 /*
  * if ipv6 is available, call NET_BindV6 to bind to the required address/port.
--- a/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c	Wed Jul 05 20:00:59 2017 +0200
@@ -195,6 +195,17 @@
     }
 }
 
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CreateEvent(JNIEnv* env, jclass this,
+    jboolean bManualReset, jboolean bInitialState)
+{
+    HANDLE hEvent = CreateEventW(NULL, bManualReset, bInitialState, NULL);
+    if (hEvent == NULL) {
+        throwWindowsException(env, GetLastError());
+    }
+    return ptr_to_jlong(hEvent);
+}
+
 JNIEXPORT jstring JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) {
     WCHAR message[255];
@@ -1230,23 +1241,38 @@
 }
 
 JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_CancelIo(JNIEnv* env, jclass this, jlong hFile) {
+    if (CancelIo((HANDLE)jlong_to_ptr(hFile)) == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetOverlappedResult(JNIEnv *env, jclass this,
+    jlong hFile, jlong lpOverlapped)
+{
+    BOOL res;
+    DWORD bytesTransferred = -1;
+
+    res = GetOverlappedResult((HANDLE)jlong_to_ptr(hFile),
+                              (LPOVERLAPPED)jlong_to_ptr(lpOverlapped),
+                              &bytesTransferred,
+                              TRUE);
+    if (res == 0) {
+        throwWindowsException(env, GetLastError());
+    }
+
+    return (jint)bytesTransferred;
+}
+
+JNIEXPORT void JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this,
     jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter,
     jlong bytesReturnedAddress, jlong pOverlapped)
 {
     BOOL res;
     BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
-
-    /* Any unused members of [OVERLAPPED] structure should always be initialized to zero
-       before the structure is used in a function call.
-       Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
-       http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx
-
-       The [Offset] and [OffsetHigh] members of this structure are not used.
-       http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
-
-       [hEvent] should be zero, other fields are the return values. */
-    ZeroMemory((LPOVERLAPPED)jlong_to_ptr(pOverlapped), sizeof(OVERLAPPED));
+    LPOVERLAPPED ov = (LPOVERLAPPED)jlong_to_ptr(pOverlapped);
 
     res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
                                 (LPVOID)jlong_to_ptr(bufferAddress),
--- a/jdk/src/java.management/share/classes/javax/management/loading/MLet.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/loading/MLet.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -1313,11 +1313,11 @@
         if (type.compareTo("java.lang.Long") == 0)
              return Long.valueOf(param);
         if (type.compareTo("java.lang.Integer") == 0)
-             return param;
+             return Integer.valueOf(param);
         if (type.compareTo("java.lang.Float") == 0)
-             return new Float(param);
+             return Float.valueOf(param);
         if (type.compareTo("java.lang.Double") == 0)
-             return new Double(param);
+             return Double.valueOf(param);
         if (type.compareTo("java.lang.String") == 0)
              return param;
 
--- a/jdk/src/java.management/share/classes/sun/management/Agent.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.management/share/classes/sun/management/Agent.java	Wed Jul 05 20:00:59 2017 +0200
@@ -210,6 +210,8 @@
             } else {
                 throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, "No port specified");
             }
+        } catch (JdpException e) {
+            error(e);
         } catch (AgentConfigurationError err) {
             error(err.getError(), err.getParams());
         }
@@ -273,7 +275,7 @@
     }
 
     private static void startDiscoveryService(Properties props)
-            throws IOException {
+            throws IOException, JdpException {
         // Start discovery service if requested
         String discoveryPort = props.getProperty("com.sun.management.jdp.port");
         String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
@@ -291,7 +293,7 @@
             try{
                shouldStart = Boolean.parseBoolean(discoveryShouldStart);
             } catch (NumberFormatException e) {
-                throw new AgentConfigurationError("Couldn't parse autodiscovery argument");
+                throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse autodiscovery argument");
             }
         }
 
@@ -302,7 +304,7 @@
                 address = (discoveryAddress == null) ?
                         InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
             } catch (UnknownHostException e) {
-                throw new AgentConfigurationError("Unable to broadcast to requested address", e);
+                throw new AgentConfigurationError(AGENT_EXCEPTION, e, "Unable to broadcast to requested address");
             }
 
             int port = JDP_DEFAULT_PORT;
@@ -310,7 +312,7 @@
                try {
                   port = Integer.parseInt(discoveryPort);
                } catch (NumberFormatException e) {
-                 throw new AgentConfigurationError("Couldn't parse JDP port argument");
+                 throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse JDP port argument");
                }
             }
 
@@ -330,12 +332,7 @@
 
             String instanceName = props.getProperty("com.sun.management.jdp.name");
 
-            try{
-               JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
-            }
-            catch(JdpException e){
-                throw new AgentConfigurationError("Couldn't start JDP service", e);
-            }
+            JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
         }
     }
 
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpBroadcaster.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/java.management/share/classes/sun/management/jdp/JdpBroadcaster.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,6 +35,7 @@
 import java.nio.ByteBuffer;
 import java.nio.channels.DatagramChannel;
 import java.nio.channels.UnsupportedAddressTypeException;
+import java.util.Enumeration;
 
 /**
  * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net
@@ -79,13 +80,49 @@
         if (srcAddress != null) {
             // User requests particular interface to bind to
             NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress);
+
+            if (interf == null) {
+                throw new JdpException("Unable to get network interface for " + srcAddress.toString());
+            }
+
+            if (!interf.isUp()) {
+                throw new JdpException(interf.getName() + " is not up.");
+            }
+
+            if (!interf.supportsMulticast()) {
+                throw new JdpException(interf.getName() + " does not support multicast.");
+            }
+
             try {
                 channel.bind(new InetSocketAddress(srcAddress, 0));
             } catch (UnsupportedAddressTypeException ex) {
                 throw new JdpException("Unable to bind to source address");
             }
             channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf);
+        } else {
+            Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
+            boolean succeed = false;
+
+            while (nics.hasMoreElements()) {
+                NetworkInterface nic = nics.nextElement();
+
+                if (nic.isUp() && nic.supportsMulticast()) {
+                    try {
+                        channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, nic);
+                        succeed = true;
+                    } catch (IOException ex) {
+                        // pass
+                    }
+                }
+
+            }
+
+            if (!succeed) {
+                throw new JdpException("Unable to bind to any interfaces.");
+            }
+
         }
+
     }
 
     /**
--- a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -28,8 +28,6 @@
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
 import com.sun.tools.attach.AttachNotSupportedException;
-import com.sun.tools.attach.spi.AttachProvider;
-
 import java.io.IOException;
 
 // Based on linux/classes/sun/tools/attach/AttachProviderImpl.java.
@@ -40,9 +38,6 @@
  */
 public class AttachProviderImpl extends HotSpotAttachProvider {
 
-    // perf counter for the JVM version
-    private static final String JVM_VERSION = "java.property.java.vm.version";
-
     public AttachProviderImpl() {
     }
 
--- a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,14 +25,12 @@
  */
 package sun.tools.attach;
 
-import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
 import com.sun.tools.attach.spi.AttachProvider;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
-import java.util.Properties;
 
 // Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java.
 
--- a/jdk/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,8 +27,6 @@
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
 import com.sun.tools.attach.AttachNotSupportedException;
-import com.sun.tools.attach.spi.AttachProvider;
-
 import java.io.IOException;
 
 /*
@@ -37,9 +35,6 @@
  */
 public class AttachProviderImpl extends HotSpotAttachProvider {
 
-    // perf counter for the JVM version
-    private static final String JVM_VERSION = "java.property.java.vm.version";
-
     public AttachProviderImpl() {
     }
 
--- a/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,8 +27,6 @@
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
 import com.sun.tools.attach.AttachNotSupportedException;
-import com.sun.tools.attach.spi.AttachProvider;
-
 import java.io.IOException;
 
 /*
@@ -37,9 +35,6 @@
  */
 public class AttachProviderImpl extends HotSpotAttachProvider {
 
-    // perf counter for the JVM version
-    private static final String JVM_VERSION = "java.property.java.vm.version";
-
     public AttachProviderImpl() {
     }
 
--- a/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachine.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachine.java	Wed Jul 05 20:00:59 2017 +0200
@@ -636,7 +636,7 @@
      * @throws  NullPointerException
      *          If agentProperties is null.
      *
-     * @since   1.9
+     * @since   1.8
      */
     public abstract void startManagementAgent(Properties agentProperties) throws IOException;
 
@@ -662,7 +662,7 @@
      *          that cannot be identified as an error to indicate that the
      *          operation failed in the target VM.
      *
-     * @since   1.9
+     * @since   1.8
      */
     public abstract String startLocalManagementAgent() throws IOException;
 
--- a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,34 +25,25 @@
 package sun.tools.attach;
 
 import com.sun.tools.attach.VirtualMachineDescriptor;
-import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AttachPermission;
 import com.sun.tools.attach.AttachNotSupportedException;
 import com.sun.tools.attach.spi.AttachProvider;
 
-import java.io.IOException;
 import java.util.List;
-import java.util.Iterator;
 import java.util.ArrayList;
 import java.util.Set;
-import java.net.URISyntaxException;
 
 import sun.jvmstat.monitor.HostIdentifier;
-import sun.jvmstat.monitor.Monitor;
 import sun.jvmstat.monitor.MonitoredHost;
 import sun.jvmstat.monitor.MonitoredVm;
 import sun.jvmstat.monitor.MonitoredVmUtil;
 import sun.jvmstat.monitor.VmIdentifier;
-import sun.jvmstat.monitor.MonitorException;
 
 /*
  * Platform specific provider implementations extend this
  */
 public abstract class HotSpotAttachProvider extends AttachProvider {
 
-    // perf count name for the JVM version
-    private static final String JVM_VERSION = "java.property.java.vm.version";
-
     public HotSpotAttachProvider() {
     }
 
--- a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Wed Jul 05 20:00:59 2017 +0200
@@ -30,8 +30,10 @@
 import com.sun.tools.attach.AgentInitializationException;
 import com.sun.tools.attach.spi.AttachProvider;
 
+import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.util.Properties;
 import java.util.stream.Collectors;
 
@@ -188,7 +190,7 @@
             .filter(entry -> checkedKeyName(entry.getKey()))
             .map(entry -> stripKeyName(entry.getKey()) + "=" + escape(entry.getValue()))
             .collect(Collectors.joining(" "));
-        executeJCmd("ManagementAgent.start " + args);
+        executeJCmd("ManagementAgent.start " + args).close();
     }
 
     private String escape(Object arg) {
@@ -201,7 +203,7 @@
 
     @Override
     public String startLocalManagementAgent() throws IOException {
-        executeJCmd("ManagementAgent.start_local");
+        executeJCmd("ManagementAgent.start_local").close();
         return getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
     }
 
@@ -305,11 +307,11 @@
      * Utility method to read data into a String.
      */
     String readErrorMessage(InputStream sis) throws IOException {
-        byte b[] = new byte[1024];
-        int n;
-        StringBuffer message = new StringBuffer();
-        while ((n = sis.read(b)) != -1) {
-            message.append(new String(b, 0, n, "UTF-8"));
+        String s;
+        StringBuilder message = new StringBuilder();
+        BufferedReader br = new BufferedReader(new InputStreamReader(sis));
+        while ((s = br.readLine()) != null) {
+            message.append(s);
         }
         return message.toString();
     }
--- a/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,7 +27,6 @@
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
 import com.sun.tools.attach.AttachNotSupportedException;
-import com.sun.tools.attach.spi.AttachProvider;
 import java.io.IOException;
 
 /*
--- a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Jul 05 20:00:59 2017 +0200
@@ -107,6 +107,7 @@
             if (status != 0) {
                 // read from the stream and use that as the error message
                 String message = readErrorMessage(is);
+                is.close();
                 // special case the load command so that the right exception is thrown
                 if (cmd.equals("load")) {
                     throw new AgentLoadException("Failed to load agent library");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/solaris/conf/security/sunpkcs11-solaris.cfg	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,22 @@
+#
+# Configuration file to allow the SunPKCS11 provider to utilize
+# the Solaris Cryptographic Framework, if it is available
+#
+
+name = Solaris
+
+description = SunPKCS11 accessing Solaris Cryptographic Framework
+
+library = /usr/lib/$ISA/libpkcs11.so
+
+handleStartupErrors = ignoreAll
+
+# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
+useEcX963Encoding = true
+
+attributes = compatibility
+
+disabledMechanisms = {
+  CKM_DSA_KEY_PAIR_GEN
+}
+
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Acre Normalzeit", "ACT",
                                      "Acre Sommerzeit", "ACST",
                                      "Acre Normalzeit", "ACT"};
-        String ADELAIDE[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien)", "CST",
-                                          "Zentrale Sommerzeit (S\u00FCdaustralien)", "CST",
-                                          "Zentrale Zeitzone (S\u00FCdaustralien)", "CT"};
+        String ADELAIDE[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien)", "ACST",
+                                          "Zentrale Sommerzeit (S\u00FCdaustralien)", "ACDT",
+                                          "Zentrale Zeitzone (S\u00FCdaustralien)", "ACT"};
         String AGT[] = new String[] {"Argentinische Zeit", "ART",
                                      "Argentinische Sommerzeit", "ARST",
                                      "Argentinische Zeit", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Bangladesch Zeit", "BDT",
                                      "Bangladesch Sommerzeit", "BDST",
                                      "Bangladesch Zeit", "BDT"};
-        String BRISBANE[] = new String[] {"\u00D6stliche Normalzeit (Queensland)", "EST",
-                                          "\u00D6stliche Sommerzeit (Queensland)", "EST",
-                                          "\u00D6stliche Zeitzone (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien/New South Wales)", "CST",
-                                             "Zentrale Sommerzeit (S\u00FCdaustralien/New South Wales)", "CST",
-                                             "Zentrale Zeitzone (S\u00FCdaustralien/New South Wales)", "CT"};
+        String BRISBANE[] = new String[] {"\u00D6stliche Normalzeit (Queensland)", "AEST",
+                                          "\u00D6stliche Sommerzeit (Queensland)", "AEDT",
+                                          "\u00D6stliche Zeitzone (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien/New South Wales)", "ACST",
+                                             "Zentrale Sommerzeit (S\u00FCdaustralien/New South Wales)", "ACDT",
+                                             "Zentrale Zeitzone (S\u00FCdaustralien/New South Wales)", "ACT"};
         String BRT[] = new String[] {"Brasilianische Zeit", "BRT",
                                      "Brasilianische Sommerzeit", "BRST",
                                      "Brasilianische Zeit", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"Kubanische Normalzeit", "CST",
                                       "Kubanische Sommerzeit", "CDT",
                                       "Kubanische Normalzeit", "CT"};
-        String DARWIN[] = new String[] {"Zentrale Normalzeit (Northern Territory)", "CST",
-                                        "Zentrale Sommerzeit (Northern Territory)", "CST",
-                                        "Zentrale Zeitzone (Northern Territory)", "CT"};
+        String DARWIN[] = new String[] {"Zentrale Normalzeit (Northern Territory)", "ACST",
+                                        "Zentrale Sommerzeit (Northern Territory)", "ACDT",
+                                        "Zentrale Zeitzone (Northern Territory)", "ACT"};
         String DUBLIN[] = new String[] {"Greenwich Zeit", "GMT",
                                         "Irische Sommerzeit", "IST",
                                         "Irische Zeit", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"\u00d6stliche Normalzeit", "EST",
                                      "\u00d6stliche Sommerzeit", "EDT",
                                      "\u00D6stliche Zeitzone", "ET"};
-        String EST_NSW[] = new String[] {"\u00D6stliche Normalzeit (New South Wales)", "EST",
-                                         "\u00D6stliche Sommerzeit (New South Wales)", "EST",
-                                         "\u00D6stliche Zeitzone (New South Wales)", "ET"};
+        String EST_NSW[] = new String[] {"\u00D6stliche Normalzeit (New South Wales)", "AEST",
+                                         "\u00D6stliche Sommerzeit (New South Wales)", "AEDT",
+                                         "\u00D6stliche Zeitzone (New South Wales)", "AET"};
         String FET[] = new String[] {"Kaliningrader Zeit", "FET",
                                      "Kaliningrader Sommerzeit", "FEST",
                                      "Kaliningrader Zeit", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"Indochina Zeit", "ICT",
                                      "Indochina Sommerzeit", "ICST",
                                      "Indochina Zeit", "ICT"};
+        String IRKT[] = new String[] {"Irkutsk Zeit", "IRKT",
+                                      "Irkutsk Sommerzeit", "IRKST",
+                                      "Irkutsk Zeit", "IRKT"};
         String IRT[] = new String[] {"Iranische Normalzeit", "IRST",
                                      "Iranische Sommerzeit", "IRDT",
                                      "Iranische Zeit", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"Japanische Normalzeit", "JST",
                                      "Japanische Sommerzeit", "JDT",
                                      "Zeitzone f\u00FCr Japan", "JT"};
+        String KRAT[] = new String[] {"Krasnojarsker Zeit", "KRAT",
+                                      "Krasnojarsker Sommerzeit", "KRAST",
+                                      "Krasnojarsker Zeit", "KRAT"};
         String KST[] = new String[] {"Koreanische Normalzeit", "KST",
                                      "Koreanische Sommerzeit", "KDT",
                                      "Zeitzone f\u00FCr Korea", "KT"};
         String LORD_HOWE[] = new String[] {"Lord Howe Normalzeit", "LHST",
-                                           "Lord Howe Sommerzeit", "LHST",
+                                           "Lord Howe Sommerzeit", "LHDT",
                                            "Lord-Howe Normalzeit", "LHT"};
         String MHT[] = new String[] {"Marshallinseln Zeit", "MHT",
                                      "Marshallinseln Sommerzeit", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"Singapur Zeit", "SGT",
                                      "Singapur Sommerzeit", "SGST",
                                      "Singapur Zeit", "SGT"};
-        String SLST[] = new String[] {"Greenwich Normalzeit", "GMT",
-                                      "Sierra Leone Sommerzeit", "SLST",
-                                      "Sierra Leone Zeit", "SLT"};
-        String TASMANIA[] = new String[] {"\u00D6stliche Normalzeit (Tasmanien)", "EST",
-                                          "\u00D6stliche Sommerzeit (Tasmanien)", "EST",
-                                          "\u00D6stliche Zeitzone (Tasmanien)", "ET"};
+        String TASMANIA[] = new String[] {"\u00D6stliche Normalzeit (Tasmanien)", "AEST",
+                                          "\u00D6stliche Sommerzeit (Tasmanien)", "AEDT",
+                                          "\u00D6stliche Zeitzone (Tasmanien)", "AET"};
         String TMT[] = new String[] {"Turkmenische Zeit", "TMT",
                                      "Turkmenische Sommerzeit", "TMST",
                                      "Turkmenische Zeit", "TMT"};
         String ULAT[]= new String[] {"Ulaanbaatar Zeit", "ULAT",
                                      "Ulaanbaatar Sommerzeit", "ULAST",
                                      "Ulaanbaatar Zeit", "ULAT"};
-        String WART[] = new String[] {"Westargentinische Zeit", "WART",
-                                      "Westargentinische Sommerzeit", "WARST"};
         String WAT[] = new String[] {"Westafrikanische Zeit", "WAT",
                                      "Westafrikanische Sommerzeit", "WAST",
                                      "Westafrikanische Zeit", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"Westindonesische Zeit", "WIB",
                                      "Westindonesische Sommerzeit", "WIST",
                                      "Westindonesische Zeit", "WIB"};
-        String WST_AUS[] = new String[] {"Westliche Normalzeit (Australien)", "WST",
-                                         "Westliche Sommerzeit (Australien)", "WST",
-                                         "Westliche Zeitzone (Australien)", "WT"};
+        String WST_AUS[] = new String[] {"Westliche Normalzeit (Australien)", "AWST",
+                                         "Westliche Sommerzeit (Australien)", "AWDT",
+                                         "Westliche Zeitzone (Australien)", "AWT"};
         String SAMOA[] = new String[] {"Samoa Normalzeit", "SST",
                                        "Samoa Sommerzeit", "SDT",
                                        "Zeitzone f\u00FCr Samoa", "ST"};
-        String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WST",
+        String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WSST",
                                            "West Samoa Sommerzeit", "WSDT",
                                            "West Samoa Zeit", "WST"};
         String ChST[] = new String[] {"Chamorro Normalzeit", "ChST",
                       "Chamorro Sommerzeit", "ChDT",
                       "Zeitzone f\u00FCr die Marianen", "ChT"};
-        String VICTORIA[] = new String[] {"\u00D6stliche Normalzeit (Victoria)", "EST",
-                                          "\u00D6stliche Sommerzeit (Victoria)", "EST",
-                                          "\u00D6stliche Zeitzone (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"\u00D6stliche Normalzeit (Victoria)", "AEST",
+                                          "\u00D6stliche Sommerzeit (Victoria)", "AEDT",
+                                          "\u00D6stliche Zeitzone (Victoria)", "AET"};
         String UTC[] = new String[] {"Koordinierte Universalzeit", "UTC",
                                      "Koordinierte Universalzeit", "UTC",
                                      "Koordinierte Universalzeit", "UTC"};
         String UZT[] = new String[] {"Usbekistan Zeit", "UZT",
                                      "Usbekistan Sommerzeit", "UZST",
                                      "Usbekistan Zeit", "UZT"};
+        String XJT[] = new String[] {"Chinesische Normalzeit", "XJT",
+                                     "Chinesische Sommerzeit", "XJDT",
+                                     "Zeitzone f\u00FCr China", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "Westgr\u00f6nl\u00e4ndische Sommerzeit", "WGST",
                                               "Westgr\u00F6nl\u00E4ndische Zeit", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Metlakatla Normalzeit", "MeST",
-                                                 "Metlakatla Sommerzeit", "MeDT",
-                                                 "Metlakatla Normalzeit", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Pierre & Miquelon Normalzeit", "PMST",
                                                "Pierre & Miquelon Sommerzeit", "PMDT",
@@ -607,6 +609,7 @@
                                           "Brunei Sommerzeit", "BNST",
                                           "Brunei Zeit", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Choibalsan Zeit", "CHOT",
                                               "Choibalsan Sommerzeit", "CHOST",
                                               "Choibalsan Zeit", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Hovd Zeit", "HOVT",
                                         "Hovd Sommerzeit", "HOVST",
                                         "Hovd Zeit", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Irkutsk Zeit", "IRKT",
-                                           "Irkutsk Sommerzeit", "IRKST",
-                                           "Irkutsk Zeit", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"Ostindonesische Zeit", "WIT",
@@ -646,16 +647,14 @@
                                              "Petropawlowsk-Kamtschatkische Sommerzeit", "PETST",
                                              "Petropawlowsk-Kamtschatkische Zeit", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Chandyga Zeit", "YAKT",
                                             "Chandyga Sommerzeit", "YAKST",
                                             "Chandyga Zeit", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Krasnojarsker Zeit", "KRAT",
-                                               "Krasnojarsker Sommerzeit", "KRAST",
-                                               "Krasnojarsker Zeit", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Philippinische Zeit", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Oral Zeit", "ORAT",
                                         "Oral Sommerzeit", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Ust-Nera Zeit", "VLAT",
                                             "Ust-Nera Sommerzeit", "VLAST",
                                             "Ust-Nera Zeit", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Zentral-Westliche Normalzeit (Australien)", "CWST",
-                                              "Zentral-Westliche Sommerzeit (Australien)", "CWST",
-                                              "Zentral-Westliche Normalzeit (Australien)", "CWT"}},
+            {"Australia/Eucla", new String[] {"Zentral-Westliche Normalzeit (Australien)", "ACWST",
+                                              "Zentral-Westliche Sommerzeit (Australien)", "ACWDT",
+                                              "Zentral-Westliche Normalzeit (Australien)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Wolgograder Zeit", "VOLT",
-                                               "Wolgograder Sommerzeit", "VOLST",
-                                               "Wolgograder Zeit", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Hora de Acre", "ACT",
                                      "Hora de verano de Acre", "ACST",
                                      "Hora de Acre", "ACT"};
-        String ADELAIDE[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia)", "CST",
-                                          "Hora de verano Central (Sur de Australia)", "CST",
-                                          "Hora Central (Australia del Sur)", "CT"};
+        String ADELAIDE[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia)", "ACST",
+                                          "Hora de verano Central (Sur de Australia)", "ACDT",
+                                          "Hora Central (Australia del Sur)", "ACT"};
         String AGT[] = new String[] {"Hora de Argentina", "ART",
                                      "Hora de verano de Argentina", "ARST",
                                      "Hora de Argentina", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Hora de Bangladesh", "BDT",
                                      "Hora de verano de Bangladesh", "BDST",
                                      "Hora de Bangladesh", "BDT"};
-        String BRISBANE[] = new String[] {"Hora est\u00E1ndar del Este (Queensland)", "EST",
-                                          "Hora est\u00E1ndar de verano del Este (Queensland)", "EST",
-                                          "Hora Oriental (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia/Nueva Gales del Sur)", "CST",
-                                             "Hora de verano Central (Sur de Australia/Nueva Gales del Sur)", "CST",
-                                             "Hora Central (Australia del Sur/Nueva Gales del Sur)", "CT"};
+        String BRISBANE[] = new String[] {"Hora est\u00E1ndar del Este (Queensland)", "AEST",
+                                          "Hora est\u00E1ndar de verano del Este (Queensland)", "AEDT",
+                                          "Hora Oriental (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia/Nueva Gales del Sur)", "ACST",
+                                             "Hora de verano Central (Sur de Australia/Nueva Gales del Sur)", "ACDT",
+                                             "Hora Central (Australia del Sur/Nueva Gales del Sur)", "ACT"};
         String BRT[] = new String[] {"Hora de Brasil", "BRT",
                                      "Hora de verano de Brasil", "BRST",
                                      "Hora de Brasil", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"Hora est\u00e1ndar de Cuba", "CST",
                                       "Hora de verano de Cuba", "CDT",
                                       "Hora de Cuba", "CT"};
-        String DARWIN[] = new String[] {"Hora est\u00E1ndar Central (territorio del Norte)", "CST",
-                                        "Hora de verano Central (territorio del Norte)", "CST",
-                                        "Hora Central (Territorio Septentrional)", "CT"};
+        String DARWIN[] = new String[] {"Hora est\u00E1ndar Central (territorio del Norte)", "ACST",
+                                        "Hora de verano Central (territorio del Norte)", "ACDT",
+                                        "Hora Central (Territorio Septentrional)", "ACT"};
         String DUBLIN[] = new String[] {"Hora del Meridiano de Greenwich", "GMT",
                                         "Hora de verano de Irlanda", "IST",
                                         "Hora de Irlanda", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"Hora est\u00e1ndar Oriental", "EST",
                                      "Hora de verano Oriental", "EDT",
                                      "Hora Oriental", "ET"};
-        String EST_NSW[] = new String[] {"Hora est\u00E1ndar Oriental (Nueva Gales del Sur)", "EST",
-                                         "Hora de verano Oriental (Nueva Gales del Sur)", "EST",
-                                         "Hora Oriental (Nueva Gales del Sur)", "ET"};
+        String EST_NSW[] = new String[] {"Hora est\u00E1ndar Oriental (Nueva Gales del Sur)", "AEST",
+                                         "Hora de verano Oriental (Nueva Gales del Sur)", "AEDT",
+                                         "Hora Oriental (Nueva Gales del Sur)", "AET"};
         String FET[] = new String[] {"Hora de Europa m\u00E1s Oriental", "FET",
                                      "Hora de verano de Europa m\u00E1s Oriental", "FEST",
                                      "Hora de Europa m\u00E1s Oriental", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"Hora de Indochina", "ICT",
                                      "Hora de verano de Indochina", "ICST",
                                      "Hora de Indochina", "ICT"};
+        String IRKT[] = new String[] {"Hora de Irkutsk", "IRKT",
+                                      "Hora de verano de Irkutsk", "IRKST",
+                                      "Hora de Irkutsk", "IRKT"};
         String IRT[] = new String[] {"Hora est\u00e1ndar de Ir\u00e1n", "IRST",
                                      "Hora de verano de Ir\u00e1n", "IRDT",
                                      "Hora de Ir\u00E1n", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"Hora est\u00e1ndar de Jap\u00f3n", "JST",
                                      "Hora de verano de Jap\u00f3n", "JDT",
                                      "Hora de Jap\u00F3n", "JT"};
+        String KRAT[] = new String[] {"Hora de Krasnoyarsk", "KRAT",
+                                      "Hora de verano de Krasnoyarsk", "KRAST",
+                                      "Hora de Krasnoyarsk", "KRAT"};
         String KST[] = new String[] {"Hora est\u00e1ndar de Corea", "KST",
                                      "Hora de verano de Corea", "KDT",
                                      "Hora de Corea", "KT"};
         String LORD_HOWE[] = new String[] {"Hora est\u00e1ndar de Lord Howe", "LHST",
-                                           "Hora de verano de Lord Howe", "LHST",
+                                           "Hora de verano de Lord Howe", "LHDT",
                                            "Hora de Lord Howe", "LHT"};
         String MHT[] = new String[] {"Hora de las Islas Marshall", "MHT",
                                      "Hora de verano de las Islas Marshall", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"Hora de Singapur", "SGT",
                                      "Hora de verano de  Singapur", "SGST",
                                      "Hora de Singapur", "SGT"};
-        String SLST[] = new String[] {"Hora del Meridiano de Greenwich", "GMT",
-                                      "Hora de verano de Sierra Leona", "SLST",
-                                      "Horario de Sierra Leona", "SLT"};
-        String TASMANIA[] = new String[] {"Hora est\u00E1ndar del Este (Tasmania)", "EST",
-                                          "Hora de verano del Este (Tasmania)", "EST",
-                                          "Hora Oriental (Tasmania)", "ET"};
+        String TASMANIA[] = new String[] {"Hora est\u00E1ndar del Este (Tasmania)", "AEST",
+                                          "Hora de verano del Este (Tasmania)", "AEDT",
+                                          "Hora Oriental (Tasmania)", "AET"};
         String TMT[] = new String[] {"Hora de Turkmenist\u00e1n", "TMT",
                                      "Hora de verano de Turkmenist\u00e1n", "TMST",
                                      "Hora de Turkmenist\u00E1n", "TMT"};
         String ULAT[]= new String[] {"Hora de Ulan Bator", "ULAT",
                                      "Hora de verano de Ulan Bator", "ULAST",
                                      "Hora de Ulan Bator", "ULAT"};
-        String WART[] = new String[] {"Hora de Argentina Occidental", "WART",
-                                      "Hora de verano de Argentina Occidental", "WARST"};
         String WAT[] = new String[] {"Hora de \u00c1frica Occidental", "WAT",
                                      "Hora de verano de \u00c1frica Occidental", "WAST",
                                      "Hora de \u00C1frica Occidental", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"Hora de Indonesia Occidental", "WIB",
                                      "Indonesia Hora de verano de Indonesia Occidental", "WIST",
                                      "Hora de Indonesia Occidental", "WIB"};
-        String WST_AUS[] = new String[] {"Hora est\u00E1ndar Occidental (Australia)", "WST",
-                                         "Hora de verano Occidental (Australia)", "WST",
-                                         "Hora Occidental (Australia)", "WT"};
+        String WST_AUS[] = new String[] {"Hora est\u00E1ndar Occidental (Australia)", "AWST",
+                                         "Hora de verano Occidental (Australia)", "AWDT",
+                                         "Hora Occidental (Australia)", "AWT"};
         String SAMOA[] = new String[] {"Hora est\u00e1ndar de Samoa", "SST",
                                        "Hora de verano de Samoa", "SDT",
                                        "Hora de Samoa", "ST"};
-        String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WST",
+        String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WSST",
                                            "Hora de verano de Samoa Occidental", "WSDT",
                                            "Hora de Samoa Occidental", "WST"};
         String ChST[] = new String[] {"Hora est\u00e1ndar de Chamorro", "ChST",
                                       "Hora de verano de Chamorro", "ChDT",
                                       "Hora de Chamorro", "ChT"};
-        String VICTORIA[] = new String[] {"Hora est\u00E1ndar del Este (Victoria)", "EST",
-                                          "Hora de verano del Este (Victoria)", "EST",
-                                          "Hora Oriental (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"Hora est\u00E1ndar del Este (Victoria)", "AEST",
+                                          "Hora de verano del Este (Victoria)", "AEDT",
+                                          "Hora Oriental (Victoria)", "AET"};
         String UTC[] = new String[] {"Hora Universal Coordinada", "UTC",
                                      "Hora Universal Coordinada", "UTC",
                                      "Hora Universal Coordinada", "UTC"};
         String UZT[] = new String[] {"Hora de Uzbekist\u00e1n", "UZT",
                                      "Hora de verano de Uzbekist\u00e1n", "UZST",
                                      "Hora de Uzbekist\u00E1n", "UZT"};
+        String XJT[] = new String[] {"Hora est\u00e1ndar de China", "XJT",
+                                     "Hora de verano de China", "XJDT",
+                                     "Hora de China", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "Hora de verano de Groenlandia Occidental", "WGST",
                                               "Hora de Groenlandia Occidental", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Hora de Metlakatla", "MeST",
-                                                 "Hora de verano de Metlakatla", "MeDT",
-                                                 "Metlakatla Time", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Hora est\u00e1ndar de Pierre & Miquelon", "PMST",
                                                "Hora de verano de Pierre & Miquelon", "PMDT",
@@ -607,6 +609,7 @@
                                           "Hora de verano de Brunei", "BNST",
                                           "Hora de Brunei", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Hora de Choibalsan", "CHOT",
                                               "Hora de verano de Choibalsan", "CHOST",
                                               "Hora de Choibalsan", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Hora de Hovd", "HOVT",
                                         "Hora de verano de Hovd", "HOVST",
                                         "Hora de Hovd", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Hora de Irkutsk", "IRKT",
-                                           "Hora de verano de Irkutsk", "IRKST",
-                                           "Hora de Irkutsk", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"Hora de Indonesia Oriental", "WIT",
@@ -646,16 +647,14 @@
                                              "Hora de verano de Petropavlovsk-Kamchatski", "PETST",
                                              "Hora de Petropavlovsk-Kamchatski", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Hora de Khandyga", "YAKT",
                                             "Hora de verano de Khandyga", "YAKST",
                                             "Hora de Khandyga", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Hora de Krasnoyarsk", "KRAT",
-                                               "Hora de verano de Krasnoyarsk", "KRAST",
-                                               "Hora de Krasnoyarsk", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Hora de Filipinas", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Hora de Uralsk", "ORAT",
                                         "Hora de verano de Uralsk", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Hora de Ust-Nera", "VLAT",
                                             "Hora de verano de Ust-Nera", "VLAST",
                                             "Hora de Ust-Nera", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Hora est\u00E1ndar de Australia Central y Occidental", "CWST",
-                                              "Hora est\u00E1ndar de verano de Australia Central y Occidental", "CWST",
-                                              "Hora de Australia Central y Occidental", "CWT"}},
+            {"Australia/Eucla", new String[] {"Hora est\u00E1ndar de Australia Central y Occidental", "ACWST",
+                                              "Hora est\u00E1ndar de verano de Australia Central y Occidental", "ACWDT",
+                                              "Hora de Australia Central y Occidental", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Hora de Volgogrado", "VOLT",
-                                               "Hora de verano de Volgogrado", "VOLST",
-                                               "Hora de Volgogrado", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Heure de l'Acre", "ACT",
                                      "Heure d'\u00e9t\u00e9 de l'Acre", "ACST",
                                      "Heure de l'Acre", "ACT"};
-        String ADELAIDE[] = new String[] {"Heure standard d'Australie centrale (Australie du sud)", "CST",
-                                          "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud)", "CST",
-                                          "Centre (Australie-M\u00E9ridionale)", "CT"};
+        String ADELAIDE[] = new String[] {"Heure standard d'Australie centrale (Australie du sud)", "ACST",
+                                          "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud)", "ACDT",
+                                          "Centre (Australie-M\u00E9ridionale)", "ACT"};
         String AGT[] = new String[] {"Heure D'Argentine", "ART",
                                      "Heure d'\u00e9t\u00e9 D'Argentine", "ARST",
                                      "Heure d'Argentine", "ART"} ;
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Heure du Bangladesh", "BDT",
                                      "Heure d'\u00e9t\u00e9 du Bangladesh", "BDST",
                                      "Heure du Bangladesh", "BDT"} ;
-        String BRISBANE[] = new String[] {"Heure standard d'Australie orientale (Queensland)", "EST",
-                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Queensland)", "EST",
-                                          "C\u00F4te Est (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Heure standard d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "CST",
-                                             "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "CST",
-                                             "Centre (Australie-M\u00E9ridionale/Nouvelle-Galles du Sud)", "CT"};
+        String BRISBANE[] = new String[] {"Heure standard d'Australie orientale (Queensland)", "AEST",
+                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Queensland)", "AEDT",
+                                          "C\u00F4te Est (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Heure standard d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "ACST",
+                                             "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "ACDT",
+                                             "Centre (Australie-M\u00E9ridionale/Nouvelle-Galles du Sud)", "ACT"};
         String BRT[] = new String[] {"Heure du Br\u00e9sil", "BRT",
                                      "Heure d'\u00e9t\u00e9 du Br\u00e9sil", "BRST",
                                      "Heure du Br\u00E9sil", "BRT"} ;
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"Heure standard de Cuba", "CST",
                                       "Heure d'\u00e9t\u00e9 de Cuba", "CDT",
                                       "Heure de Cuba", "CT"};
-        String DARWIN[] = new String[] {"Heure standard d'Australie centrale (Territoire du Nord)", "CST",
-                                        "Heure d'\u00E9t\u00E9 d'Australie centrale (Territoire du Nord)", "CST",
-                                        "Centre (Territoire du Nord)", "CT"};
+        String DARWIN[] = new String[] {"Heure standard d'Australie centrale (Territoire du Nord)", "ACST",
+                                        "Heure d'\u00E9t\u00E9 d'Australie centrale (Territoire du Nord)", "ACDT",
+                                        "Centre (Territoire du Nord)", "ACT"};
         String DUBLIN[] = new String[] {"Heure du m\u00e9ridien de Greenwich", "GMT",
                                         "Heure d'\u00e9t\u00e9 irlandaise", "IST",
                                         "Heure irlandaise", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"Heure normale de l'Est", "EST",
                                      "Heure avanc\u00e9e de l'Est", "EDT",
                                      "C\u00F4te Est", "ET"} ;
-        String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "EST",
-                                         "Heure d'\u00E9t\u00E9 de l'Est (Nouvelle-Galles du Sud)", "EST",
-                                         "C\u00F4te Est (Nouvelle-Galles du Sud)", "ET"} ;
+        String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "AEST",
+                                         "Heure d'\u00E9t\u00E9 de l'Est (Nouvelle-Galles du Sud)", "AEDT",
+                                         "C\u00F4te Est (Nouvelle-Galles du Sud)", "AET"} ;
         String FET[] = new String[] {"Heure d'Europe de l'Est UTC+3", "FET",
                                      "Heure d'\u00E9t\u00E9 d'Europe de l'Est UTC+3", "FEST",
                                      "Heure d'Europe de l'Est UTC+3", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"Heure d'Indochine", "ICT",
                                      "Heure d'\u00e9t\u00e9 d'Indochine", "ICST",
                                      "Heure d'Indochine", "ICT"} ;
+        String IRKT[] = new String[] {"Heure d'Irkutsk", "IRKT",
+                                      "Heure d'\u00e9t\u00e9 d'Irkutsk", "IRKST",
+                                      "Heure d'Irkutsk", "IRKT"};
         String IRT[] = new String[] {"Heure normale d'Iran", "IRST",
                                      "Heure avanc\u00e9e d'Iran", "IRDT",
                                      "Heure d'Iran", "IRT"} ;
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"Heure normale du Japon", "JST",
                                      "Heure avanc\u00e9e du Japon", "JDT",
                                      "Japon", "JT"} ;
+        String KRAT[] = new String[] {"Heure de Krasno\u00efarsk", "KRAT",
+                                      "Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST",
+                                      "Heure de Krasno\u00EFarsk", "KRAT"};
         String KST[] = new String[] {"Heure normale de Cor\u00e9e", "KST",
                                      "Heure avanc\u00e9e de Cor\u00e9e", "KDT",
                                      "Cor\u00E9e", "KT"} ;
         String LORD_HOWE[] = new String[] {"Heure standard de Lord Howe", "LHST",
-                                           "Heure d'\u00e9t\u00e9 de Lord Howe", "LHST",
+                                           "Heure d'\u00e9t\u00e9 de Lord Howe", "LHDT",
                                            "Heure de Lord Howe", "LHT"};
         String MHT[] = new String[] {"Heure des Iles Marshall", "MHT",
                                      "Heure d'\u00e9t\u00e9 des Iles Marshall", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"Heure de Singapour", "SGT",
                                      "Heure d'\u00e9t\u00e9 de Singapour", "SGST",
                                      "Heure de Singapour", "SGT"};
-        String SLST[] = new String[] {"Heure du m\u00e9ridien de Greenwich", "GMT",
-                                      "Heure d'\u00e9t\u00e9 de Sierra Leone", "SLST",
-                                      "Heure de Sierra Leone", "SLT"};
-        String TASMANIA[] = new String[] {"Heure standard d'Australie orientale (Tasmanie)", "EST",
-                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Tasmanie)", "EST",
-                                          "C\u00F4te Est (Tasmanie)", "ET"};
+        String TASMANIA[] = new String[] {"Heure standard d'Australie orientale (Tasmanie)", "AEST",
+                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Tasmanie)", "AEDT",
+                                          "C\u00F4te Est (Tasmanie)", "AET"};
         String TMT[] = new String[] {"Heure du Turkm\u00e9nistan", "TMT",
                                      "Heure d'\u00e9t\u00e9 du Turkm\u00e9nistan", "TMST",
                                      "Heure du Turkm\u00E9nistan", "TMT"} ;
         String ULAT[]= new String[] {"Heure de l'Ulaanbaatar", "ULAT",
                                      "Heure d'\u00e9t\u00e9 de l'Ulaanbaatar", "ULAST",
                                      "Heure de l'Ulaanbaatar", "ULAT"} ;
-        String WART[] = new String[] {"Heure D'Argentine de l'Ouest", "WART",
-                                      "Heure d'\u00e9t\u00e9 D'Argentine de l'Ouest", "WARST"} ;
         String WAT[] = new String[] {"Heure d'Afrique de l'Ouest", "WAT",
                                      "Heure d'\u00e9t\u00e9 d'Afrique de l'Ouest", "WAST",
                                      "Heure d'Afrique de l'Ouest", "WAT"} ;
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"Heure de l'Indon\u00e9sie occidentale", "WIB",
                                      "Heure d'\u00e9t\u00e9 de l'Indon\u00e9sie occidentale", "WIST",
                                      "Heure de l'Indon\u00E9sie occidentale", "WIB"};
-        String WST_AUS[] = new String[] {"Heure normale de l'Ouest (Australie)", "WST",
-                                         "Heure d'\u00E9t\u00E9 de l'Ouest (Australie)", "WST",
-                                         "Ouest (Australie)", "WT"} ;
+        String WST_AUS[] = new String[] {"Heure normale de l'Ouest (Australie)", "AWST",
+                                         "Heure d'\u00E9t\u00E9 de l'Ouest (Australie)", "AWDT",
+                                         "Ouest (Australie)", "AWT"} ;
         String SAMOA[] = new String[] {"Heure standard de Samoa", "SST",
                                        "Heure avanc\u00e9e de Samoa", "SDT",
                                        "Samoa", "ST"};
-        String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WST",
+        String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WSST",
                                            "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSDT",
                                            "Heure des Samoas occidentales", "WST"} ;
         String ChST[] = new String[] {"Heure normale des \u00eeles Mariannes", "ChST",
                       "Heure d'\u00e9t\u00e9 des \u00eeles Mariannes", "ChDT",
                       "Chamorro", "ChT"};
-        String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "EST",
-                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Victoria)", "EST",
-                                          "C\u00F4te Est (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "AEST",
+                                          "Heure d'\u00E9t\u00E9 d'Australie orientale (Victoria)", "AEDT",
+                                          "C\u00F4te Est (Victoria)", "AET"};
         String UTC[] = new String[] {"Temps universel coordonn\u00e9", "UTC",
                                      "Temps universel coordonn\u00e9", "UTC",
                                      "Temps universel coordonn\u00E9", "UTC"};
         String UZT[] = new String[] {"Heure de l'Ouzb\u00e9kistan", "UZT",
                                      "Heure d'\u00e9t\u00e9 de l'Ouzb\u00e9kistan", "UZST",
                                      "Heure de l'Ouzb\u00E9kistan", "UZT"};
+        String XJT[] = new String[] {"Heure normale de Chine", "XJT",
+                                     "Heure avanc\u00e9e de Chine", "XJDT",
+                                     "Chine", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "Heure d'\u00e9t\u00e9 du Groenland de l'Ouest", "WGST",
                                               "Heure du Groenland de l'Ouest", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Heure normale de Metlakatla", "MeST",
-                                                 "Heure avanc\u00E9e de Metlakatla", "MeDT",
-                                                 "Heure de Metlakatla", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Heure normale de Saint-Pierre et Miquelon", "PMST",
                                                "Heure avanc\u00e9e de Saint-Pierre et Miquelon", "PMDT",
@@ -607,6 +609,7 @@
                                           "Heure d'\u00e9t\u00e9 du Brunei", "BNST",
                                           "Heure du Brunei", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Heure de Choibalsan", "CHOT",
                                               "Heure d'\u00e9t\u00e9 de Choibalsan", "CHOST",
                                               "Heure de Choibalsan", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Heure de Hovd", "HOVT",
                                         "Heure d'\u00e9t\u00e9 de Hovd", "HOVST",
                                         "Heure de Hovd", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Heure d'Irkutsk", "IRKT",
-                                           "Heure d'\u00e9t\u00e9 d'Irkutsk", "IRKST",
-                                           "Heure d'Irkutsk", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"Heure d'Indon\u00e9sie orientale", "WIT",
@@ -646,16 +647,14 @@
                                              "Heure d'\u00e9t\u00e9 de Petropavlovsk-Kamchatski", "PETST",
                                              "Heure de Petropavlovsk-Kamchatski", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Heure de Khandyga", "YAKT",
                                             "Heure d'\u00E9t\u00E9 de Khandyga", "YAKST",
                                             "Heure de Khandyga", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Heure de Krasno\u00efarsk", "KRAT",
-                                               "Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST",
-                                               "Heure de Krasno\u00EFarsk", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Heure des Philippines", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Heure d'Oral", "ORAT",
                                         "Heure d'\u00e9t\u00e9 d'Oral", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Heure d'Ust-Nera", "VLAT",
                                             "Heure d'\u00E9t\u00E9 d'Ust-Nera", "VLAST",
                                             "Heure d'Ust-Nera", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Heure standard de l'Australie occidentale (centre)", "CWST",
-                                              "Heure d'\u00E9t\u00E9 de l'Australie occidentale (centre)", "CWST",
-                                              "Heure de l'Australie occidentale (centre)", "CWT"}},
+            {"Australia/Eucla", new String[] {"Heure standard de l'Australie occidentale (centre)", "ACWST",
+                                              "Heure d'\u00E9t\u00E9 de l'Australie occidentale (centre)", "ACWDT",
+                                              "Heure de l'Australie occidentale (centre)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Heure de Volgograd", "VOLT",
-                                               "Heure d'\u00e9t\u00e9 de Volgograd", "VOLST",
-                                               "Heure de Volgograd", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Ora di Acre", "ACT",
                                      "Ora estiva di Acre", "ACST",
                                      "Ora di Acre", "ACT"};
-        String ADELAIDE[] = new String[] {"Ora standard centrale (Australia del Sud)", "CST",
-                                          "Ora estiva centrale (Australia del Sud)", "CST",
-                                          "Ora fuso centrale (Australia del Sud)", "CT"};
+        String ADELAIDE[] = new String[] {"Ora standard centrale (Australia del Sud)", "ACST",
+                                          "Ora estiva centrale (Australia del Sud)", "ACDT",
+                                          "Ora fuso centrale (Australia del Sud)", "ACT"};
         String AGT[] = new String[] {"Ora dell'Argentina", "ART",
                                      "Ora estiva dell'Argentina", "ARST",
                                      "Ora dell'Argentina", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Ora del Bangladesh", "BDT",
                                      "Ora estiva del Bangladesh", "BDST",
                                      "Ora del Bangladesh", "BDT"};
-        String BRISBANE[] = new String[] {"Ora standard orientale (Queensland)", "EST",
-                                          "Ora estiva orientale (Queensland)", "EST",
-                                          "Ora fuso orientale (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Ora standard centrale (Australia del Sud/Nuovo Galles del Sud)", "CST",
-                                             "Ora estiva centrale (Australia del Sud/Nuovo Galles del Sud)", "CST",
-                                             "Ora fuso centrale (Australia del Sud/Nuovo Galles del Sud)", "CT"};
+        String BRISBANE[] = new String[] {"Ora standard orientale (Queensland)", "AEST",
+                                          "Ora estiva orientale (Queensland)", "AEDT",
+                                          "Ora fuso orientale (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Ora standard centrale (Australia del Sud/Nuovo Galles del Sud)", "ACST",
+                                             "Ora estiva centrale (Australia del Sud/Nuovo Galles del Sud)", "ACDT",
+                                             "Ora fuso centrale (Australia del Sud/Nuovo Galles del Sud)", "ACT"};
         String BRT[] = new String[] {"Ora del Brasile", "BRT",
                                      "Ora estiva del Brasile", "BRST",
                                      "Ora di Brasilia", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"Ora solare Cuba", "CST",
                                       "Ora legale Cuba", "CDT",
                                       "Ora di Cuba", "CT"};
-        String DARWIN[] = new String[] {"Ora standard centrale (Territori del Nord)", "CST",
-                                        "Ora estiva centrale (Territori del Nord)", "CST",
-                                        "Ora fuso centrale (Territori del Nord)", "CT"};
+        String DARWIN[] = new String[] {"Ora standard centrale (Territori del Nord)", "ACST",
+                                        "Ora estiva centrale (Territori del Nord)", "ACDT",
+                                        "Ora fuso centrale (Territori del Nord)", "ACT"};
         String DUBLIN[] = new String[] {"Ora media di Greenwich", "GMT",
                                         "Ora estiva irlandese", "IST",
                                         "Ora irlandese", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"Ora solare USA orientale", "EST",
                                      "Ora legale USA orientale", "EDT",
                                      "Fuso orientale", "ET"};
-        String EST_NSW[] = new String[] {"Ora standard dell'Australia orientale (Nuovo Galles del Sud)", "EST",
-                                         "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "EST",
-                                         "Ora fuso orientale (Nuovo Galles del Sud)", "ET"};
+        String EST_NSW[] = new String[] {"Ora standard dell'Australia orientale (Nuovo Galles del Sud)", "AEST",
+                                         "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "AEDT",
+                                         "Ora fuso orientale (Nuovo Galles del Sud)", "AET"};
         String FET[] = new String[] {"Ora dei paesi europei pi\u00F9 orientali", "FET",
                                      "Ora estiva dei paesi europei pi\u00F9 orientali", "FEST",
                                      "Ora dei paesi europei pi\u00F9 orientali", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"Ora dell'Indocina", "ICT",
                                      "Ora estiva dell'Indocina", "ICST",
                                      "Ora dell'Indocina", "ICT"};
+        String IRKT[] = new String[] {"Ora di Irkutsk", "IRKT",
+                                      "Ora estiva di Irkutsk", "IRKST",
+                                      "Ora di Irkutsk", "IRKT"};
         String IRT[] = new String[] {"Ora solare Iran", "IRST",
                                      "Ora legale Iran", "IRDT",
                                      "Ora Iran", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"Ora solare del Giappone", "JST",
                                      "Ora legale del Giappone", "JDT",
                                      "Ora Giappone", "JT"};
+        String KRAT[] = new String[] {"Ora di Krasnojarsk", "KRAT",
+                                      "Ora estiva di Krasnojarsk", "KRAST",
+                                      "Ora di Krasnojarsk", "KRAT"};
         String KST[] = new String[] {"Ora solare della Corea", "KST",
                                      "Ora legale della Corea", "KDT",
                                      "Ora Corea", "KT"};
         String LORD_HOWE[] = new String[] {"Ora standard di Lord Howe", "LHST",
-                                           "Ora estiva di Lord Howe", "LHST",
+                                           "Ora estiva di Lord Howe", "LHDT",
                                            "Ora di Lord Howe", "LHT"};
         String MHT[] = new String[] {"Ora delle Isole Marshall", "MHT",
                                      "Ora estiva delle Isole Marshall", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"Ora di Singapore", "SGT",
                                      "Ora estiva di Singapore", "SGST",
                                      "Ora di Singapore", "SGT"};
-        String SLST[] = new String[] {"Ora media di Greenwich", "GMT",
-                                      "Ora legale della Sierra Leone", "SLST",
-                                      "Ora della Sierra Leone", "SLT"};
-        String TASMANIA[] = new String[] {"Ora standard orientale (Tasmania)", "EST",
-                                          "Ora estiva orientale (Tasmania)", "EST",
-                                          "Ora fuso orientale (Tasmania)", "ET"};
+        String TASMANIA[] = new String[] {"Ora standard orientale (Tasmania)", "AEST",
+                                          "Ora estiva orientale (Tasmania)", "AEDT",
+                                          "Ora fuso orientale (Tasmania)", "AET"};
         String TMT[] = new String[] {"Ora del Turkmenistan", "TMT",
                                      "Ora estiva del Turkmenistan", "TMST",
                                      "Ora del Turkmenistan", "TMT"};
         String ULAT[]= new String[] {"Ora di Ulaanbaatar", "ULAT",
                                      "Ora estiva di Ulaanbaatar", "ULAST",
                                      "Ora di Ulaanbaatar", "ULAT"};
-        String WART[] = new String[] {"Ora dell'Argentina occidentale", "WART",
-                                      "Ora estiva dell'Argentina occidentale", "WARST"};
         String WAT[] = new String[] {"Ora dell'Africa occidentale", "WAT",
                                      "Ora estiva dell'Africa occidentale", "WAST",
                                      "Ora dell'Africa occidentale", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"Ora dell'Indonesia occidentale", "WIB",
                                      "Ora estiva dell'Indonesia occidentale", "WIST",
                                      "Ora dell'Indonesia occidentale", "WIB"};
-        String WST_AUS[] = new String[] {"Ora standard dell'Australia occidentale", "WST",
-                                         "Ora estiva dell'Australia occidentale", "WST",
-                                         "Ora Australia occidentale", "WT"};
+        String WST_AUS[] = new String[] {"Ora standard dell'Australia occidentale", "AWST",
+                                         "Ora estiva dell'Australia occidentale", "AWDT",
+                                         "Ora Australia occidentale", "AWT"};
         String SAMOA[] = new String[] {"Ora standard di Samoa", "SST",
                                        "Ora legale di Samoa", "SDT",
                                        "Ora Samoa", "ST"};
-        String WST_SAMOA[] = new String[] {"Ora di Samoa", "WST",
+        String WST_SAMOA[] = new String[] {"Ora di Samoa", "WSST",
                                            "Ora estiva di Samoa", "WSDT",
                                            "Ora di Samoa occidentale", "WST"};
         String ChST[] = new String[] {"Ora standard di Chamorro", "ChST",
                               "Ora legale di Chamorro", "ChDT",
                               "Ora Chamorro", "ChT"};
-        String VICTORIA[] = new String[] {"Ora standard orientale (Victoria)", "EST",
-                                          "Ora estiva orientale (Victoria)", "EST",
-                                          "Ora fuso orientale (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"Ora standard orientale (Victoria)", "AEST",
+                                          "Ora estiva orientale (Victoria)", "AEDT",
+                                          "Ora fuso orientale (Victoria)", "AET"};
         String UTC[] = new String[] {"Tempo universale coordinato", "UTC",
                                      "Tempo universale coordinato", "UTC",
                                      "Tempo universale coordinato", "UTC"};
         String UZT[] = new String[] {"Ora dell'Uzbekistan", "UZT",
                                      "Ora estiva dell'Uzbekistan", "UZST",
                                      "Ora dell'Uzbekistan", "UZT"};
+        String XJT[] = new String[] {"Ora solare della Cina", "XJT",
+                                     "Ora legale della Cina", "XJDT",
+                                     "Ora Cina", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "Ora estiva della Groenlandia occidentale", "WGST",
                                               "Ora della Groenlandia occidentale", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Ora standard di Metlakatla", "MeST",
-                                                 "Ora legale di Metlakatla", "MeDT",
-                                                 "Ora di Metlakatla", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Ora solare di Saint-Pierre e Miquelon", "PMST",
                                                "Ora legale di Saint-Pierre e Miquelon", "PMDT",
@@ -607,6 +609,7 @@
                                           "Ora estiva del Brunei", "BNST",
                                           "Ora del Brunei", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Ora di Choibalsan", "CHOT",
                                               "Ora estiva di Choibalsan", "CHOST",
                                               "Ora di Choibalsan", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Ora di Hovd", "HOVT",
                                         "Ora estiva di Hovd", "HOVST",
                                         "Ora di Hovd", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Ora di Irkutsk", "IRKT",
-                                           "Ora estiva di Irkutsk", "IRKST",
-                                           "Ora di Irkutsk", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"Ora dell'Indonesia orientale", "WIT",
@@ -646,16 +647,14 @@
                                              "Ora estiva di Petropavlovsk-Kamchatski", "PETST",
                                              "Ora di Petropavlovsk-Kamchatski", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Kolkata", IST},
             {"Asia/Khandyga", new String[] {"Ora di Khandyga", "YAKT",
                                             "Ora estiva di Khandyga", "YAKST",
                                             "Ora di Khandyga", "YAKT"}},
-            {"Asia/Krasnoyarsk", new String[] {"Ora di Krasnojarsk", "KRAT",
-                                               "Ora estiva di Krasnojarsk", "KRAST",
-                                               "Ora di Krasnojarsk", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Ora delle Filippine", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Ora di Oral", "ORAT",
                                         "Ora estiva di Oral", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Ora di Ust-Nera", "VLAT",
                                             "Ora estiva di Ust-Nera", "VLAST",
                                             "Ora di Ust-Nera", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Ora standard Australia centro-occidentale", "CWST",
-                                              "Ora estiva Australia centro-occidentale", "CWST",
-                                              "Ora Australia centro-occidentale", "CWT"}},
+            {"Australia/Eucla", new String[] {"Ora standard Australia centro-occidentale", "ACWST",
+                                              "Ora estiva Australia centro-occidentale", "ACWDT",
+                                              "Ora Australia centro-occidentale", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Ora di Volgograd", "VOLT",
-                                               "Ora estiva di Volgograd", "VOLST",
-                                               "Ora di Volgograd", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"\u30a2\u30af\u30ec\u6642\u9593", "ACT",
                                      "\u30a2\u30af\u30ec\u590f\u6642\u9593", "ACST",
                                      "\u30a2\u30af\u30ec\u6642\u9593", "ACT"};
-        String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CST",
-                                          "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CST",
-                                          "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CT"};
+        String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACST",
+                                          "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACDT",
+                                          "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACT"};
         String AGT[] = new String[] {"\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "ART",
                                      "\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "ARST",
                                      "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6642\u9593", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"\u30d0\u30f3\u30b0\u30e9\u30c7\u30b7\u30e5\u6642\u9593", "BDT",
                                      "\u30d0\u30f3\u30b0\u30e9\u30c7\u30b7\u30e5\u590f\u6642\u9593", "BDST",
                                      "\u30D0\u30F3\u30B0\u30E9\u30C7\u30B7\u30E5\u6642\u9593", "BDT"};
-        String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "EST",
-                                          "\u6771\u90E8\u590F\u6642\u9593(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "EST",
-                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "ET"};
-        String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CST",
-                                             "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CST",
-                                             "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CT"};
+        String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AEST",
+                                          "\u6771\u90E8\u590F\u6642\u9593(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AEDT",
+                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AET"};
+        String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACST",
+                                             "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACDT",
+                                             "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACT"};
         String BRT[] = new String[] {"\u30d6\u30e9\u30b8\u30eb\u6642\u9593", "BRT",
                                      "\u30d6\u30e9\u30b8\u30eb\u590f\u6642\u9593", "BRST",
                                      "\u30D6\u30E9\u30B8\u30EA\u30A2\u6642\u9593", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"\u30ad\u30e5\u30fc\u30d0\u6a19\u6e96\u6642", "CST",
                                       "\u30ad\u30e5\u30fc\u30d0\u590f\u6642\u9593", "CDT",
                                       "\u30AD\u30E5\u30FC\u30D0\u6642\u9593", "CT"};
-        String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CST",
-                                        "\u4E2D\u90E8\u590F\u6642\u9593(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CST",
-                                        "\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CT"};
+        String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACST",
+                                        "\u4E2D\u90E8\u590F\u6642\u9593(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACDT",
+                                        "\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACT"};
         String DUBLIN[] = new String[] {"\u30b0\u30ea\u30cb\u30c3\u30b8\u6a19\u6e96\u6642", "GMT",
                                         "\u30a2\u30a4\u30eb\u30e9\u30f3\u30c9\u590f\u6642\u9593", "IST",
                                         "\u30A2\u30A4\u30EB\u30E9\u30F3\u30C9\u6642\u9593", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642", "EST",
                                      "\u6771\u90e8\u590f\u6642\u9593", "EDT",
                                      "\u6771\u90E8\u6A19\u6E96\u6642", "ET"};
-        String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "EST",
-                                         "\u6771\u90E8\u590F\u6642\u9593(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "EST",
-                                         "\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ET"};
+        String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AEST",
+                                         "\u6771\u90E8\u590F\u6642\u9593(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AEDT",
+                                         "\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AET"};
         String FET[] = new String[] {"\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u6642\u9593", "FET",
                                      "\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u590F\u6642\u9593", "FEST",
                                      "\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u6642\u9593", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"\u30a4\u30f3\u30c9\u30b7\u30ca\u6642\u9593", "ICT",
                                      "\u30a4\u30f3\u30c9\u30b7\u30ca\u590f\u6642\u9593", "ICST",
                                      "\u30A4\u30F3\u30C9\u30B7\u30CA\u6642\u9593", "ICT"};
+        String IRKT[] = new String[] {"\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u6642\u9593", "IRKT",
+                                      "\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u590f\u6642\u9593", "IRKST",
+                                      "\u30A4\u30EB\u30AF\u30FC\u30C4\u30AF\u6642\u9593", "IRKT"};
         String IRT[] = new String[] {"\u30a4\u30e9\u30f3\u6a19\u6e96\u6642", "IRST",
                                      "\u30a4\u30e9\u30f3\u590f\u6642\u9593", "IRDT",
                                      "\u30A4\u30E9\u30F3\u6642\u9593", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"\u65e5\u672c\u6a19\u6e96\u6642", "JST",
                                      "\u65e5\u672c\u590f\u6642\u9593", "JDT",
                                      "\u65E5\u672C\u6642\u9593", "JT"};
+        String KRAT[] = new String[] {"\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u6642\u9593", "KRAT",
+                                      "\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u590f\u6642\u9593", "KRAST",
+                                      "\u30AF\u30E9\u30B9\u30CE\u30E4\u30EB\u30B9\u30AF\u6642\u9593", "KRAT"};
         String KST[] = new String[] {"\u97d3\u56fd\u6a19\u6e96\u6642", "KST",
                                      "\u97d3\u56fd\u590f\u6642\u9593", "KDT",
                                      "\u97D3\u56FD\u6642\u9593", "KT"};
         String LORD_HOWE[] = new String[] {"\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u6a19\u6e96\u6642", "LHST",
-                                           "\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u590f\u6642\u9593", "LHST",
+                                           "\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u590f\u6642\u9593", "LHDT",
                                            "\u30ED\u30FC\u30C9\u30CF\u30A6\u6642\u9593", "LHT"};
         String MHT[] = new String[] {"\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u6642\u9593", "MHT",
                                      "\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u590f\u6642\u9593", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"\u30b7\u30f3\u30ac\u30dd\u30fc\u30eb\u6642\u9593", "SGT",
                                      "\u30b7\u30f3\u30ac\u30dd\u30fc\u30eb\u590f\u6642\u9593", "SGST",
                                      "\u30B7\u30F3\u30AC\u30DD\u30FC\u30EB\u6642\u9593", "SGT"};
-        String SLST[] = new String[] {"\u30b0\u30ea\u30cb\u30c3\u30b8\u6a19\u6e96\u6642", "GMT",
-                                      "\u30b7\u30a8\u30e9\u30ec\u30aa\u30cd\u590f\u6642\u9593", "SLST",
-                                      "\u30B7\u30A8\u30E9\u30EC\u30AA\u30CD\u6642\u9593", "SLT"};
-        String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "EST",
-                                          "\u6771\u90E8\u590F\u6642\u9593(\u30BF\u30B9\u30DE\u30CB\u30A2)", "EST",
-                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "ET"};
+        String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AEST",
+                                          "\u6771\u90E8\u590F\u6642\u9593(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AEDT",
+                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AET"};
         String TMT[] = new String[] {"\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u6642\u9593", "TMT",
                                      "\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u590f\u6642\u9593", "TMST",
                                      "\u30C8\u30EB\u30AF\u30E1\u30CB\u30B9\u30BF\u30F3\u6642\u9593", "TMT"};
         String ULAT[]= new String[] {"\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u6642\u9593", "ULAT",
                                      "\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u590f\u6642\u9593", "ULAST",
                                      "\u30A6\u30E9\u30F3\u30D0\u30FC\u30C8\u30EB\u6642\u9593", "ULAT"};
-        String WART[] = new String[] {"\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "WART",
-                                      "\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "WARST"};
         String WAT[] = new String[] {"\u897f\u30a2\u30d5\u30ea\u30ab\u6642\u9593", "WAT",
                                      "\u897f\u30a2\u30d5\u30ea\u30ab\u590f\u6642\u9593", "WAST",
                                      "\u897F\u90E8\u30A2\u30D5\u30EA\u30AB\u6642\u9593", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"\u897f\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u6642\u9593", "WIB",
                                      "\u897f\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u590f\u6642\u9593", "WIST",
                                      "\u897F\u90E8\u30A4\u30F3\u30C9\u30CD\u30B7\u30A2\u6642\u9593", "WIB"};
-        String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WST",
-                                         "\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WST",
-                                         "\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WT"};
+        String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWST",
+                                         "\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWDT",
+                                         "\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWT"};
         String SAMOA[] = new String[] {"\u30b5\u30e2\u30a2\u6a19\u6e96\u6642", "SST",
                                        "\u30b5\u30e2\u30a2\u590f\u6642\u9593", "SDT",
                                        "\u30B5\u30E2\u30A2\u6642\u9593", "ST"};
-        String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WST",
+        String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WSST",
                                            "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSDT",
                                            "\u897F\u30B5\u30E2\u30A2\u6642\u9593", "WST"};
         String ChST[] = new String[] {"\u30b0\u30a2\u30e0\u6a19\u6e96\u6642", "ChST",
                                       "\u30b0\u30a2\u30e0\u590f\u6642\u9593", "ChDT",
                                       "\u30C1\u30E3\u30E2\u30ED\u6642\u9593", "ChT"};
-        String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "EST",
-                                          "\u6771\u90E8\u590F\u6642\u9593(\u30D3\u30AF\u30C8\u30EA\u30A2)", "EST",
-                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "ET"};
+        String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AEST",
+                                          "\u6771\u90E8\u590F\u6642\u9593(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AEDT",
+                                          "\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AET"};
         String UTC[] = new String[] {"\u5354\u5b9a\u4e16\u754c\u6642", "UTC",
                                      "\u5354\u5b9a\u4e16\u754c\u6642", "UTC",
                                      "\u5354\u5B9A\u4E16\u754C\u6642", "UTC"};
         String UZT[] = new String[] {"\u30a6\u30ba\u30d9\u30ad\u30b9\u30bf\u30f3\u6642\u9593", "UZT",
                                      "\u30a6\u30ba\u30d9\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "UZST",
                                      "\u30A6\u30BA\u30D9\u30AD\u30B9\u30BF\u30F3\u6642\u9593", "UZT"};
+        String XJT[] = new String[] {"\u4e2d\u56fd\u6a19\u6e96\u6642", "XJT",
+                                     "\u4e2d\u56fd\u590f\u6642\u9593", "XJDT",
+                                     "\u4E2D\u56FD\u6642\u9593", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "\u897f\u30b0\u30ea\u30fc\u30f3\u30e9\u30f3\u30c9\u590f\u6642\u9593", "WGST",
                                               "\u897F\u90E8\u30B0\u30EA\u30FC\u30F3\u30E9\u30F3\u30C9\u6642\u9593", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u6A19\u6E96\u6642\u9593", "MeST",
-                                                 "\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u590F\u6642\u9593", "MeDT",
-                                                 "\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u6642\u9593", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u6a19\u6e96\u6642", "PMST",
                                                "\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u590f\u6642\u9593", "PMDT",
@@ -607,6 +609,7 @@
                                           "\u30d6\u30eb\u30cd\u30a4\u590f\u6642\u9593", "BNST",
                                           "\u30D6\u30EB\u30CD\u30A4\u6642\u9593", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"\u30c1\u30e7\u30a4\u30d0\u30eb\u30b5\u30f3\u6642\u9593", "CHOT",
                                               "\u30c1\u30e7\u30a4\u30d0\u30eb\u30b5\u30f3\u590f\u6642\u9593", "CHOST",
                                               "\u30C1\u30E7\u30A4\u30D0\u30EB\u30B5\u30F3\u6642\u9593", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"\u30db\u30d6\u30c9\u6642\u9593", "HOVT",
                                         "\u30db\u30d6\u30c9\u590f\u6642\u9593", "HOVST",
                                         "\u30DB\u30D6\u30C9\u6642\u9593", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u6642\u9593", "IRKT",
-                                           "\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u590f\u6642\u9593", "IRKST",
-                                           "\u30A4\u30EB\u30AF\u30FC\u30C4\u30AF\u6642\u9593", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"\u6771\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u6642\u9593", "WIT",
@@ -646,16 +647,14 @@
                                              "\u30da\u30c8\u30ed\u30d1\u30d6\u30ed\u30d5\u30b9\u30af\u30ab\u30e0\u30c1\u30e3\u30c4\u30ad\u30fc\u590f\u6642\u9593", "PETST",
                                              "\u30DA\u30C8\u30ED\u30D1\u30D6\u30ED\u30D5\u30B9\u30AF\u30FB\u30AB\u30E0\u30C1\u30E3\u30C4\u30AD\u30FC\u6642\u9593", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u6642\u9593", "YAKT",
                                             "\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u590F\u6642\u9593", "YAKST",
                                             "\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u6642\u9593", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u6642\u9593", "KRAT",
-                                               "\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u590f\u6642\u9593", "KRAST",
-                                               "\u30AF\u30E9\u30B9\u30CE\u30E4\u30EB\u30B9\u30AF\u6642\u9593", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "\u30D5\u30A3\u30EA\u30D4\u30F3\u6642\u9593", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"\u30aa\u30e9\u30eb\u6642\u9593", "ORAT",
                                         "\u30aa\u30e9\u30eb\u590f\u6642\u9593", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"\u30A6\u30B9\u30C1\u30CD\u30E9\u6642\u9593", "VLAT",
                                             "\u30A6\u30B9\u30C1\u30CD\u30E9\u590F\u6642\u9593", "VLAST",
                                             "\u30A6\u30B9\u30C1\u30CD\u30E9\u6642\u9593", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWT"}},
+            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWST",
+                                              "\u4E2D\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWDT",
+                                              "\u4E2D\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u6642\u9593", "VOLT",
-                                               "\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u590f\u6642\u9593", "VOLST",
-                                               "\u30DC\u30EB\u30B4\u30B0\u30E9\u30FC\u30C9\u6642\u9593", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"\uc5d0\uc774\ucee4 \uc2dc\uac04", "ACT",
                                      "\uc5d0\uc774\ucee4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ACST",
                                      "\uc5d0\uc774\ucee4 \uc2dc\uac04", "ACT"};
-        String ADELAIDE[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CST",
-                                          "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CST",
-                                          "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CT"};
+        String ADELAIDE[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACST",
+                                          "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACDT",
+                                          "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACT"};
         String AGT[] = new String[] {"\uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "ART",
                                      "\uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ARST",
                                      "\uC544\uB974\uD5E8\uD2F0\uB098 \uD45C\uC900\uC2DC", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"\ubc29\uae00\ub77c\ub370\uc2dc \uc2dc\uac04", "BDT",
                                      "\ubc29\uae00\ub77c\ub370\uc2dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BDST",
                                      "\uBC29\uAE00\uB77C\uB370\uC2DC \uD45C\uC900\uC2DC", "BDT"};
-        String BRISBANE[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "EST",
-                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD038\uC990\uB79C\uB4DC)", "EST",
-                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "ET"};
-        String BROKEN_HILL[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CST",
-                                             "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CST",
-                                             "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CT"};
+        String BRISBANE[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "AEST",
+                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD038\uC990\uB79C\uB4DC)", "AEDT",
+                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "AET"};
+        String BROKEN_HILL[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACST",
+                                             "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACDT",
+                                             "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACT"};
         String BRT[] = new String[] {"\ube0c\ub77c\uc9c8\ub9ac\uc544 \uc2dc\uac04", "BRT",
                                      "\ube0c\ub77c\uc9c8\ub9ac\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BRST",
                                      "\uBE0C\uB77C\uC9C8\uB9AC\uC544 \uD45C\uC900\uC2DC", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"\ucfe0\ubc14 \ud45c\uc900\uc2dc", "CST",
                                       "\ucfe0\ubc14 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT",
                                       "\uCFE0\uBC14 \uD45C\uC900\uC2DC", "CT"};
-        String DARWIN[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "CST",
-                                        "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBD81\uBD80 \uC9C0\uC5ED)", "CST",
-                                        "\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "CT"};
+        String DARWIN[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "ACST",
+                                        "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBD81\uBD80 \uC9C0\uC5ED)", "ACDT",
+                                        "\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "ACT"};
         String DUBLIN[] = new String[] {"\uadf8\ub9ac\ub2c8\uce58 \ud45c\uc900\uc2dc", "GMT",
                                         "\uc544\uc77c\ub79c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IST",
                                         "\uC544\uC77C\uB79C\uB4DC \uD45C\uC900\uC2DC", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc", "EST",
                                      "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "EDT",
                                      "\uB3D9\uBD80 \uD45C\uC900\uC2DC", "ET"};
-        String EST_NSW[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "EST",
-                                         "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "EST",
-                                         "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ET"};
+        String EST_NSW[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AEST",
+                                         "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AEDT",
+                                         "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AET"};
         String FET[] = new String[] {"\uADF9\uB3D9 \uC720\uB7FD \uD45C\uC900\uC2DC", "FET",
                                      "\uADF9\uB3D9 \uC720\uB7FD \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "FEST",
                                      "\uADF9\uB3D9 \uC720\uB7FD \uD45C\uC900\uC2DC", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"\uc778\ub3c4\ucc28\uc774\ub098 \ubc18\ub3c4 \uc2dc\uac04", "ICT",
                                      "\uc778\ub3c4\ucc28\uc774\ub098 \ubc18\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ICST",
                                      "\uC778\uB3C4\uCC28\uC774\uB098 \uBC18\uB3C4 \uD45C\uC900\uC2DC", "ICT"};
+        String IRKT[] =  new String[] {"\uc774\ub974\ucfe0\uce20\ud06c \uc2dc\uac04", "IRKT",
+                                       "\uc774\ub974\ucfe0\uce20\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRKST",
+                                       "\uC774\uB974\uCFE0\uCE20\uD06C \uD45C\uC900\uC2DC", "IRKT"};
         String IRT[] = new String[] {"\uc774\ub780 \ud45c\uc900\uc2dc", "IRST",
                                      "\uc774\ub780 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRDT",
                                      "\uC774\uB780 \uD45C\uC900\uC2DC", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"\uc77c\ubcf8 \ud45c\uc900\uc2dc", "JST",
                                      "\uc77c\ubcf8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "JDT",
                                      "\uC77C\uBCF8 \uD45C\uC900\uC2DC", "JT"};
+        String KRAT[] = new String[] {"\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc2dc\uac04", "KRAT",
+                                      "\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KRAST",
+                                      "\uD06C\uB77C\uC2A4\uB178\uC57C\uB974\uC2A4\uD06C \uD45C\uC900\uC2DC", "KRAT"};
         String KST[] = new String[] {"\ud55c\uad6d \ud45c\uc900\uc2dc", "KST",
                                      "\ud55c\uad6d \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KDT",
                                      "\uB300\uD55C\uBBFC\uAD6D \uD45C\uC900\uC2DC", "KT"};
         String LORD_HOWE[] = new String[] {"\ub85c\ub4dc \ud558\uc6b0 \ud45c\uc900\uc2dc", "LHST",
-                                           "\ub85c\ub4dc \ud558\uc6b0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "LHST",
+                                           "\ub85c\ub4dc \ud558\uc6b0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "LHDT",
                                            "\uB85C\uB4DC\uD558\uC6B0 \uD45C\uC900\uC2DC", "LHT"};
         String MHT[] = new String[] {"\ub9c8\uc15c\uc81c\ub3c4 \uc2dc\uac04", "MHT",
                                      "\ub9c8\uc15c\uc81c\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"\uc2f1\uac00\ud3ec\ub974 \uc2dc\uac04", "SGT",
                                      "\uc2f1\uac00\ud3ec\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SGST",
                                      "\uC2F1\uAC00\uD3EC\uB974 \uD45C\uC900\uC2DC", "SGT"};
-        String SLST[] = new String[] {"\uadf8\ub9ac\ub2c8\uce58 \ud45c\uc900\uc2dc", "GMT",
-                                      "\uc2dc\uc5d0\ub77c\ub9ac\uc628 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SLST",
-                                      "\uC2DC\uC5D0\uB77C\uB9AC\uC628 \uD45C\uC900\uC2DC", "SLT"};
-        String TASMANIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "EST",
-                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "EST",
-                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "ET"};
+        String TASMANIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AEST",
+                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AEDT",
+                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AET"};
         String TMT[] = new String[] {"\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc2dc\uac04", "TMT",
                                      "\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TMST",
                                      "\uD22C\uB974\uD06C\uBA54\uB2C8\uC2A4\uD0C4 \uD45C\uC900\uC2DC", "TMT"};
         String ULAT[]= new String[] {"\uc6b8\ub780\ubc14\ud0c0\ub974 \uc2dc\uac04", "ULAT",
                                      "\uc6b8\ub780\ubc14\ud0c0\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ULAST",
                                      "\uC6B8\uB780\uBC14\uD1A0\uB974 \uD45C\uC900\uC2DC", "ULAT"};
-        String WART[] = new String[] {"\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "WART",
-                                      "\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WARST"};
         String WAT[] = new String[] {"\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc2dc\uac04", "WAT",
                                      "\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WAST",
                                      "\uC11C\uBD80 \uC544\uD504\uB9AC\uCE74 \uD45C\uC900\uC2DC", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"\uc11c\uc778\ub3c4\ub124\uc2dc\uc544 \uc2dc\uac04", "WIB",
                                      "\uc11c\uc778\ub3c4\ub124\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WIST",
                                      "\uC11C\uBD80 \uC778\uB3C4\uB124\uC2DC\uC544 \uD45C\uC900\uC2DC", "WIB"};
-        String WST_AUS[] = new String[] {"\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WST",
-                                         "\uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WST",
-                                         "\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WT"};
+        String WST_AUS[] = new String[] {"\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWST",
+                                         "\uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWDT",
+                                         "\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWT"};
         String SAMOA[] = new String[] {"\uc0ac\ubaa8\uc544 \ud45c\uc900\uc2dc", "SST",
                                        "\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SDT",
                                        "\uC0AC\uBAA8\uC544 \uD45C\uC900\uC2DC", "ST"};
-        String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WST",
+        String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WSST",
                                            "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSDT",
                                            "\uC11C\uC0AC\uBAA8\uC544 \uD45C\uC900\uC2DC", "WST"};
         String ChST[] = new String[] {"\ucc28\ubaa8\ub85c \ud45c\uc900\uc2dc", "ChST",
                                       "\ucc28\ubaa8\ub85c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ChDT",
                                       "\uCC28\uBAA8\uB974 \uD45C\uC900\uC2DC", "ChT"};
-        String VICTORIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "EST",
-                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBE45\uD1A0\uB9AC\uC544)", "EST",
-                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "ET"};
+        String VICTORIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "AEST",
+                                          "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBE45\uD1A0\uB9AC\uC544)", "AEDT",
+                                          "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "AET"};
         String UTC[] = new String[] {"\uc138\uacc4 \ud45c\uc900\uc2dc", "UTC",
                                      "\uc138\uacc4 \ud45c\uc900\uc2dc", "UTC",
                                      "\uC9C0\uC5ED \uD45C\uC900\uC2DC", "UTC"};
         String UZT[] = new String[] {"\uc6b0\uc988\ubca0\ud0a4\uc2a4\ud0c4 \uc2dc\uac04", "UZT",
                                      "\uc6b0\uc988\ubca0\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "UZST",
                                      "\uC6B0\uC988\uBCA0\uD0A4\uC2A4\uD0C4 \uD45C\uC900\uC2DC", "UZT"};
+        String XJT[] = new String[] {"\uc911\uad6d \ud45c\uc900\uc2dc", "XJT",
+                                     "\uc911\uad6d \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "XJDT",
+                                     "\uC911\uAD6D \uD45C\uC900\uC2DC", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "\uc11c\ubd80 \uadf8\ub9b0\ub79c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WGST",
                                               "\uC11C\uBD80 \uADF8\uB9B0\uB780\uB4DC \uD45C\uC900\uC2DC", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uD45C\uC900\uC2DC", "MeST",
-                                                 "\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "MeDT",
-                                                 "\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uD45C\uC900\uC2DC", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \ud45c\uc900\uc2dc", "PMST",
                                                "\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PMDT",
@@ -607,6 +609,7 @@
                                           "\ube0c\ub8e8\ub098\uc774 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BNST",
                                           "\uBE0C\uB8E8\uB098\uC774 \uD45C\uC900\uC2DC", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Choibalsan \uc2dc\uac04", "CHOT",
                                               "Choibalsan \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CHOST",
                                               "\uCD08\uC774\uBC1C\uC0B0 \uD45C\uC900\uC2DC", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Hovd \uc2dc\uac04", "HOVT",
                                         "Hovd \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "HOVST",
                                         "\uD638\uBE0C\uB4DC \uD45C\uC900\uC2DC", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"\uc774\ub974\ucfe0\uce20\ud06c \uc2dc\uac04", "IRKT",
-                                            "\uc774\ub974\ucfe0\uce20\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRKST",
-                                            "\uC774\uB974\uCFE0\uCE20\uD06C \uD45C\uC900\uC2DC", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"\ub3d9\ubd80 \uc778\ub3c4\ub124\uc2dc\uc544 \uc2dc\uac04", "WIT",
@@ -646,16 +647,14 @@
                                             "\ud398\ud2b8\ub85c\ud30c\ube14\ub85c\ud504\uc2a4\ud06c-\uce84\ucc28\uce20\ud0a4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PETST",
                                             "\uD398\uD2B8\uB85C\uD30C\uBE0C\uB85C\uD504\uC2A4\uD06C-\uCE84\uCC28\uCE20\uD0A4 \uD45C\uC900\uC2DC", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"\uD55C\uB514\uAC00 \uD45C\uC900\uC2DC", "YAKT",
                                             "\uD55C\uB514\uAC00 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "YAKST",
                                             "\uD55C\uB514\uAC00 \uD45C\uC900\uC2DC", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc2dc\uac04", "KRAT",
-                                               "\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KRAST",
-                                               "\uD06C\uB77C\uC2A4\uB178\uC57C\uB974\uC2A4\uD06C \uD45C\uC900\uC2DC", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "\uD544\uB9AC\uD540 \uD45C\uC900\uC2DC", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Oral \ud45c\uc900\uc2dc", "ORAT",
                                         "Oral \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"\uC6B0\uC2A4\uD2F0\uB124\uB77C \uD45C\uC900\uC2DC", "VLAT",
                                             "\uC6B0\uC2A4\uD2F0\uB124\uB77C \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "VLAST" ,
                                             "\uC6B0\uC2A4\uD2F0\uB124\uB77C \uD45C\uC900\uC2DC", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWST",
-                                              "\uC911\uC559 \uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWST",
-                                              "\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWT"}},
+            {"Australia/Eucla", new String[] {"\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWST",
+                                              "\uC911\uC559 \uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWDT",
+                                              "\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"\ubcfc\uace0\uadf8\ub77c\ub4dc \uc2dc\uac04", "VOLT",
-                                               "\ubcfc\uace0\uadf8\ub77c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VOLST",
-                                               "\uBCFC\uACE0\uADF8\uB77C\uB4DC \uD45C\uC900\uC2DC", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Fuso hor\u00e1rio do Acre", "ACT",
                                      "Fuso hor\u00e1rio de ver\u00e3o do Acre", "ACST",
                                      "Fuso hor\u00e1rio do Acre", "ACT"};
-        String ADELAIDE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul)", "CST",
-                                          "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul)", "CST",
-                                          "Hor\u00E1rio Central (Austr\u00E1lia do Sul)", "CT"};
+        String ADELAIDE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul)", "ACST",
+                                          "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul)", "ACDT",
+                                          "Hor\u00E1rio Central (Austr\u00E1lia do Sul)", "ACT"};
         String AGT[] = new String[] {"Fuso hor\u00e1rio da Argentina", "ART",
                                      "Fuso hor\u00e1rio de ver\u00e3o da Argentina", "ARST",
                                      "Hor\u00E1rio da Argentina", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Fuso hor\u00e1rio de Bangladesh", "BDT",
                                      "Fuso hor\u00e1rio de ver\u00e3o de Bangladesh", "BDST",
                                      "Hor\u00E1rio de Bangladesh", "BDT"};
-        String BRISBANE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Queensland)", "EST",
-                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Queensland)", "EST",
-                                          "Hor\u00E1rio do Leste (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CST",
-                                             "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CST",
-                                             "Hor\u00E1rio Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CT"};
+        String BRISBANE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Queensland)", "AEST",
+                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Queensland)", "AEDT",
+                                          "Hor\u00E1rio do Leste (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACST",
+                                             "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACDT",
+                                             "Hor\u00E1rio Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACT"};
         String BRT[] = new String[] {"Fuso hor\u00e1rio de Bras\u00edlia", "BRT",
                                      "Fuso hor\u00e1rio de ver\u00e3o de Bras\u00edlia", "BRST",
                                      "Hor\u00E1rio de Bras\u00EDlia", "BRT"};
@@ -108,9 +108,9 @@
         String CUBA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Cuba", "CST",
                                       "Hor\u00e1rio de luz natural de Cuba", "CDT",
                                       "Hor\u00E1rio de Cuba", "CT"};
-        String DARWIN[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Territ\u00F3rio do Norte)", "CST",
-                                        "Fuso Hor\u00E1rio de Ver\u00E3o Central (Territ\u00F3rio do Norte)", "CST",
-                                        "Hor\u00E1rio Central (Territ\u00F3rio do Norte)", "CT"};
+        String DARWIN[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Territ\u00F3rio do Norte)", "ACST",
+                                        "Fuso Hor\u00E1rio de Ver\u00E3o Central (Territ\u00F3rio do Norte)", "ACDT",
+                                        "Hor\u00E1rio Central (Territ\u00F3rio do Norte)", "ACT"};
         String DUBLIN[] = new String[] {"Fuso hor\u00e1rio do meridiano de Greenwich", "GMT",
                                         "Fuso hor\u00e1rio de ver\u00e3o da Irlanda", "IST",
                                         "Hor\u00E1rio da Rep\u00FAblica da Irlanda", "IT"};
@@ -129,9 +129,9 @@
         String EST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental", "EST",
                                      "Hor\u00e1rio de luz natural oriental", "EDT",
                                      "Hor\u00E1rio do Leste", "ET"};
-        String EST_NSW[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Oriental (Nova Gales do Sul)", "EST",
-                                         "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Nova Gales do Sul)", "EST",
-                                         "Hor\u00E1rio Oriental (Nova Gales do Sul)", "ET"};
+        String EST_NSW[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Oriental (Nova Gales do Sul)", "AEST",
+                                         "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Nova Gales do Sul)", "AEDT",
+                                         "Hor\u00E1rio Oriental (Nova Gales do Sul)", "AET"};
         String FET[] = new String[] {"Hor\u00E1rio do Extremo Leste Europeu (FET)", "FET",
                                      "Fuso Hor\u00E1rio de Ver\u00E3o do Extremo Leste Europeu", "FEST",
                                      "Hor\u00E1rio do Extremo Leste Europeu (FET)", "FET"};
@@ -162,6 +162,9 @@
         String ICT[] = new String[] {"Fuso hor\u00e1rio da Indochina", "ICT",
                                      "Fuso hor\u00e1rio de ver\u00e3o da Indochina", "ICST",
                                      "Hor\u00E1rio da Indochina", "ICT"};
+        String IRKT[] = new String[] {"Fuso hor\u00e1rio de Irkutsk", "IRKT",
+                                      "Fuso hor\u00e1rio de ver\u00e3o de Irkutsk", "IRKST",
+                                      "Hor\u00E1rio de Irkutsk", "IRKT"};
         String IRT[] = new String[] {"Fuso hor\u00e1rio do Ir\u00e3", "IRST",
                                      "Hor\u00e1rio de luz natural do Ir\u00e3", "IRDT",
                                      "Hor\u00E1rio do Ir\u00E3", "IRT"};
@@ -174,11 +177,14 @@
         String JST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o do Jap\u00e3o", "JST",
                                      "Hor\u00e1rio de luz natural do Jap\u00e3o", "JDT",
                                      "Hor\u00E1rio do Jap\u00E3o", "JT"};
+        String KRAT[] = new String[] {"Fuso hor\u00e1rio de Krasnoyarsk", "KRAT",
+                                      "Fuso hor\u00e1rio de ver\u00e3o de Krasnoyarsk", "KRAST",
+                                      "Hor\u00E1rio de Krasnoyarsk", "KRAT"};
         String KST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o da Coreia", "KST",
                                      "Hor\u00e1rio de luz natural da Coreia", "KDT",
                                      "Hor\u00E1rio da Coreia", "KT"};
         String LORD_HOWE[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Lord Howe", "LHST",
-                                           "Fuso hor\u00e1rio de ver\u00e3o de Lord Howe", "LHST",
+                                           "Fuso hor\u00e1rio de ver\u00e3o de Lord Howe", "LHDT",
                                            "Hor\u00E1rio de Lord Howe", "LHT"};
         String MHT[] = new String[] {"Fuso hor\u00e1rio das Ilhas Marshall", "MHT",
                                      "Fuso hor\u00e1rio de ver\u00e3o das Ilhas Marshall", "MHST",
@@ -228,12 +234,9 @@
         String SGT[] = new String[] {"Fuso hor\u00e1rio de Cingapura", "SGT",
                                      "Fuso hor\u00e1rio de ver\u00e1 de Cingapura", "SGST",
                                      "Hor\u00E1rio de Cingapura", "SGT"};
-        String SLST[] = new String[] {"Fuso hor\u00e1rio do meridiano de Greenwich", "GMT",
-                                      "Fuso hor\u00e1rio de ver\u00e3o de Serra Leoa", "SLST",
-                                      "Hor\u00E1rio de Serra Leoa", "SLT"};
-        String TASMANIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Tasm\u00E2nia)", "EST",
-                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Tasm\u00E2nia)", "EST",
-                                          "Hor\u00E1rio do Leste (Tasm\u00E2nia)", "ET"};
+        String TASMANIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Tasm\u00E2nia)", "AEST",
+                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Tasm\u00E2nia)", "AEDT",
+                                          "Hor\u00E1rio do Leste (Tasm\u00E2nia)", "AET"};
         String TMT[] = new String[] {"Fuso hor\u00e1rio do Turcomenist\u00e3o", "TMT",
                                      "Fuso hor\u00e1rio de ver\u00e3o do Turcomenist\u00e3o", "TMST",
                                      "Hor\u00E1rio do Turcomenist\u00E3o", "TMT"};
@@ -252,29 +255,30 @@
         String WIT[] = new String[] {"Fuso hor\u00e1rio da Indon\u00e9sia Ocidental", "WIB",
                                      "Fuso hor\u00e1rio de ver\u00e3o da Indon\u00e9sia Ocidental", "WIST",
                                      "Hor\u00E1rio da Indon\u00E9sia Ocidental", "WIB"};
-        String WST_AUS[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Ocidental (Austr\u00E1lia)", "WST",
-                                         "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental (Austr\u00E1lia)", "WST",
-                                         "Hor\u00E1rio Ocidental (Austr\u00E1lia)", "WT"};
+        String WST_AUS[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Ocidental (Austr\u00E1lia)", "AWST",
+                                         "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental (Austr\u00E1lia)", "AWDT",
+                                         "Hor\u00E1rio Ocidental (Austr\u00E1lia)", "AWT"};
         String SAMOA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Samoa", "SST",
                                        "Hor\u00e1rio de luz natural de Samoa", "SDT",
                                        "Hor\u00E1rio da Samoa", "ST"};
-        String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WST",
+        String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WSST",
                                            "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSDT",
                                            "Fuso Hor\u00E1rio de Samoa Ocidental", "WST"};
         String ChST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Chamorro", "ChST",
                                       "Hor\u00e1rio de luz natural de Chamorro", "ChDT",
                                       "Hor\u00E1rio de Chamorro", "ChT"};
-        String VICTORIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Victoria)", "EST",
-                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Victoria)", "EST",
-                                          "Hor\u00E1rio do Leste (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Victoria)", "AEST",
+                                          "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Victoria)", "AEDT",
+                                          "Hor\u00E1rio do Leste (Victoria)", "AET"};
         String UTC[] = new String[] {"Tempo universal coordenado", "UTC",
                                      "Tempo universal coordenado", "UTC",
                                      "Hor\u00E1rio Universal Coordenado", "UTC"};
         String UZT[] = new String[] {"Fuso hor\u00e1rio do Uzbequist\u00e3o", "UZT",
                                      "Fuso hor\u00e1rio de ver\u00e3o do Uzbequist\u00e3o", "UZST",
                                      "Hor\u00E1rio do Uzbequist\u00E3o", "UZT"};
-        String WART[] = new String[] {"Fuso hor\u00e1rio da Argentina Ocidental", "WART",
-                                      "Fuso hor\u00e1rio de ver\u00e3o da Argentina Ocidental", "WARST"};
+        String XJT[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o da China", "XJT",
+                                     "Hor\u00e1rio de luz natural da China", "XJDT",
+                                     "Hor\u00E1rio da China", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "Fuso hor\u00e1rio de ver\u00e3o da Groenl\u00e2ndia Ocidental", "WGST",
                                               "Hor\u00E1rio da Groenl\u00E2ndia Ocidental", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Hor\u00E1rio Padr\u00E3o de Metlakatla", "MeST",
-                                                 "Hor\u00E1rio de Luz Natural de Metlakatla", "MeDT",
-                                                 "Hor\u00E1rio de Metlakatla", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Fuso hor\u00e1rio padr\u00e3o de S\u00e3o Pedro e Miquelon", "PMST",
                                                "Hor\u00e1rio de luz natural de S\u00e3o Pedro e Miquelon", "PMDT",
@@ -607,6 +609,7 @@
                                           "Fuso hor\u00e1rio de ver\u00e3o de Brunei", "BNST",
                                           "Hor\u00E1rio de Brunei", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Fuso hor\u00e1rio de Choibalsan", "CHOT",
                                               "Fuso hor\u00e1rio de ver\u00e3o de Choibalsan", "CHOST",
                                               "Hor\u00E1rio de Choibalsan", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Fuso hor\u00e1rio de Hovd", "HOVT",
                                         "Fuso hor\u00e1rio de ver\u00e3o de Hovd", "HOVST",
                                         "Hor\u00E1rio de Hovd", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Fuso hor\u00e1rio de Irkutsk", "IRKT",
-                                           "Fuso hor\u00e1rio de ver\u00e3o de Irkutsk", "IRKST",
-                                           "Hor\u00E1rio de Irkutsk", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"Fuso hor\u00e1rio da Indon\u00e9sia Oriental", "WIT",
@@ -646,16 +647,14 @@
                                              "Fuso hor\u00e1rio de ver\u00e3o de Petropavlovsk-Kamchatski", "PETST",
                                              "Hor\u00E1rio de Petropavlovsk-Kamchatski", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Hor\u00E1rio de Khandyga", "YAKT",
                                             "Hor\u00E1rio de Ver\u00E3o de Khandyga", "YAKST",
                                             "Hor\u00E1rio de Khandyga", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Fuso hor\u00e1rio de Krasnoyarsk", "KRAT",
-                                               "Fuso hor\u00e1rio de ver\u00e3o de Krasnoyarsk", "KRAST",
-                                               "Hor\u00E1rio de Krasnoyarsk", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Hor\u00E1rio das Filipinas", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Fuso hor\u00e1rio de Uralsk", "ORAT",
                                         "Fuso hor\u00e1rio de ver\u00e3o de Uralsk", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Hor\u00E1rio de Ust-Nera", "VLAT",
                                             "Hor\u00E1rio de Ver\u00E3o de Ust-Nera", "VLAST",
                                             "Hor\u00E1rio de Ust-Nera", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Fuso Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "CWST",
-                                              "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental Central (Austr\u00E1lia)", "CWST",
-                                              "Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "CWT"}},
+            {"Australia/Eucla", new String[] {"Fuso Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "ACWST",
+                                              "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental Central (Austr\u00E1lia)", "ACWDT",
+                                              "Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Fuso hor\u00e1rio de Volgogrado", "VOLT",
-                                               "Fuso hor\u00e1rio de ver\u00e3o de Volgogrado", "VOLST",
-                                               "Hor\u00E1rio de Volgogrado", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Acre, normaltid", "ACT",
                                      "Acre, sommartid", "ACST",
                                      "Acre, normaltid", "ACT"};
-        String ADELAIDE[] = new String[] {"Central standardtid (Sydaustralien)", "CST",
-                                          "Central sommartid (South Australia)", "CST",
-                                          "Central tid (Sydaustralien)", "CT"};
+        String ADELAIDE[] = new String[] {"Central standardtid (Sydaustralien)", "ACST",
+                                          "Central sommartid (South Australia)", "ACDT",
+                                          "Central tid (Sydaustralien)", "ACT"};
         String AGT[] = new String[] {"Argentina, normaltid", "ART",
                                      "Argentina, sommartid", "ARST",
                                      "Argentinsk tid", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"Bangladesh, normaltid", "BDT",
                                      "Bangladesh, sommartid", "BDST",
                                      "Bangladeshisk tid", "BDT"};
-        String BRISBANE[] = new String[] {"\u00D6stlig standardtid (Queensland)", "EST",
-                                          "\u00D6stlig sommartid (Queensland)", "EST",
-                                          "\u00D6stlig tid (Queensland)", "ET"};
-        String BROKEN_HILL[] = new String[] {"Central standardtid (Sydaustralien/New South Wales)", "CST",
-                                             "Central sommartid (South Australia/New South Wales)", "CST",
-                                             "Central tid (Sydaustralien/New South Wales)", "CT"};
+        String BRISBANE[] = new String[] {"\u00D6stlig standardtid (Queensland)", "AEST",
+                                          "\u00D6stlig sommartid (Queensland)", "AEDT",
+                                          "\u00D6stlig tid (Queensland)", "AET"};
+        String BROKEN_HILL[] = new String[] {"Central standardtid (Sydaustralien/New South Wales)", "ACST",
+                                             "Central sommartid (South Australia/New South Wales)", "ACDT",
+                                             "Central tid (Sydaustralien/New South Wales)", "ACT"};
         String BRT[] = new String[] {"Brasilien, normaltid", "BRT",
                                      "Brasilien, sommartid", "BRST",
                                      "Brasiliansk tid", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"Kuba, normaltid", "CST",
                                       "Kuba, sommartid", "CDT",
                                       "Kubansk tid", "CT"};
-        String DARWIN[] = new String[] {"Central standardtid (Nordterritoriet)", "CST",
-                                        "Central sommartid (Nordterritoriet)", "CST",
-                                        "Central tid (Nordterritoriet)", "CT"};
+        String DARWIN[] = new String[] {"Central standardtid (Nordterritoriet)", "ACST",
+                                        "Central sommartid (Nordterritoriet)", "ACDT",
+                                        "Central tid (Nordterritoriet)", "ACT"};
         String DUBLIN[] = new String[] {"Greenwichtid", "GMT",
                                         "Irland, sommartid", "IST",
                                         "Irl\u00E4ndsk tid", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"Eastern, normaltid", "EST",
                                      "Eastern, sommartid", "EDT",
                                      "\u00D6stlig tid", "ET"};
-        String EST_NSW[] = new String[] {"\u00D6stlig standardtid (New South Wales)", "EST",
-                                         "\u00D6stlig sommartid (New South Wales)", "EST",
-                                         "\u00D6stlig tid (New South Wales)", "ET"};
+        String EST_NSW[] = new String[] {"\u00D6stlig standardtid (New South Wales)", "AEST",
+                                         "\u00D6stlig sommartid (New South Wales)", "AEDT",
+                                         "\u00D6stlig tid (New South Wales)", "AET"};
         String FET[] = new String[] {"Kaliningradtid", "FET",
                                      "\u00D6steuropeisk sommartid", "FEST",
                                      "Kaliningradtid", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"Indokinesisk tid", "ICT",
                                      "Indokinesisk sommartid", "ICST",
                                      "Indokinesisk tid", "ICT"};
+        String IRKT[] = new String[] {"Irkutsk, normaltid", "IRKT",
+                                      "Irkutsk, sommartid", "IRKST",
+                                      "Irkutsk-tid", "IRKT"};
         String IRT[] = new String[] {"Iran, normaltid", "IRST",
                                      "Iran, sommartid", "IRDT",
                                      "Iransk tid", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"Japan, normaltid", "JST",
                                      "Japan, sommartid", "JDT",
                                      "Japansk tid", "JT"};
+        String KRAT[] = new String[] {"Krasnojarsk, normaltid", "KRAT",
+                                      "Krasnojarsk, sommartid", "KRAST",
+                                      "Krasnojarsk-tid", "KRAT"};
         String KST[] = new String[] {"Korea, normaltid", "KST",
                                      "Korea, sommartid", "KDT",
                                      "Koreansk tid", "KT"};
         String LORD_HOWE[] = new String[] {"Lord Howe, normaltid", "LHST",
-                                           "Lord Howe, sommartid", "LHST",
+                                           "Lord Howe, sommartid", "LHDT",
                                            "Lord Howe-tid", "LHT"};
         String MHT[] = new String[] {"Marshall\u00f6arna, normaltid", "MHT",
                                      "Marshall\u00f6arna, sommartid", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"Singapore, normaltid", "SGT",
                                      "Singapore, sommartid", "SGST",
                                      "Singapore-tid", "SGT"};
-        String SLST[] = new String[] {"Greenwichtid", "GMT",
-                                      "Sierra Leone, sommartid", "SLST",
-                                      "Sierra Leone-tid", "SLT"};
-        String TASMANIA[] = new String[] {"\u00D6stlig standardtid (Tasmania)", "EST",
-                                          "\u00D6stlig sommartid (Tasmanien)", "EST",
-                                          "\u00D6stlig tid (Tasmania)", "ET"};
+        String TASMANIA[] = new String[] {"\u00D6stlig standardtid (Tasmania)", "AEST",
+                                          "\u00D6stlig sommartid (Tasmanien)", "AEDT",
+                                          "\u00D6stlig tid (Tasmania)", "AET"};
         String TMT[] = new String[] {"Turkmenistan, normaltid", "TMT",
                                      "Turkmenistan, sommartid", "TMST",
                                      "Turkmensk tid", "TMT"};
         String ULAT[]= new String[] {"Ulaanbaatar, normaltid", "ULAT",
                                      "Ulaanbaatar, sommartid", "ULAST",
                                      "Ulaanbaatar-tid", "ULAT"};
-        String WART[] = new String[] {"V\u00e4stargentina, normaltid", "WART",
-                                      "V\u00e4stargentina, sommartid", "WARST"};
         String WAT[] = new String[] {"V\u00e4stafrikansk tid", "WAT",
                                      "V\u00e4stafrikansk sommartid", "WAST",
                                      "V\u00E4stafrikansk tid", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"V\u00e4stindonesisk tid", "WIB",
                                      "V\u00e4stindonesisk sommartid", "WIST",
                                      "V\u00E4stindonesisk tid", "WIB"};
-        String WST_AUS[] = new String[] {"Western Standard Time (Australien)", "WST",
-                                         "V\u00E4stlig sommartid (Australien)", "WST",
-                                         "V\u00E4stlig tid (Australien)", "WT"};
+        String WST_AUS[] = new String[] {"Western Standard Time (Australien)", "AWST",
+                                         "V\u00E4stlig sommartid (Australien)", "AWDT",
+                                         "V\u00E4stlig tid (Australien)", "AWT"};
         String SAMOA[] = new String[] {"Samoa, normaltid", "SST",
                                        "Samoa, sommartid", "SDT",
                                        "Samoansk tid", "ST"};
-        String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WST",
+        String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WSST",
                                            "V\u00e4stsamoansk sommartid", "WSDT",
                                            "V\u00E4stsamoansk tid", "WST"};
         String ChST[] = new String[] {"Chamorro, normaltid", "ChST",
                                       "Chamorro, sommartid", "ChDT",
                                       "Chamorros tid", "ChT"};
-        String VICTORIA[] = new String[] {"\u00D6stlig standardtid (Victoria)", "EST",
-                                          "\u00D6stlig sommartid (Victoria)", "EST",
-                                          "\u00D6stlig tid (Victoria)", "ET"};
+        String VICTORIA[] = new String[] {"\u00D6stlig standardtid (Victoria)", "AEST",
+                                          "\u00D6stlig sommartid (Victoria)", "AEDT",
+                                          "\u00D6stlig tid (Victoria)", "AET"};
         String UTC[] = new String[] {"Koordinerad universell tid", "UTC",
                                      "Koordinerad universell tid", "UTC",
                                      "UTC (koordinerad v\u00E4rldstid)", "UTC"};
         String UZT[] = new String[] {"Uzbekistan, normaltid", "UZT",
                                      "Uzbekistan, sommartid", "UZST",
                                      "Uzbekisk tid", "UZT"};
+        String XJT[] = new String[] {"Kina, normaltid", "XJT",
+                                     "Kina, sommartid", "XJDT",
+                                     "Kinesisk tid", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "V\u00e4stra Gr\u00f6nland, sommartid", "WGST",
                                               "V\u00E4stgr\u00F6nl\u00E4ndsk tid", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"Metlakatla, normaltid", "MeST",
-                                                 "Metlakatla, sommartid", "MeDT",
-                                                 "Metlakatla-tid", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"Saint-Pierre-et-Miquelon, normaltid", "PMST",
                                                "Saint-Pierre-et-Miquelon, sommartid", "PMDT",
@@ -612,6 +614,7 @@
                                               "Choibalsan-tid", "CHOT"}},
             {"Asia/Chongqing", CTT},
             {"Asia/Chungking", CTT},
+            {"Asia/Chita", IRKT},
             {"Asia/Colombo", IST},
             {"Asia/Dacca", BDT},
             {"Asia/Dhaka", BDT},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"Hovd, normaltid", "HOVT",
                                         "Hovd, sommartid", "HOVST",
                                         "Hovd-tid", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Irkutsk, normaltid", "IRKT",
-                                           "Irkutsk, sommartid", "IRKST",
-                                           "Irkutsk-tid", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"\u00d6stindonesisk tid", "WIT",
@@ -646,16 +647,14 @@
                                              "Petropavlovsk-Kamtjatka, sommartid", "PETST",
                                              "Petropavlovsk-Kamtjatskij-tid", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"Khandyga, normaltid", "YAKT",
                                             "Khandyga, sommartid", "YAKST",
                                             "Khandyga, normaltid", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"Krasnojarsk, normaltid", "KRAT",
-                                               "Krasnojarsk, sommartid", "KRAST",
-                                               "Krasnojarsk-tid", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "Filippinsk tid", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Oral, normaltid", "ORAT",
                                         "Oral, sommartid", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"Ust-Nera, normaltid", "VLAT",
                                             "Ust-Nera, sommartid", "VLAST",
                                             "Ust-Nera, normaltid", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"Central v\u00E4stlig normaltid (Australien)", "CWST",
-                                              "Central v\u00E4stlig sommartid (Australien)", "CWST",
-                                              "Central v\u00E4stlig tid (Australien)", "CWT"}},
+            {"Australia/Eucla", new String[] {"Central v\u00E4stlig normaltid (Australien)", "ACWST",
+                                              "Central v\u00E4stlig sommartid (Australien)", "ACWDT",
+                                              "Central v\u00E4stlig tid (Australien)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"Volgograd-tid", "VOLT",
-                                               "Volgograd, sommartid", "VOLST",
-                                               "Volgograd, normaltid", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Acre \u65f6\u95f4", "ACT",
                                      "Acre \u590f\u4ee4\u65f6", "ACST",
                                      "Acre \u65f6\u95f4", "ACT"};
-        String ADELAIDE[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CST",
-                                          "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CST",
-                                          "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CT"};
+        String ADELAIDE[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACST",
+                                          "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACDT",
+                                          "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACT"};
         String AGT[] = new String[] {"\u963f\u6839\u5ef7\u65f6\u95f4", "ART",
                                      "\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "ARST",
                                      "\u963F\u6839\u5EF7\u65F6\u95F4", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"\u5b5f\u52a0\u62c9\u65f6\u95f4", "BDT",
                                      "\u5b5f\u52a0\u62c9\u590f\u4ee4\u65f6", "BDST",
                                      "\u5B5F\u52A0\u62C9\u65F6\u95F4", "BDT"};
-        String BRISBANE[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u6606\u58EB\u5170)", "EST",
-                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u6606\u58EB\u5170)", "EST",
-                                          "\u4E1C\u90E8\u65F6\u95F4 (\u6606\u58EB\u5170)", "ET"};
-        String BROKEN_HILL[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CST",
-                                             "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CST",
-                                             "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CT"};
+        String BRISBANE[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u6606\u58EB\u5170)", "AEST",
+                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u6606\u58EB\u5170)", "AEDT",
+                                          "\u4E1C\u90E8\u65F6\u95F4 (\u6606\u58EB\u5170)", "AET"};
+        String BROKEN_HILL[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACST",
+                                             "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACDT",
+                                             "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACT"};
         String BRT[] = new String[] {"\u5df4\u897f\u5229\u4e9a\u65f6\u95f4", "BRT",
                                      "\u5df4\u897f\u5229\u4e9a\u590f\u4ee4\u65f6", "BRST",
                                      "\u5DF4\u897F\u5229\u4E9A\u65F6\u95F4", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"\u53e4\u5df4\u6807\u51c6\u65f6\u95f4", "CST",
                                       "\u53e4\u5df4\u590f\u4ee4\u65f6", "CDT",
                                       "\u53E4\u5DF4\u65F6\u95F4", "CT"};
-        String DARWIN[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5317\u9886\u5730)", "CST",
-                                        "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5317\u9886\u5730)", "CST",
-                                        "\u4E2D\u90E8\u65F6\u95F4 (\u5317\u90E8\u5730\u533A)", "CT"};
+        String DARWIN[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5317\u9886\u5730)", "ACST",
+                                        "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5317\u9886\u5730)", "ACDT",
+                                        "\u4E2D\u90E8\u65F6\u95F4 (\u5317\u90E8\u5730\u533A)", "ACT"};
         String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u65f6\u95f4", "GMT",
                                         "\u7231\u5c14\u5170\u590f\u4ee4\u65f6", "IST",
                                         "\u7231\u5C14\u5170\u65F6\u95F4", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "EST",
                                      "\u4e1c\u90e8\u590f\u4ee4\u65f6", "EDT",
                                      "\u4E1C\u90E8\u65F6\u95F4", "ET"};
-        String EST_NSW[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "EST",
-                                         "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u65B0\u5357\u5A01\u5C14\u65AF)", "EST",
-                                         "\u4E1C\u90E8\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "ET"};
+        String EST_NSW[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AEST",
+                                         "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AEDT",
+                                         "\u4E1C\u90E8\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AET"};
         String FET[] = new String[] {"\u8FDC\u4E1C\u6B27\u65F6\u95F4", "FET",
                                      "\u8FDC\u4E1C\u6B27\u590F\u4EE4\u65F6", "FEST",
                                      "\u8FDC\u4E1C\u6B27\u65F6\u95F4", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"\u5370\u5ea6\u652f\u90a3\u65f6\u95f4", "ICT",
                                      "\u5370\u5ea6\u652f\u90a3\u590f\u4ee4\u65f6", "ICST",
                                      "\u5370\u5EA6\u652F\u90A3\u65F6\u95F4", "ICT"};
+        String IRKT[] = new String[] {"\u4f0a\u5c14\u5e93\u6b21\u514b\u65f6\u95f4", "IRKT",
+                                      "\u4f0a\u5c14\u5e93\u6b21\u514b\u590f\u4ee4\u65f6", "IRKST",
+                                      "\u4F0A\u5C14\u5E93\u6B21\u514B\u65F6\u95F4", "IRKT"};
         String IRT[] = new String[] {"\u4f0a\u6717\u6807\u51c6\u65f6\u95f4", "IRST",
                                      "\u4f0a\u6717\u590f\u4ee4\u65f6", "IRDT",
                                      "\u4F0A\u6717\u65F6\u95F4", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"\u65e5\u672c\u6807\u51c6\u65f6\u95f4", "JST",
                                      "\u65e5\u672c\u590f\u4ee4\u65f6", "JDT",
                                      "\u65E5\u672C\u65F6\u95F4", "JT"};
+        String KRAT[] = new String[] {"\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u65f6\u95f4", "KRAT",
+                                      "\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u590f\u4ee4\u65f6", "KRAST",
+                                      "\u514B\u62C9\u65AF\u8BFA\u4E9A\u5C14\u65AF\u514B\u65F6\u95F4", "KRAT"};
         String KST[] = new String[] {"\u97e9\u56fd\u6807\u51c6\u65f6\u95f4", "KST",
                                      "\u97e9\u56fd\u590f\u4ee4\u65f6", "KDT",
                                      "\u97E9\u56FD\u65F6\u95F4", "KT"};
         String LORD_HOWE[] = new String[] {"\u8c6a\u516c\u6807\u51c6\u65f6\u95f4", "LHST",
-                                           "\u8c6a\u516c\u590f\u4ee4\u65f6", "LHST",
+                                           "\u8c6a\u516c\u590f\u4ee4\u65f6", "LHDT",
                                            "\u8C6A\u516C\u65F6\u95F4", "LHT"};
         String MHT[] = new String[] {"\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u65f6\u95f4", "MHT",
                                      "\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u590f\u4ee4\u65f6", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"\u65b0\u52a0\u5761\u65f6\u95f4", "SGT",
                                      "\u65b0\u52a0\u5761\u590f\u4ee4\u65f6", "SGST",
                                      "\u65B0\u52A0\u5761\u65F6\u95F4", "SGT"};
-        String SLST[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u65f6\u95f4", "GMT",
-                                      "\u585e\u62c9\u5229\u6602\u590f\u4ee4\u65f6", "SLST",
-                                      "\u585E\u62C9\u91CC\u6602\u65F6\u95F4", "SLT"};
-        String TASMANIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "EST",
-                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "EST",
-                                          "\u4E1C\u90E8\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "ET"};
+        String TASMANIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AEST",
+                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AEDT",
+                                          "\u4E1C\u90E8\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AET"};
         String TMT[] = new String[] {"\u571f\u5e93\u66fc\u65f6\u95f4", "TMT",
                                      "\u571f\u5e93\u66fc\u590f\u4ee4\u65f6", "TMST",
                                      "\u571F\u5E93\u66FC\u65F6\u95F4", "TMT"};
         String ULAT[]= new String[] {"\u5e93\u4f26\u65f6\u95f4", "ULAT",
                                      "\u5e93\u4f26\u590f\u4ee4\u65f6", "ULAST",
                                      "\u5E93\u4F26\u65F6\u95F4", "ULAT"};
-        String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u65f6\u95f4", "WART",
-                                      "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "WARST"};
         String WAT[] = new String[] {"\u897f\u975e\u65f6\u95f4", "WAT",
                                      "\u897f\u975e\u590f\u4ee4\u65f6", "WAST",
                                      "\u897F\u975E\u65F6\u95F4", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"\u897f\u5370\u5ea6\u5c3c\u897f\u4e9a\u65f6\u95f4", "WIB",
                                      "\u897f\u5370\u5ea6\u5c3c\u897f\u4e9a\u590f\u4ee4\u65f6", "WIST",
                                      "\u897F\u5370\u5EA6\u5C3C\u897F\u4E9A\u65F6\u95F4", "WIB"};
-        String WST_AUS[] = new String[] {"\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "WST",
-                                         "\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "WST",
-                                         "\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "WT"};
+        String WST_AUS[] = new String[] {"\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "AWST",
+                                         "\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "AWDT",
+                                         "\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "AWT"};
         String SAMOA[] = new String[] {"\u8428\u6469\u4e9a\u7fa4\u5c9b\u6807\u51c6\u65f6\u95f4", "SST",
                                        "\u8428\u6469\u4e9a\u7fa4\u5c9b\u590f\u4ee4\u65f6", "SDT",
                                        "\u8428\u6469\u4E9A\u65F6\u95F4", "ST"};
-        String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WST",
+        String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WSST",
                                            "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSDT",
                                            "\u897F\u8428\u6469\u4E9A\u65F6\u95F4", "WST"};
         String ChST[] = new String[] {"Chamorro \u6807\u51c6\u65f6\u95f4", "ChST",
                                       "Chamorro \u590f\u4ee4\u65f6", "ChDT",
                                       "\u67E5\u6469\u6D1B\u65F6\u95F4", "ChT"};
-        String VICTORIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "EST",
-                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u7EF4\u591A\u5229\u4E9A)", "EST",
-                                          "\u4E1C\u90E8\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "ET"};
+        String VICTORIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "AEST",
+                                          "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u7EF4\u591A\u5229\u4E9A)", "AEDT",
+                                          "\u4E1C\u90E8\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "AET"};
         String UTC[] = new String[] {"\u534f\u8c03\u4e16\u754c\u65f6\u95f4", "UTC",
                                      "\u534f\u8c03\u4e16\u754c\u65f6\u95f4", "UTC",
                                      "\u534F\u8C03\u4E16\u754C\u65F6\u95F4", "UTC"};
         String UZT[] = new String[] {"\u4e4c\u5179\u522b\u514b\u65af\u5766\u65f6\u95f4", "UZT",
                                      "\u4e4c\u5179\u522b\u514b\u65af\u5766\u590f\u4ee4\u65f6", "UZST",
                                      "\u4E4C\u5179\u522B\u514B\u65AF\u5766\u65F6\u95F4", "UZT"};
+        String XJT[] = new String[] {"\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", "XJT",
+                                     "\u4e2d\u56fd\u590f\u4ee4\u65f6", "XJDT",
+                                     "\u4E2D\u56FD\u65F6\u95F4", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "\u897f\u683c\u6797\u5170\u5c9b\u590f\u4ee4\u65f6", "WGST",
                                               "\u897F\u683C\u6797\u5170\u5C9B\u65F6\u95F4", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"\u6885\u7279\u62C9\u5361\u7279\u62C9\u6807\u51C6\u65F6\u95F4", "MeST",
-                                                 "\u6885\u7279\u62C9\u5361\u7279\u62C9\u590F\u4EE4\u65F6", "MeDT",
-                                                 "\u6885\u7279\u62C9\u5361\u7279\u62C9\u65F6\u95F4", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u6807\u51c6\u65f6\u95f4", "PMST",
                                                "\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u590f\u4ee4\u65f6", "PMDT",
@@ -607,6 +609,7 @@
                                           "\u6587\u83b1\u590f\u4ee4\u65f6", "BNST",
                                           "\u6587\u83B1\u65F6\u95F4", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"Choibalsan \u65f6\u95f4", "CHOT",
                                               "Choibalsan \u590f\u4ee4\u65f6", "CHOST",
                                               "Choibalsan \u65F6\u95F4", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"\u79d1\u5e03\u591a\u65f6\u95f4", "HOVT",
                                         "\u79d1\u5e03\u591a\u590f\u4ee4\u65f6", "HOVST",
                                         "\u79D1\u5E03\u591A\u65F6\u95F4", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"\u4f0a\u5c14\u5e93\u6b21\u514b\u65f6\u95f4", "IRKT",
-                                           "\u4f0a\u5c14\u5e93\u6b21\u514b\u590f\u4ee4\u65f6", "IRKST",
-                                           "\u4F0A\u5C14\u5E93\u6B21\u514B\u65F6\u95F4", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"\u4e1c\u5370\u5ea6\u5c3c\u897f\u4e9a\u65f6\u95f4", "WIT",
@@ -646,16 +647,14 @@
                                              "\u5f7c\u5f97\u7f57\u5df4\u752b\u6d1b\u592b\u65af\u514b\u590f\u4ee4\u65f6", "PETST",
                                              "\u5F7C\u5F97\u7F57\u5DF4\u752B\u6D1B\u592B\u65AF\u514B\u65F6\u95F4", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"\u6C49\u5FB7\u52A0\u65F6\u95F4", "YAKT",
                                             "\u6C49\u5FB7\u52A0\u590F\u4EE4\u65F6", "YAKST",
                                             "\u6C49\u5FB7\u52A0\u65F6\u95F4", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u65f6\u95f4", "KRAT",
-                                               "\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u590f\u4ee4\u65f6", "KRAST",
-                                               "\u514B\u62C9\u65AF\u8BFA\u4E9A\u5C14\u65AF\u514B\u65F6\u95F4", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "\u83F2\u5F8B\u5BBE\u65F6\u95F4", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"Oral \u65f6\u95f4", "ORAT",
                                         "Oral \u590f\u4ee4\u65f6", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", CTT},
             {"Asia/Tel_Aviv", ISRAEL},
             {"Asia/Tashkent", UZT},
@@ -708,7 +710,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"\u4E4C\u65AF\u5B63\u6D85\u62C9\u65F6\u95F4", "VLAT",
                                             "\u4E4C\u65AF\u5B63\u6D85\u62C9\u590F\u4EE4\u65F6", "VLAST",
                                             "\u4E4C\u65AF\u5B63\u6D85\u62C9\u65F6\u95F4", "VLAT"}},
@@ -750,9 +752,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "CWT"}},
+            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "ACWST",
+                                              "\u4E2D\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "ACWDT",
+                                              "\u4E2D\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -818,7 +820,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -853,9 +855,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"\u4f0f\u5c14\u52a0\u683c\u52d2\u65f6\u95f4", "VOLT",
-                                               "\u4f0f\u5c14\u52a0\u683c\u52d2\u590f\u4ee4\u65f6", "VOLST",
-                                               "\u4F0F\u5C14\u52A0\u683C\u52D2\u65F6\u95F4", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,9 +48,9 @@
         String ACT[] = new String[] {"Acre \u6642\u9593", "ACT",
                                      "Acre \u590f\u4ee4\u6642\u9593", "ACST",
                                      "Acre \u6642\u9593", "ACT"};
-        String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "CST",
-                                          "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340)", "CST",
-                                          "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "CT"};
+        String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "ACST",
+                                          "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340)", "ACDT",
+                                          "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "ACT"};
         String AGT[] = new String[] {"\u963f\u6839\u5ef7\u6642\u9593", "ART",
                                      "\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "ARST",
                                      "\u963F\u6839\u5EF7\u6642\u9593", "ART"};
@@ -72,12 +72,12 @@
         String BDT[] = new String[] {"\u5b5f\u52a0\u62c9\u6642\u9593", "BDT",
                                      "\u5b5f\u52a0\u62c9\u590f\u4ee4\u6642\u9593", "BDST",
                                      "\u5B5F\u52A0\u62C9\u6642\u9593", "BDT"};
-        String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u6606\u58EB\u862D)", "EST",
-                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u6606\u58EB\u862D)", "EST",
-                                          "\u6771\u90E8\u6642\u9593 (\u6606\u58EB\u862D)", "ET"};
-        String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "CST",
-                                             "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "CST",
-                                             "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8/\u65B0\u5357\u5A01\u723E\u65AF)", "CT"};
+        String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u6606\u58EB\u862D)", "AEST",
+                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u6606\u58EB\u862D)", "AEDT",
+                                          "\u6771\u90E8\u6642\u9593 (\u6606\u58EB\u862D)", "AET"};
+        String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "ACST",
+                                             "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "ACDT",
+                                             "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8/\u65B0\u5357\u5A01\u723E\u65AF)", "ACT"};
         String BRT[] = new String[] {"\u5df4\u897f\u5229\u4e9e\u6642\u9593", "BRT",
                                      "\u5df4\u897f\u5229\u4e9e\u590f\u4ee4\u6642\u9593", "BRST",
                                      "\u5DF4\u897F\u5229\u4E9E\u6642\u9593", "BRT"};
@@ -111,9 +111,9 @@
         String CUBA[] = new String[] {"\u53e4\u5df4\u6a19\u6e96\u6642\u9593", "CST",
                                       "\u53e4\u5df4\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT",
                                       "\u53E4\u5DF4\u6642\u9593", "CT"};
-        String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "CST",
-                                        "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "CST",
-                                        "\u6FB3\u5927\u5229\u4E9E\u4E2D\u90E8\u6642\u9593 (\u5317\u65B9\u5340\u57DF)", "CT"};
+        String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "ACST",
+                                        "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "ACDT",
+                                        "\u6FB3\u5927\u5229\u4E9E\u4E2D\u90E8\u6642\u9593 (\u5317\u65B9\u5340\u57DF)", "ACT"};
         String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u5e73\u5747\u6642\u9593", "GMT",
                                         "\u611b\u723e\u862d\u590f\u4ee4\u6642\u9593", "IST",
                                         "\u611B\u723E\u862D\u6587\u6642\u9593", "IT"};
@@ -132,9 +132,9 @@
         String EST[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593", "EST",
                                      "\u6771\u65b9\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "EDT",
                                      "\u7F8E\u570B\u6771\u90E8\u6642\u9593", "ET"};
-        String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "EST",
-                                         "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "EST",
-                                         "\u6771\u90E8\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "ET"};
+        String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AEST",
+                                         "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AEDT",
+                                         "\u6771\u90E8\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AET"};
         String FET[] = new String[] {"\u6771\u6B50\u5167\u9678\u6642\u9593", "FET",
                                      "\u6771\u6B50\u5167\u9678\u590F\u4EE4\u6642\u9593", "FEST",
                                      "\u6771\u6B50\u5167\u9678\u6642\u9593", "FET"};
@@ -165,6 +165,9 @@
         String ICT[] = new String[] {"\u5370\u5ea6\u652f\u90a3\u6642\u9593", "ICT",
                                      "\u5370\u5ea6\u652f\u90a3\u590f\u4ee4\u6642\u9593", "ICST",
                                      "\u5370\u5EA6\u652F\u90A3\u6642\u9593", "ICT"};
+        String IRKT[] = new String[] {"Irkutsk \u6642\u9593", "IRKT",
+                                      "Irkutsk \u590f\u4ee4\u6642\u9593", "IRKST",
+                                      "\u4F0A\u723E\u5EAB\u6B21\u514B\u6642\u9593", "IRKT"};
         String IRT[] = new String[] {"\u4f0a\u6717\u6a19\u6e96\u6642\u9593", "IRST",
                                      "\u4f0a\u6717\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "IRDT",
                                      "\u4F0A\u6717\u6642\u9593", "IRT"};
@@ -177,11 +180,14 @@
         String JST[] = new String[] {"\u65e5\u672c\u6a19\u6e96\u6642\u9593", "JST",
                                      "\u65e5\u672c\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "JDT",
                                      "\u65E5\u672C\u6642\u9593", "JT"};
+        String KRAT[] = new String[] {"\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u6642\u9593", "KRAT",
+                                      "\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u590f\u4ee4\u6642\u9593", "KRAST",
+                                      "\u514B\u62C9\u65AF\u8AFE\u4E9E\u723E\u65AF\u514B\u6642\u9593", "KRAT"};
         String KST[] = new String[] {"\u97d3\u570b\u6a19\u6e96\u6642\u9593", "KST",
                                      "\u97d3\u570b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "KDT",
                                      "\u97D3\u570B\u6642\u9593", "KT"};
         String LORD_HOWE[] = new String[] {"\u8c6a\u52f3\u7235\u5cf6\u6a19\u6e96\u6642\u9593", "LHST",
-                                           "\u8c6a\u52f3\u7235\u5cf6\u590f\u4ee4\u6642\u9593", "LHST",
+                                           "\u8c6a\u52f3\u7235\u5cf6\u590f\u4ee4\u6642\u9593", "LHDT",
                                            "\u8C6A\u52F3\u7235\u5CF6\u6642\u9593", "LHT"};
         String MHT[] = new String[] {"\u99ac\u7d39\u723e\u7fa4\u5cf6\u6642\u9593", "MHT",
                                      "\u99ac\u7d39\u723e\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "MHST",
@@ -231,20 +237,15 @@
         String SGT[] = new String[] {"\u65b0\u52a0\u5761\u6642\u9593", "SGT",
                                      "\u65b0\u52a0\u5761\u590f\u4ee4\u6642\u9593", "SGST",
                                      "\u65B0\u52A0\u5761\u6642\u9593", "SGT"};
-        String SLST[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u5e73\u5747\u6642\u9593", "GMT",
-                                      "\u7345\u5b50\u5c71\u590f\u4ee4\u6642\u9593", "SLST",
-                                      "\u7345\u5B50\u5C71\u6642\u9593", "SLT"};
-        String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "EST",
-                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "EST",
-                                          "\u6FB3\u5927\u5229\u4E9E\u6771\u90E8\u6642\u9593 (\u5854\u65AF\u99AC\u5C3C\u4E9E\u5CF6)", "ET"};
+        String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "AEST",
+                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "AEDT",
+                                          "\u6FB3\u5927\u5229\u4E9E\u6771\u90E8\u6642\u9593 (\u5854\u65AF\u99AC\u5C3C\u4E9E\u5CF6)", "AET"};
         String TMT[] = new String[] {"\u571f\u5eab\u66fc\u6642\u9593", "TMT",
                                      "\u571f\u5eab\u66fc\u590f\u4ee4\u6642\u9593", "TMST",
                                      "\u571F\u5EAB\u66FC\u6642\u9593", "TMT"};
         String ULAT[]= new String[] {"\u5eab\u502b\u6642\u9593", "ULAT",
                                      "\u5eab\u502b\u590f\u4ee4\u6642\u9593", "ULAST",
                                      "\u5EAB\u502B\u6642\u9593", "ULAT"};
-          String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u6642\u9593", "WART",
-                                      "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "WARST"};
         String WAT[] = new String[] {"\u897f\u975e\u6642\u9593", "WAT",
                                      "\u897f\u975e\u590f\u4ee4\u6642\u9593", "WAST",
                                      "\u897F\u975E\u6642\u9593", "WAT"};
@@ -254,27 +255,30 @@
         String WIT[] = new String[] {"\u897f\u5370\u5c3c\u6642\u9593", "WIB",
                                      "\u897f\u5370\u5c3c\u590f\u4ee4\u6642\u9593", "WIST",
                                      "\u897F\u5370\u5C3C\u6642\u9593", "WIB"};
-        String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WST",
-                                         "\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WST",
-                                         "\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WT"};
+        String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWST",
+                                         "\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWDT",
+                                         "\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWT"};
         String SAMOA[] = new String[] {"\u85a9\u6469\u4e9e\u6a19\u6e96\u6642\u9593", "SST",
                                        "\u85a9\u6469\u4e9e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "SDT",
                                        "\u85A9\u6469\u4E9E\u6642\u9593", "ST"};
-        String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WST",
+        String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WSST",
                                            "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSDT",
                                            "\u897F\u85A9\u6469\u4E9E\u6642\u9593", "WST"};
         String ChST[] = new String[] {"\u67e5\u83ab\u6d1b\u6a19\u6e96\u6642\u9593", "ChST",
                                      "\u67e5\u83ab\u6d1b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "ChDT",
                                      "\u67E5\u83AB\u7F85\u6642\u9593", "ChT"};
-        String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "EST",
-                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "EST",
-                                          "\u6771\u90E8\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E)", "ET"};
+        String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "AEST",
+                                          "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "AEDT",
+                                          "\u6771\u90E8\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E)", "AET"};
         String UTC[] = new String[] {"\u5354\u8abf\u4e16\u754c\u6642\u9593", "UTC",
                                      "\u5354\u8abf\u4e16\u754c\u6642\u9593", "UTC",
                                      "\u5354\u8ABF\u4E16\u754C\u6642\u9593", "UTC"};
         String UZT[] = new String[] {"\u70cf\u8332\u5225\u514b\u65af\u5766\u6642\u9593", "UZT",
                                      "\u70cf\u8332\u5225\u514b\u65af\u5766\u590f\u4ee4\u6642\u9593", "UZST",
                                      "\u70CF\u8332\u5225\u514B\u65AF\u5766\u6642\u9593", "UZT"};
+        String XJT[] = new String[] {"\u4e2d\u570b\u6a19\u6e96\u6642\u9593", "XJT",
+                                     "\u4e2d\u570b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "XJDT",
+                                     "\u4E2D\u570B\u6642\u9593", "XJT"};
 
         return new Object[][] {
             {"America/Los_Angeles", PST},
@@ -336,7 +340,7 @@
             {"Africa/Djibouti", EAT},
             {"Africa/Douala", WAT},
             {"Africa/El_Aaiun", WET},
-            {"Africa/Freetown", SLST},
+            {"Africa/Freetown", GMT},
             {"Africa/Gaborone", CAT},
             {"Africa/Harare", CAT},
             {"Africa/Johannesburg", SAST},
@@ -437,7 +441,7 @@
                                               "\u897f\u683c\u6797\u862d\u5cf6\u590f\u4ee4\u6642\u9593", "WGST",
                                               "\u897F\u683C\u9675\u862D\u6642\u9593", "WGT"}},
             {"America/Goose_Bay", AST},
-            {"America/Grand_Turk", EST},
+            {"America/Grand_Turk", AST},
             {"America/Grenada", AST},
             {"America/Guadeloupe", AST},
             {"America/Guatemala", CST},
@@ -484,9 +488,7 @@
             {"America/Mendoza", AGT},
             {"America/Menominee", CST},
             {"America/Merida", CST},
-            {"America/Metlakatla", new String[] {"\u6885\u7279\u62C9\u5361\u7279\u62C9\u6A19\u6E96\u6642\u9593", "MeST",
-                                                 "\u6885\u7279\u62C9\u5361\u7279\u62C9\u65E5\u5149\u7BC0\u7D04\u6642\u9593", "MeDT",
-                                                 "\u6885\u7279\u62C9\u5361\u7279\u62C9\u6642\u9593", "MeT"}},
+            {"America/Metlakatla", PST},
             {"America/Mexico_City", CST},
             {"America/Miquelon", new String[] {"\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u6a19\u6e96\u6642\u9593", "PMST",
                                                "\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PMDT",
@@ -607,6 +609,7 @@
                                           "\u6c76\u840a\u590f\u4ee4\u6642\u9593", "BNST",
                                           "\u6C76\u840A\u6642\u9593", "BNT"}},
             {"Asia/Calcutta", IST},
+            {"Asia/Chita", IRKT},
             {"Asia/Choibalsan", new String[] {"\u5de7\u5df4\u5c71 (Choibalsan) \u6642\u9593", "CHOT",
                                               "\u5de7\u5df4\u5c71 (Choibalsan) \u590f\u4ee4\u6642\u9593", "CHOST",
                                               "\u5DE7\u5DF4\u5C71 (Choibalsan) \u6642\u9593", "CHOT"}},
@@ -631,9 +634,7 @@
             {"Asia/Hovd", new String[] {"\u4faf\u5fb7 (Hovd) \u6642\u9593", "HOVT",
                                         "\u4faf\u5fb7 (Hovd) \u590f\u4ee4\u6642\u9593", "HOVST",
                                         "\u4FAF\u5FB7 (Hovd) \u6642\u9593", "HOVT"}},
-            {"Asia/Irkutsk", new String[] {"Irkutsk \u6642\u9593", "IRKT",
-                                           "Irkutsk \u590f\u4ee4\u6642\u9593", "IRKST",
-                                           "\u4F0A\u723E\u5EAB\u6B21\u514B\u6642\u9593", "IRKT"}},
+            {"Asia/Irkutsk", IRKT},
             {"Asia/Istanbul", EET},
             {"Asia/Jakarta", WIT},
             {"Asia/Jayapura", new String[] {"\u6771\u5370\u5ea6\u5c3c\u897f\u4e9e\u6642\u9593", "WIT",
@@ -646,16 +647,14 @@
                                              "Petropavlovsk-Kamchatski \u590f\u4ee4\u6642\u9593", "PETST",
                                              "Petropavlovsk-Kamchatski \u6642\u9593", "PETT"}},
             {"Asia/Karachi", PKT},
-            {"Asia/Kashgar", CTT},
+            {"Asia/Kashgar", XJT},
             {"Asia/Kathmandu", NPT},
             {"Asia/Katmandu", NPT},
             {"Asia/Khandyga", new String[] {"\u6F22\u5730\u52A0 (Khandyga) \u6642\u9593", "YAKT",
                                             "\u6F22\u5730\u52A0 (Khandyga) \u590F\u4EE4\u6642\u9593", "YAKST",
                                             "\u6F22\u5730\u52A0 (Khandyga) \u6642\u9593", "YAKT"}},
             {"Asia/Kolkata", IST},
-            {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u6642\u9593", "KRAT",
-                                               "\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u590f\u4ee4\u6642\u9593", "KRAST",
-                                               "\u514B\u62C9\u65AF\u8AFE\u4E9E\u723E\u65AF\u514B\u6642\u9593", "KRAT"}},
+            {"Asia/Krasnoyarsk", KRAT},
             {"Asia/Kuala_Lumpur", MYT},
             {"Asia/Kuching", MYT},
             {"Asia/Kuwait", ARAST},
@@ -670,7 +669,7 @@
                                           "\u83F2\u5F8B\u8CD3\u6642\u9593", "PHT"}},
             {"Asia/Muscat", GST},
             {"Asia/Nicosia", EET},
-            {"Asia/Novokuznetsk", NOVT},
+            {"Asia/Novokuznetsk", KRAT},
             {"Asia/Novosibirsk", NOVT},
             {"Asia/Oral", new String[] {"\u6b50\u4f5b\u6642\u9593", "ORAT",
                                         "\u6b50\u4f5b\u590f\u4ee4\u6642\u9593", "ORAST",
@@ -696,6 +695,9 @@
             {"Asia/Samarkand", UZT},
             {"Asia/Seoul", KST},
             {"Asia/Singapore", SGT},
+            {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET",
+                                                 "Srednekolymsk Daylight Time", "SREDT",
+                                                 "Srednekolymsk Time", "SRET"}},
             {"Asia/Taipei", new String[] {"\u53f0\u7063\u6a19\u6e96\u6642\u9593", "TST",
                                           "\u53f0\u7063\u590f\u4ee4\u6642\u9593", "TDT",
                                           "\u53f0\u7063\u6642\u9593", "TT"}},
@@ -710,7 +712,7 @@
             {"Asia/Ujung_Pandang", CIT},
             {"Asia/Ulaanbaatar", ULAT},
             {"Asia/Ulan_Bator", ULAT},
-            {"Asia/Urumqi", CTT},
+            {"Asia/Urumqi", XJT},
             {"Asia/Ust-Nera", new String[] {"\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u6642\u9593", "VLAT",
                                             "\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u590F\u4EE4\u6642\u9593", "VLAST",
                                             "\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u6642\u9593", "VLAT"}},
@@ -752,9 +754,9 @@
             {"Australia/Canberra", EST_NSW},
             {"Australia/Currie", EST_NSW},
             {"Australia/Darwin", DARWIN},
-            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWST",
-                                              "\u4E2D\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWT"}},
+            {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWST",
+                                              "\u4E2D\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWDT",
+                                              "\u4E2D\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWT"}},
             {"Australia/Hobart", TASMANIA},
             {"Australia/LHI", LORD_HOWE},
             {"Australia/Lindeman", BRISBANE},
@@ -820,7 +822,7 @@
             {"Europe/Isle_of_Man", GMTBST},
             {"Europe/Istanbul", EET},
             {"Europe/Jersey", GMTBST},
-            {"Europe/Kaliningrad", FET},
+            {"Europe/Kaliningrad", EET},
             {"Europe/Kiev", EET},
             {"Europe/Lisbon", WET},
             {"Europe/Ljubljana", CET},
@@ -855,9 +857,7 @@
             {"Europe/Vatican", CET},
             {"Europe/Vienna", CET},
             {"Europe/Vilnius", EET},
-            {"Europe/Volgograd", new String[] {"\u4f0f\u723e\u52a0\u683c\u52d2\u6642\u9593", "VOLT",
-                                               "\u4f0f\u723e\u52a0\u683c\u52d2\u590f\u4ee4\u6642\u9593", "VOLST",
-                                               "\u4F0F\u723E\u52A0\u683C\u52D2\u6642\u9593", "VOLT"}},
+            {"Europe/Volgograd", MSK},
             {"Europe/Warsaw", CET},
             {"Europe/Zagreb", CET},
             {"Europe/Zaporozhye", EET},
--- a/jdk/src/jdk.runtime/share/native/common-unpack/unpack.cpp	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/src/jdk.runtime/share/native/common-unpack/unpack.cpp	Wed Jul 05 20:00:59 2017 +0200
@@ -32,9 +32,12 @@
  *    the printf format %ld is correct and use of %lld will cause warning
  *    errors from some compilers (gcc/g++).
  * _LP64 can be explicitly set (used on Linux).
+ * Should be checking for the Visual C++ since the _LP64 is set on the 64-bit
+ * systems but the correct format prefix for 64-bit integers is ll.
  * Solaris compilers will define __sparcv9 or __x86_64 on 64bit compilations.
  */
-#if defined(_LP64) || defined(__sparcv9) || defined(__x86_64)
+#if !defined (_MSC_VER) && \
+    (defined(_LP64) || defined(__sparcv9) || defined(__x86_64))
   #define LONG_LONG_FORMAT "%ld"
   #define LONG_LONG_HEX_FORMAT "%lx"
 #else
--- a/jdk/test/ProblemList.txt	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 20:00:59 2017 +0200
@@ -124,7 +124,7 @@
 
 # jdk_management
 
-# 8046351
+# 8044591
 com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java   generic-all
 com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java          generic-all
 # 8056143
@@ -139,6 +139,9 @@
 com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java  aix-all
 javax/management/MBeanServer/OldMBeanServerTest.java            aix-all
 
+# 8050115
+javax/management/monitor/GaugeMonitorDeadlockTest.java          generic-all
+
 ############################################################################
 
 # jdk_math
@@ -272,6 +275,9 @@
 
 # jdk_util
 
+# 8051641
+sun/util/calendar/zi/TestZoneInfo310.java                        generic-all
+
 ############################################################################
 
 # jdk_instrument
@@ -283,15 +289,13 @@
 # 8031482
 sun/tools/jcmd/TestJcmdSanity.java				windows-all
 
-# 8033104
-sun/jvmstat/monitor/MonitoredVm/CR6672135.java			generic-all
-
 # 8027668
 sun/tools/jstatd/TestJstatdDefaults.java                generic-all
 sun/tools/jstatd/TestJstatdServer.java                  generic-all
 sun/tools/jstatd/TestJstatdPort.java                    generic-all
+sun/tools/jstatd/TestJstatdPortAndServer.java                    generic-all
 
-# 8046355
+# 8046285 8027668 
 sun/tools/jstatd/TestJstatdExternalRegistry.java                generic-all
 
 # 6456333
--- a/jdk/test/TEST.groups	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/TEST.groups	Wed Jul 05 20:00:59 2017 +0200
@@ -124,18 +124,29 @@
 
 jdk_security3 = \
     javax/security  \
+    -javax/security/auth/kerberos \
     com/sun/security \
+    -com/sun/security/jgss \
     com/sun/org/apache/xml/internal/security \
     sun/security \
+    -sun/security/krb5 \
+    -sun/security/jgss \
     javax/net \
     sun/net/www/protocol/https \
     com/sun/net/ssl \
     lib/security
 
+jdk_security4 = \
+    com/sun/security/jgss \
+    javax/security/auth/kerberos \
+    sun/security/krb5 \
+    sun/security/jgss
+
 jdk_security = \
     :jdk_security1 \
     :jdk_security2 \
-    :jdk_security3
+    :jdk_security3 \
+    :jdk_security4
 
 jdk_text = \
     java/text \
--- a/jdk/test/java/lang/Integer/ParsingTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/Integer/ParsingTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -23,24 +23,22 @@
 
 /*
  * @test
- * @bug 5017980 6576055 8041972
+ * @bug 5017980 6576055 8041972 8055251
  * @summary Test parsing methods
  * @author Joseph D. Darcy
  */
 
-import java.lang.IllegalArgumentException;
 import java.lang.IndexOutOfBoundsException;
 import java.lang.NullPointerException;
 import java.lang.RuntimeException;
 
 /**
- * There are eight methods in java.lang.Integer which transform strings
+ * There are seven methods in java.lang.Integer which transform strings
  * into an int or Integer value:
  *
  * public Integer(String s)
  * public static Integer decode(String nm)
- * public static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex)
- * public static int parseInt(CharSequence s, int radix, int beginIndex)
+ * public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
  * public static int parseInt(String s, int radix)
  * public static int parseInt(String s)
  * public static Integer valueOf(String s, int radix)
@@ -55,20 +53,17 @@
 public class ParsingTest {
 
     public static void main(String... argv) {
-        check("+100", +100);
-        check("-100", -100);
+        check(+100, "+100");
+        check(-100, "-100");
 
-        check("+0", 0);
-        check("-0", 0);
-        check("+00000", 0);
-        check("-00000", 0);
+        check(0, "+0");
+        check(0, "-0");
+        check(0, "+00000");
+        check(0, "-00000");
 
-        check("+00000", 0, 0, 6);
-        check("-00000", 0, 0, 6);
-
-        check("0", 0);
-        check("1", 1);
-        check("9", 9);
+        check(0, "0");
+        check(1, "1");
+        check(9, "9");
 
         checkFailure("");
         checkFailure("\u0000");
@@ -85,41 +80,37 @@
         checkFailure("-+6");
         checkFailure("*100");
 
-        check("test-00000", 0, 4, 10);
-        check("test-12345", -12345, 4, 10);
-        check("xx12345yy", 12345, 2, 7);
+        // check offset based methods
+        check(0, "+00000", 0, 6, 10);
+        check(0, "-00000", 0, 6, 10);
+        check(0, "test-00000", 4, 10, 10);
+        check(-12345, "test-12345", 4, 10, 10);
+        check(12345, "xx12345yy", 2, 7, 10);
+        check(15, "xxFyy", 2, 3, 16);
 
-        checkNumberFormatException("", 10, 0);
-        checkNumberFormatException("100", 10, 3);
-        checkNumberFormatException("+1000000", 10, 8);
-        checkNumberFormatException("-1000000", 10, 8);
-
-        checkNumberFormatException("", 10, 0, 0);
-        checkNumberFormatException("+-6", 10, 0, 3);
-        checkNumberFormatException("1000000", 10, 7);
-        checkNumberFormatException("1000000", 10, 7, 7);
-        checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2);
-        checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2);
+        checkNumberFormatException("", 0, 0, 10);
+        checkNumberFormatException("+-6", 0, 3, 10);
+        checkNumberFormatException("1000000", 7, 7, 10);
+        checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
+        checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
 
-        checkIndexOutOfBoundsException("1000000", 10, 8);
-        checkIndexOutOfBoundsException("1000000", 10, -1);
-        checkIndexOutOfBoundsException("1000000", 10, 10, 4);
-        checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, -1, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, -1, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, 10, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, 10, 2);
-        checkIndexOutOfBoundsException("-1", 10, 0, 3);
-        checkIndexOutOfBoundsException("-1", 10, 2, 3);
-        checkIndexOutOfBoundsException("-1", 10, -1, 2);
+        checkIndexOutOfBoundsException("1000000", 10, 4, 10);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("-1", 0, 3, 10);
+        checkIndexOutOfBoundsException("-1", 2, 3, 10);
+        checkIndexOutOfBoundsException("-1", -1, 2, 10);
 
-        checkNull(10, 0, 1);
-        checkNull(10, -1, 0);
-        checkNull(10, 0, 0);
-        checkNull(10, 0, -1);
+        checkNull(0, 1, 10);
+        checkNull(-1, 0, 10);
+        checkNull(0, 0, 10);
+        checkNull(0, -1, 10);
         checkNull(-1, -1, -1);
     }
 
-    private static void check(String val, int expected) {
+    private static void check(int expected, String val) {
         int n = Integer.parseInt(val);
         if (n != expected)
             throw new RuntimeException("Integer.parseInt failed. String:" +
@@ -137,23 +128,11 @@
         }
     }
 
-    private static void checkNumberFormatException(String val, int radix, int start) {
+    private static void checkNumberFormatException(String val, int start, int end, int radix) {
         int n = 0;
         try {
-            n = Integer.parseInt(val, radix, start);
-            System.err.println("parseInt(" + val + ", " + radix + ", " + start +
-                    ") incorrectly returned " + n);
-            throw new RuntimeException();
-        } catch (NumberFormatException nfe) {
-            ; // Expected
-        }
-    }
-
-    private static void checkNumberFormatException(String val, int radix, int start, int end) {
-        int n = 0;
-        try {
-            n = Integer.parseInt(val, radix, start, end);
-            System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end +
+            n = Integer.parseInt(val, start, end, radix);
+            System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (NumberFormatException nfe) {
@@ -161,11 +140,11 @@
         }
     }
 
-    private static void checkIndexOutOfBoundsException(String val, int radix, int start) {
+    private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
         int n = 0;
         try {
-            n = Integer.parseInt(val, radix, start);
-            System.err.println("parseInt(" + val + ", " + radix + ", " + start +
+            n = Integer.parseInt(val, start, end, radix);
+            System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix  +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (IndexOutOfBoundsException ioob) {
@@ -173,23 +152,11 @@
         }
     }
 
-    private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) {
+    private static void checkNull(int start, int end, int radix) {
         int n = 0;
         try {
-            n = Integer.parseInt(val, radix, start, end);
-            System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end +
-                    ") incorrectly returned " + n);
-            throw new RuntimeException();
-        } catch (IndexOutOfBoundsException ioob) {
-            ; // Expected
-        }
-    }
-
-    private static void checkNull(int radix, int start, int end) {
-        int n = 0;
-        try {
-            n = Integer.parseInt(null, 10, start, end);
-            System.err.println("parseInt(null, " + radix + ", " + start + ", " + end +
+            n = Integer.parseInt(null, start, end, radix);
+            System.err.println("parseInt(null, " + start + ", " + end + ", " + radix +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (NullPointerException npe) {
@@ -197,10 +164,10 @@
         }
     }
 
-    private static void check(String val, int expected, int start, int end) {
-        int n = Integer.parseInt(val, 10, start, end);
+    private static void check(int expected, String val, int start, int end, int radix) {
+        int n = Integer.parseInt(val, start, end, radix);
         if (n != expected)
-            throw new RuntimeException("Integer.parsedInt failed. String:" +
-                    val + ", start: " + start + ", end: " + end + " Result:" + n);
+            throw new RuntimeException("Integer.parsedInt failed. Expected: " + expected + " String: \"" +
+                    val + "\", start: " + start + ", end: " + end + ", radix: " + radix + " Result:" + n);
     }
 }
--- a/jdk/test/java/lang/Integer/Unsigned.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/Integer/Unsigned.java	Wed Jul 05 20:00:59 2017 +0200
@@ -303,6 +303,17 @@
                                       "\tconverting back ''%s'' resulted in %d%n",
                                       value, radix, longString,  intResult);
                 }
+
+                // test offset based parse method
+                intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix",
+                        "prefix".length(), "prefix".length() + longString.length(), radix);
+
+                if (Integer.toUnsignedLong(intResult) != value) {
+                    errors++;
+                    System.err.printf("Bad roundtrip conversion of %d in base %d" +
+                            "\tconverting back ''%s'' resulted in %d%n",
+                            value, radix, longString,  intResult);
+                }
             }
         }
 
--- a/jdk/test/java/lang/Long/ParsingTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/Long/ParsingTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -23,19 +23,18 @@
 
 /*
  * @test
- * @bug 5017980 6576055 8041972
+ * @bug 5017980 6576055 8041972 8055251
  * @summary Test parsing methods
  * @author Joseph D. Darcy
  */
 
 /**
- * There are eight methods in java.lang.Long which transform strings
+ * There are seven methods in java.lang.Long which transform strings
  * into a long or Long value:
  *
  * public Long(String s)
  * public static Long decode(String nm)
  * public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex)
- * public static long parseLong(CharSequence s, int radix, int beginIndex)
  * public static long parseLong(String s, int radix)
  * public static long parseLong(String s)
  * public static Long valueOf(String s, int radix)
@@ -49,17 +48,17 @@
 public class ParsingTest {
 
     public static void main(String... argv) {
-        check("+100", +100L);
-        check("-100", -100L);
+        check(+100L, "+100");
+        check(-100L, "-100");
 
-        check("+0", 0L);
-        check("-0", 0L);
-        check("+00000", 0L);
-        check("-00000", 0L);
+        check(0L, "+0");
+        check(0L, "-0");
+        check(0L, "+00000");
+        check(0L, "-00000");
 
-        check("0", 0L);
-        check("1", 1L);
-        check("9", 9L);
+        check(0L, "0");
+        check(1L, "1");
+        check(9L, "9");
 
         checkFailure("");
         checkFailure("\u0000");
@@ -76,40 +75,36 @@
         checkFailure("-+6");
         checkFailure("*100");
 
-        check("test-00000", 0L, 4, 10);
-        check("test-12345", -12345L, 4, 10);
-        check("xx12345yy", 12345L, 2, 7);
-        check("xx123456789012345yy", 123456789012345L, 2, 17);
+        check(0L, "test-00000", 4, 10, 10);
+        check(-12345L, "test-12345", 4, 10, 10);
+        check(12345L, "xx12345yy", 2, 7, 10);
+        check(123456789012345L, "xx123456789012345yy", 2, 17, 10);
+        check(15L, "xxFyy", 2, 3, 16);
 
-        checkNumberFormatException("100", 10, 3);
-        checkNumberFormatException("", 10, 0);
-        checkNumberFormatException("+1000000", 10, 8);
-        checkNumberFormatException("-1000000", 10, 8);
+        checkNumberFormatException("", 0, 0, 10);
+        checkNumberFormatException("+-6", 0, 3, 10);
+        checkNumberFormatException("1000000", 7, 7, 10);
+        checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
+        checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
 
-        checkNumberFormatException("", 10, 0, 0);
-        checkNumberFormatException("+-6", 10, 0, 3);
-        checkNumberFormatException("1000000", 10, 7, 7);
-        checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2);
-        checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2);
+        checkIndexOutOfBoundsException("", 1, 1, 10);
+        checkIndexOutOfBoundsException("1000000", 10, 4, 10);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("-1", 0, 3, 10);
+        checkIndexOutOfBoundsException("-1", 2, 3, 10);
+        checkIndexOutOfBoundsException("-1", -1, 2, 10);
 
-        checkIndexOutOfBoundsException("", 10, 1, 1);
-        checkIndexOutOfBoundsException("1000000", 10, 10, 4);
-        checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, 10, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, 10, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, -1, 2);
-        checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, -1, 2);
-        checkIndexOutOfBoundsException("-1", 10, 0, 3);
-        checkIndexOutOfBoundsException("-1", 10, 2, 3);
-        checkIndexOutOfBoundsException("-1", 10, -1, 2);
-
-        checkNull(10, 0, 1);
-        checkNull(10, -1, 0);
-        checkNull(10, 0, 0);
-        checkNull(10, 0, -1);
+        checkNull(0, 1, 10);
+        checkNull(-1, 0, 10);
+        checkNull(0, 0, 10);
+        checkNull(0, -1, 10);
         checkNull(-1, -1, -1);
     }
 
-    private static void check(String val, long expected) {
+    private static void check(long expected, String val) {
         long n = Long.parseLong(val);
         if (n != expected)
             throw new RuntimeException("Long.parseLong failed. String:" +
@@ -127,23 +122,11 @@
         }
     }
 
-    private static void checkNumberFormatException(String val, int radix, int start) {
+    private static void checkNumberFormatException(String val, int start, int end, int radix) {
         long n = 0;
         try {
-            n = Long.parseLong(val, radix, start);
-            System.err.println("parseLong(" + val + ", " + radix + ", " + start +
-                    ") incorrectly returned " + n);
-            throw new RuntimeException();
-        } catch (NumberFormatException nfe) {
-            ; // Expected
-        }
-    }
-
-    private static void checkNumberFormatException(String val, int radix, int start, int end) {
-        long n = 0;
-        try {
-            n = Long.parseLong(val, radix, start, end);
-            System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end +
+            n = Long.parseLong(val, start, end, radix);
+            System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (NumberFormatException nfe) {
@@ -151,11 +134,11 @@
         }
     }
 
-    private static void checkIndexOutOfBoundsException(String val, int radix, int start) {
+    private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
         long n = 0;
         try {
-            n = Long.parseLong(val, radix, start);
-            System.err.println("parseLong(" + val + ", " + radix + ", " + start +
+            n = Long.parseLong(val, start, end, radix);
+            System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (IndexOutOfBoundsException ioob) {
@@ -163,23 +146,11 @@
         }
     }
 
-    private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) {
+    private static void checkNull(int start, int end, int radix) {
         long n = 0;
         try {
-            n = Long.parseLong(val, radix, start, end);
-            System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end +
-                    ") incorrectly returned " + n);
-            throw new RuntimeException();
-        } catch (IndexOutOfBoundsException ioob) {
-            ; // Expected
-        }
-    }
-
-    private static void checkNull(int radix, int start, int end) {
-        long n = 0;
-        try {
-            n = Long.parseLong(null, 10, start, end);
-            System.err.println("parseLong(null, " + radix + ", " + start + ", " + end +
+            n = Long.parseLong(null, start, end, radix);
+            System.err.println("parseLong(null, " + start + ", " + end + ", " + radix +
                     ") incorrectly returned " + n);
             throw new RuntimeException();
         } catch (NullPointerException npe) {
@@ -187,10 +158,10 @@
         }
     }
 
-    private static void check(String val, long expected, int start, int end) {
-        long n = Long.parseLong(val, 10, start, end);
+    private static void check(long expected, String val, int start, int end, int radix) {
+        long n = Long.parseLong(val, start, end, radix);
         if (n != expected)
-            throw new RuntimeException("Long.parseLong failed. String:" +
-                    val + ", start: " + start + ", end: " + end + " Result:" + n);
+            throw new RuntimeException("Long.parseLong failed. Expexted: " + expected + " String: \"" +
+                    val + "\", start: " + start + ", end: " + end + " radix: " + radix + " Result: " + n);
     }
 }
--- a/jdk/test/java/lang/Long/Unsigned.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/Long/Unsigned.java	Wed Jul 05 20:00:59 2017 +0200
@@ -289,6 +289,17 @@
                                       "\tconverting back ''%s'' resulted in %d%n",
                                       value, radix, bigString,  longResult);
                 }
+
+                // test offset based parse method
+                longResult = Long.parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(),
+                        "prefix".length() + bigString.length(), radix);
+
+                if (!toUnsignedBigInt(longResult).equals(value)) {
+                    errors++;
+                    System.err.printf("Bad roundtrip conversion of %d in base %d" +
+                            "\tconverting back ''%s'' resulted in %d%n",
+                            value, radix, bigString,  longResult);
+                }
             }
         }
 
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -2160,15 +2160,23 @@
                     else
                         type = type.changeParameterType(j, argType);
                     if (done.add(type))
-                        testInvokers(type);
+                        testInvokersWithCatch(type);
                     MethodType vtype = type.changeReturnType(void.class);
                     if (done.add(vtype))
-                        testInvokers(vtype);
+                        testInvokersWithCatch(vtype);
                 }
             }
         }
     }
 
+    public void testInvokersWithCatch(MethodType type) throws Throwable {
+        try {
+            testInvokers(type);
+        } catch (Throwable ex) {
+            System.out.println("*** testInvokers on "+type+" => ");
+            ex.printStackTrace(System.out);
+        }
+    }
     public void testInvokers(MethodType type) throws Throwable {
         if (verbosity >= 3)
             System.out.println("test invokers for "+type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarargsArrayTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+/* @test
+ * @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int),
+ *          MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int)
+ *
+ * @run main/bootclasspath java.lang.invoke.VarargsArrayTest
+ * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
+ *                         java.lang.invoke.VarargsArrayTest
+ */
+
+/* This might take a while and burn lots of metadata:
+ * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true java.lang.invoke.VarargsArrayTest
+ */
+public class VarargsArrayTest {
+    private static final Class<?> CLASS = VarargsArrayTest.class;
+    private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);
+    private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0);
+    private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE");
+
+    public static void main(String[] args) throws Throwable {
+        testVarargsArray();
+        testVarargsReferenceArray();
+        testVarargsPrimitiveArray();
+    }
+
+    public static void testVarargsArray() throws Throwable {
+        final int MIN = START_ARITY;
+        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
+            MethodHandle target = MethodHandleImpl.varargsArray(nargs);
+            Object[] args = new Object[nargs];
+            for (int i = 0; i < nargs; i++)
+                args[i] = "#"+i;
+            Object res = target.invokeWithArguments(args);
+            assertArrayEquals(args, (Object[])res);
+        }
+    }
+
+    public static void testVarargsReferenceArray() throws Throwable {
+        testTypedVarargsArray(Object[].class);
+        testTypedVarargsArray(String[].class);
+        testTypedVarargsArray(Number[].class);
+    }
+
+    public static void testVarargsPrimitiveArray() throws Throwable {
+        testTypedVarargsArray(int[].class);
+        testTypedVarargsArray(long[].class);
+        testTypedVarargsArray(byte[].class);
+        testTypedVarargsArray(boolean[].class);
+        testTypedVarargsArray(short[].class);
+        testTypedVarargsArray(char[].class);
+        testTypedVarargsArray(float[].class);
+        testTypedVarargsArray(double[].class);
+    }
+
+    private static int nextArgCount(int nargs, int density, int MAX) {
+        if (EXHAUSTIVE)  return nargs + 1;
+        if (nargs >= MAX)  return Integer.MAX_VALUE;
+        int BOT = 20, TOP = MAX-5;
+        if (density < 10) { BOT = 10; MAX = TOP-2; }
+        if (nargs <= BOT || nargs >= TOP) {
+            ++nargs;
+        } else {
+            int bump = Math.max(1, 100 / density);
+            nargs += bump;
+            if (nargs > TOP)  nargs = TOP;
+        }
+        return nargs;
+    }
+
+    private static void testTypedVarargsArray(Class<?> arrayType) throws Throwable {
+        Class<?> elemType = arrayType.getComponentType();
+        int MIN = START_ARITY;
+        int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        int density = 3;
+        if (elemType == int.class || elemType == long.class)  density = 7;
+        if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
+        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
+            Object[] args = makeTestArray(elemType, nargs);
+            MethodHandle varargsArray = MethodHandleImpl.varargsArray(arrayType, nargs);
+            MethodType vaType = varargsArray.type();
+            assertEquals(arrayType, vaType.returnType());
+            if (nargs != 0) {
+                assertEquals(elemType, vaType.parameterType(0));
+                assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1));
+            }
+            assertEquals(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)),
+                         vaType);
+            Object res = varargsArray.invokeWithArguments(args);
+            assertEquals(res.getClass(), arrayType);
+            String resString = toArrayString(res);
+            assertEquals(Arrays.toString(args), resString);
+
+            MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs);
+            MethodType stype = spreader.type();
+            assert(stype == MethodType.methodType(arrayType, arrayType));
+            if (nargs <= 5) {
+                // invoke target as a spreader also:
+                @SuppressWarnings("cast")
+                Object res2 = spreader.invokeWithArguments((Object)res);
+                String res2String = toArrayString(res2);
+                assertEquals(Arrays.toString(args), res2String);
+                // invoke the spreader on a generic Object[] array; check for error
+                try {
+                    Object res3 = spreader.invokeWithArguments((Object)args);
+                    String res3String = toArrayString(res3);
+                    assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+                    assertEquals(Arrays.toString(args), res3String);
+                } catch (ClassCastException ex) {
+                    assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+                }
+            }
+            if (nargs == 0) {
+                // invoke spreader on null arglist
+                Object res3 = spreader.invokeWithArguments((Object)null);
+                String res3String = toArrayString(res3);
+                assertEquals(Arrays.toString(args), res3String);
+            }
+        }
+    }
+
+    private static Object[] makeTestArray(Class<?> elemType, int len) {
+        Wrapper elem = null;
+        if (elemType.isPrimitive())
+            elem = Wrapper.forPrimitiveType(elemType);
+        else if (Wrapper.isWrapperType(elemType))
+            elem = Wrapper.forWrapperType(elemType);
+        Object[] args = new Object[len];
+        for (int i = 0; i < len; i++) {
+            Object arg = i * 100;
+            if (elem == null) {
+                if (elemType == String.class)
+                    arg = "#"+arg;
+                arg = elemType.cast(arg);  // just to make sure
+            } else {
+                switch (elem) {
+                    case BOOLEAN: arg = (i % 3 == 0);           break;
+                    case CHAR:    arg = 'a' + i;                break;
+                    case LONG:    arg = (long)i * 1000_000_000; break;
+                    case FLOAT:   arg = (float)i / 100;         break;
+                    case DOUBLE:  arg = (double)i / 1000_000;   break;
+                }
+                arg = elem.cast(arg, elemType);
+            }
+            args[i] = arg;
+        }
+        return args;
+    }
+
+    private static String toArrayString(Object a) {
+        if (a == null)  return "null";
+        Class<?> elemType = a.getClass().getComponentType();
+        if (elemType == null)  return a.toString();
+        if (elemType.isPrimitive()) {
+            switch (Wrapper.forPrimitiveType(elemType)) {
+                case INT:      return Arrays.toString((int[])a);
+                case BYTE:     return Arrays.toString((byte[])a);
+                case BOOLEAN:  return Arrays.toString((boolean[])a);
+                case SHORT:    return Arrays.toString((short[])a);
+                case CHAR:     return Arrays.toString((char[])a);
+                case FLOAT:    return Arrays.toString((float[])a);
+                case LONG:     return Arrays.toString((long[])a);
+                case DOUBLE:   return Arrays.toString((double[])a);
+            }
+        }
+        return Arrays.toString((Object[])a);
+    }
+
+    public static void assertArrayEquals(Object[] arr1, Object[] arr2) {
+        if (arr1 == null && arr2 == null)  return;
+        if (arr1 != null && arr2 != null && arr1.length == arr2.length) {
+            for (int i = 0; i < arr1.length; i++) {
+                assertEquals(arr1[i], arr2[i]);
+            }
+            return;
+        }
+        throw new AssertionError(Arrays.deepToString(arr1) + " != " + Arrays.deepToString(arr2));
+    }
+
+    public static void assertEquals(Object o1, Object o2) {
+        if (o1 == null && o2 == null)    return;
+        if (o1 != null && o1.equals(o2)) return;
+        throw new AssertionError(o1 + " != " + o2);
+    }
+
+    public static void assertTrue(String msg, boolean b) {
+        if (!b) {
+            throw new AssertionError(msg);
+        }
+    }
+
+    public static void assertFalse(String msg, boolean b) {
+        assertTrue(msg, !b);
+    }
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -63,11 +63,16 @@
         // Use a low young gen size to ensure that the
         // allocated objects are put in the old gen.
         final String nmFlag = "-Xmn" + YOUNG_GEN_SIZE;
-        RunUtil.runTestKeepGcOpts(main, nmFlag);
-        RunUtil.runTestClearGcOpts(main, nmFlag, "-XX:+UseSerialGC");
-        RunUtil.runTestClearGcOpts(main, nmFlag, "-XX:+UseParallelGC");
-        RunUtil.runTestClearGcOpts(main, nmFlag, "-XX:+UseG1GC");
-        RunUtil.runTestClearGcOpts(main, nmFlag, "-XX:+UseConcMarkSweepGC");
+        // Using large pages will change the young gen size,
+        // make sure we don't use them for this test.
+        final String lpFlag = "-XX:-UseLargePages";
+        // Prevent G1 from selecting a large heap region size,
+        // since that would change the young gen size.
+        final String g1Flag = "-XX:G1HeapRegionSize=1m";
+        RunUtil.runTestClearGcOpts(main, nmFlag, lpFlag, "-XX:+UseSerialGC");
+        RunUtil.runTestClearGcOpts(main, nmFlag, lpFlag, "-XX:+UseParallelGC");
+        RunUtil.runTestClearGcOpts(main, nmFlag, lpFlag, "-XX:+UseG1GC", g1Flag);
+        RunUtil.runTestClearGcOpts(main, nmFlag, lpFlag, "-XX:+UseConcMarkSweepGC");
     }
 
     private static volatile boolean listenerInvoked = false;
@@ -155,19 +160,23 @@
             Thread allocator = new AllocatorThread();
             Thread sweeper = new SweeperThread();
 
-            // Now set threshold
+            // The chunk size needs to be larger than YOUNG_GEN_SIZE,
+            // otherwise we will get intermittent failures when objects
+            // end up in the young gen instead of the old gen.
+            final long epsilon = 1024;
+            chunkSize = YOUNG_GEN_SIZE + epsilon;
+
             MemoryUsage mu = mpool.getUsage();
-            chunkSize = (mu.getMax() - mu.getUsed()) / 20;
             newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
 
-            // Sanity check. Make sure the chunkSize is large than the YOUNG_GEN_SIZE
-            // If the chunkSize are lower than the YOUNG_GEN_SIZE, we will get intermittent
-            // failures when objects end up in the young gen instead of the old gen.
+            // Sanity check. Make sure the new threshold isn't too large.
             // Tweak the test if this fails.
-            if (chunkSize < YOUNG_GEN_SIZE) {
-                throw new RuntimeException("TEST FAILED: " +
-                        " chunkSize: " + chunkSize + " is less than YOUNG_GEN_SIZE: " + YOUNG_GEN_SIZE +
-                        " max: " + mu.getMax() + " used: " + mu.getUsed() + " newThreshold: " + newThreshold);
+            final long headRoom = chunkSize * 2;
+            final long max = mu.getMax();
+            if (max != -1 && newThreshold > max - headRoom) {
+                throw new RuntimeException("TEST FAILED: newThreshold: " + newThreshold +
+                        " is too near the maximum old gen size: " + max +
+                        " used: " + mu.getUsed() + " headRoom: " + headRoom);
             }
 
             System.out.println("Setting threshold for " + mpool.getName() +
--- a/jdk/test/java/lang/management/MemoryMXBean/MemoryManagement.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/MemoryManagement.java	Wed Jul 05 20:00:59 2017 +0200
@@ -31,7 +31,7 @@
  * @author  Mandy Chung
  *
  * @build MemoryManagement MemoryUtil
- * @run main/othervm/timeout=600 -Xmn8m MemoryManagement
+ * @run main/othervm/timeout=600 -Xmn8m -XX:+IgnoreUnrecognizedVMOptions -XX:G1HeapRegionSize=1 -XX:-UseLargePages MemoryManagement
  */
 
 import java.lang.management.*;
@@ -103,25 +103,24 @@
 
         Thread allocator = new AllocatorThread();
 
+        // The chunk size needs to be larger than YOUNG_GEN_SIZE,
+        // otherwise we will get intermittent failures when objects
+        // end up in the young gen instead of the old gen.
+        final long epsilon = 1024;
+        chunkSize = YOUNG_GEN_SIZE + epsilon;
+
         // Now set threshold
         MemoryUsage mu = mpool.getUsage();
-        long max = mu.getMax();
-        if (max != -1) {
-            chunkSize = (max - mu.getUsed()) / 20;
-        } else { // 6980984
-            System.gc();
-            chunkSize = Runtime.getRuntime().freeMemory()/20;
-        }
         newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
 
-        // Sanity check. Make sure the chunkSize is large than the YOUNG_GEN_SIZE
-        // If the chunkSize are lower than the YOUNG_GEN_SIZE, we will get intermittent
-        // failures when objects end up in the young gen instead of the old gen.
+        // Sanity check. Make sure the new threshold isn't too large.
         // Tweak the test if this fails.
-        if (chunkSize < YOUNG_GEN_SIZE) {
-            throw new RuntimeException("TEST FAILED: " +
-                    " chunkSize: " + chunkSize + " is less than YOUNG_GEN_SIZE: " + YOUNG_GEN_SIZE +
-                    " max: " + mu.getMax() + " used: " + mu.getUsed() + " newThreshold: " + newThreshold);
+        final long headRoom = chunkSize * 2;
+        final long max = mu.getMax();
+        if (max != -1 && newThreshold > max - headRoom) {
+            throw new RuntimeException("TEST FAILED: newThreshold: " + newThreshold +
+                    " is too near the maximum old gen size: " + max +
+                    " used: " + mu.getUsed() + " headRoom: " + headRoom);
         }
 
         System.out.println("Setting threshold for " + mpool.getName() +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Field/TestFieldReflectValueOf.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 5043030
+ * @summary Verify that the method java.lang.reflect.Field.get(Object) makes
+ *          use of the same caching mechanism as used for autoboxing
+ *          when wrapping values of the primitive types.
+ * @author Andrej Golovnin
+ */
+
+import java.lang.reflect.Field;
+
+public class TestFieldReflectValueOf {
+
+    @SuppressWarnings("unused")
+    private static boolean booleanStaticField;
+    @SuppressWarnings("unused")
+    private static byte byteStaticField;
+    @SuppressWarnings("unused")
+    private static char charStaticField;
+    @SuppressWarnings("unused")
+    private static int intStaticField;
+    @SuppressWarnings("unused")
+    private static long longStaticField;
+    @SuppressWarnings("unused")
+    private static short shortStaticField;
+
+    @SuppressWarnings("unused")
+    private static volatile boolean booleanStaticVolatileField;
+    @SuppressWarnings("unused")
+    private static volatile byte byteStaticVolatileField;
+    @SuppressWarnings("unused")
+    private static volatile char charStaticVolatileField;
+    @SuppressWarnings("unused")
+    private static volatile int intStaticVolatileField;
+    @SuppressWarnings("unused")
+    private static volatile long longStaticVolatileField;
+    @SuppressWarnings("unused")
+    private static volatile short shortStaticVolatileField;
+
+    @SuppressWarnings("unused")
+    private boolean booleanField;
+    @SuppressWarnings("unused")
+    private byte byteField;
+    @SuppressWarnings("unused")
+    private char charField;
+    @SuppressWarnings("unused")
+    private int intField;
+    @SuppressWarnings("unused")
+    private long longField;
+    @SuppressWarnings("unused")
+    private short shortField;
+
+    @SuppressWarnings("unused")
+    private volatile boolean booleanVolatileField;
+    @SuppressWarnings("unused")
+    private volatile byte byteVolatileField;
+    @SuppressWarnings("unused")
+    private volatile char charVolatileField;
+    @SuppressWarnings("unused")
+    private volatile int intVolatileField;
+    @SuppressWarnings("unused")
+    private volatile long longVolatileField;
+    @SuppressWarnings("unused")
+    private volatile short shortVolatileField;
+
+    public static void main(String[] args) {
+        testUnsafeStaticFieldAccessors();
+        testUnsafeQualifiedStaticFieldAccessors();
+        testUnsafeFieldAccessors();
+        testUnsafeQualifiedFieldAccessors();
+    }
+
+    private static void testUnsafeStaticFieldAccessors() {
+        testFieldAccessors(true, false);
+    }
+
+    private static void testUnsafeQualifiedStaticFieldAccessors() {
+        testFieldAccessors(true, true);
+    }
+
+    private static void testUnsafeFieldAccessors() {
+        testFieldAccessors(false, false);
+    }
+
+    private static void testUnsafeQualifiedFieldAccessors() {
+        testFieldAccessors(false, true);
+    }
+
+    private static void testFieldAccessors(boolean checkStatic,
+        boolean checkVolatile)
+    {
+        // Boolean#valueOf test
+        testField(Boolean.TYPE, Boolean.FALSE, checkStatic, checkVolatile);
+        testField(Boolean.TYPE, Boolean.TRUE, checkStatic, checkVolatile);
+
+        // Byte#valueOf test
+        for (int b = Byte.MIN_VALUE; b < (Byte.MAX_VALUE + 1); b++) {
+            testField(Byte.TYPE, Byte.valueOf((byte) b), checkStatic, checkVolatile);
+        }
+
+        // Character#valueOf test
+        for (char c = '\u0000'; c <= '\u007F'; c++) {
+            testField(Character.TYPE, Character.valueOf(c), checkStatic, checkVolatile);
+        }
+
+        // Integer#valueOf test
+        for (int i = -128; i <= 127; i++) {
+            testField(Integer.TYPE, Integer.valueOf(i), checkStatic, checkVolatile);
+        }
+
+        // Long#valueOf test
+        for (long l = -128L; l <= 127L; l++) {
+            testField(Long.TYPE, Long.valueOf(l), checkStatic, checkVolatile);
+        }
+
+        // Short#valueOf test
+        for (short s = -128; s <= 127; s++) {
+            testField(Short.TYPE, Short.valueOf(s), checkStatic, checkVolatile);
+        }
+    }
+
+    private static void testField(Class<?> primType, Object wrappedValue,
+        boolean checkStatic, boolean checkVolatile)
+    {
+        String fieldName = primType.getName();
+        if (checkStatic) {
+            fieldName += "Static";
+        }
+        if (checkVolatile) {
+            fieldName += "Volatile";
+        }
+        fieldName += "Field";
+        try {
+            Field field = TestFieldReflectValueOf.class.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            TestFieldReflectValueOf obj = new TestFieldReflectValueOf();
+            field.set(obj, wrappedValue);
+            Object result = field.get(obj);
+            if (result != wrappedValue) {
+                throw new RuntimeException("The value " + wrappedValue
+                    + " is not cached for the type " + primType);
+            }
+        } catch (  NoSuchFieldException | SecurityException
+                 | IllegalAccessException | IllegalArgumentException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Method/invoke/TestMethodReflectValueOf.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 5043030
+ * @summary Verify that the method java.lang.reflect.Method.invoke(Object, Object...)
+ *          makes use of the same caching mechanism as used for autoboxing
+ *          when wrapping returned values of the primitive types.
+ * @author Andrej Golovnin
+ * @run main/othervm -Dsun.reflect.noInflation=true TestMethodReflectValueOf
+ * @run main/othervm -Dsun.reflect.noInflation=false -Dsun.reflect.inflationThreshold=500 TestMethodReflectValueOf
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+public class TestMethodReflectValueOf {
+
+    public static void main(String[] args) {
+        // When the inflation is disabled we compare values using "=="
+        // as the returned values of the primitive types should be cached
+        // by the same mechanism as used for autoboxing. When the inflation
+        // is enabled we use "equals()"-method to compare values as the native
+        // code still creates new instances to wrap values of the primitive
+        // types.
+        boolean checkIdentity = Boolean.getBoolean("sun.reflect.noInflation");
+
+        // Boolean#valueOf test
+        testMethod(Boolean.TYPE, Boolean.FALSE, checkIdentity);
+        testMethod(Boolean.TYPE, Boolean.TRUE, checkIdentity);
+
+        // Byte#valueOf test
+        for (int b = Byte.MIN_VALUE; b < (Byte.MAX_VALUE + 1); b++) {
+            testMethod(Byte.TYPE, Byte.valueOf((byte) b), checkIdentity);
+        }
+
+        // Character#valueOf test
+        for (char c = '\u0000'; c <= '\u007F'; c++) {
+            testMethod(Character.TYPE, Character.valueOf(c), checkIdentity);
+        }
+
+        // Integer#valueOf test
+        for (int i = -128; i <= 127; i++) {
+            testMethod(Integer.TYPE, Integer.valueOf(i), checkIdentity);
+        }
+
+        // Long#valueOf test
+        for (long l = -128L; l <= 127L; l++) {
+            testMethod(Long.TYPE, Long.valueOf(l), checkIdentity);
+        }
+
+        // Short#valueOf test
+        for (short s = -128; s <= 127; s++) {
+            testMethod(Short.TYPE, Short.valueOf(s), checkIdentity);
+        }
+    }
+
+    public static void testMethod(Class<?> primType, Object wrappedValue,
+            boolean checkIdentity)
+    {
+        String methodName = primType.getName() + "Method";
+        try {
+            Method method = TestMethodReflectValueOf.class.getMethod(methodName, primType);
+            Object result = method.invoke(new TestMethodReflectValueOf(), wrappedValue);
+            if (checkIdentity) {
+                if (result != wrappedValue) {
+                    throw new RuntimeException("The value " + wrappedValue
+                        + " is not cached for the type " + primType);
+                }
+            } else {
+                if (!result.equals(wrappedValue)) {
+                    throw new RuntimeException("The result value " + result
+                        + " is not equal to the expected value "
+                        + wrappedValue + " for the type " + primType);
+                }
+            }
+        } catch (  NoSuchMethodException | SecurityException
+                 | IllegalAccessException | IllegalArgumentException
+                 | InvocationTargetException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public int intMethod(int value) {
+        return value;
+    }
+
+    public long longMethod(long value) {
+        return value;
+    }
+
+    public short shortMethod(short value) {
+        return value;
+    }
+
+    public byte byteMethod(byte value) {
+        return value;
+    }
+
+    public char charMethod(char value) {
+        return value;
+    }
+
+    public boolean booleanMethod(boolean value) {
+        return value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/annotationSharing/AnnotationSharing.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8054987
+ * @summary Test sharing of annotations between Executable/Field instances.
+ *          Sharing should not be noticeable when performing mutating
+ *          operations.
+ * @run testng AnnotationSharing
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import org.testng.annotations.Test;
+
+public class AnnotationSharing {
+    @Test
+    public void testMethodSharing() throws Exception {
+        Method[] m1 = AnnotationSharing.class.getMethods();
+        Method[] m2 = AnnotationSharing.class.getMethods();
+        validateSharingSafelyObservable(m1, m2);
+    }
+
+    @Test
+    public void testDeclaredMethodSharing() throws Exception {
+        Method[] m3 = AnnotationSharing.class.getDeclaredMethods();
+        Method[] m4 = AnnotationSharing.class.getDeclaredMethods();
+        validateSharingSafelyObservable(m3, m4);
+    }
+
+    @Test
+    public void testFieldSharing() throws Exception {
+        Field[] f1 = AnnotationSharing.class.getFields();
+        Field[] f2 = AnnotationSharing.class.getFields();
+        validateSharingSafelyObservable(f1, f2);
+    }
+
+    @Test
+    public void testDeclaredFieldsSharing() throws Exception {
+        Field[] f3 = AnnotationSharing.class.getDeclaredFields();
+        Field[] f4 = AnnotationSharing.class.getDeclaredFields();
+        validateSharingSafelyObservable(f3, f4);
+    }
+
+    @Test
+    public void testMethodSharingOccurs() throws Exception {
+        Method mm1 = AnnotationSharing.class.getDeclaredMethod("m", (Class<?>[])null);
+        Method mm2 = AnnotationSharing.class.getDeclaredMethod("m", (Class<?>[])null);
+        validateAnnotationSharing(mm1, mm2);
+    }
+
+    @Test
+    public void testMethodSharingIsSafe() throws Exception {
+        Method mm1 = AnnotationSharing.class.getDeclaredMethod("m", (Class<?>[])null);
+        Method mm2 = AnnotationSharing.class.getDeclaredMethod("m", (Class<?>[])null);
+        validateAnnotationSharingIsSafe(mm1, mm2);
+        validateArrayValues(mm1.getAnnotation(Baz.class), mm2.getAnnotation(Baz.class));
+    }
+
+    @Test
+    public void testFieldSharingOccurs() throws Exception {
+        Field ff1 = AnnotationSharing.class.getDeclaredField("f");
+        Field ff2 = AnnotationSharing.class.getDeclaredField("f");
+        validateAnnotationSharing(ff1, ff2);
+    }
+
+    @Test
+    public void testFieldSharingIsSafe() throws Exception {
+        Field ff1 = AnnotationSharing.class.getDeclaredField("f");
+        Field ff2 = AnnotationSharing.class.getDeclaredField("f");
+        validateAnnotationSharingIsSafe(ff1, ff2);
+        validateArrayValues(ff1.getAnnotation(Baz.class), ff2.getAnnotation(Baz.class));
+    }
+
+    // Validate that AccessibleObject instances are not shared
+    private static void validateSharingSafelyObservable(AccessibleObject[] m1, AccessibleObject[] m2)
+            throws Exception {
+
+        // Validate that setAccessible works
+        for (AccessibleObject m : m1)
+            m.setAccessible(false);
+
+        for (AccessibleObject m : m2)
+            m.setAccessible(true);
+
+        for (AccessibleObject m : m1)
+            if (m.isAccessible())
+                throw new RuntimeException(m + " should not be accessible");
+
+        for (AccessibleObject m : m2)
+            if (!m.isAccessible())
+                throw new RuntimeException(m + " should be accessible");
+
+        // Validate that methods are still equal()
+        for (int i = 0; i < m1.length; i++)
+            if (!m1[i].equals(m2[i]))
+                throw new RuntimeException(m1[i] + " and " + m2[i] + " should be equal()");
+
+        // Validate that the arrays aren't shared
+        for (int i = 0; i < m1.length; i++)
+            m1[i] = null;
+
+        for (int i = 0; i < m2.length; i++)
+            if (m2[i] == null)
+                throw new RuntimeException("Detected sharing of AccessibleObject arrays");
+    }
+
+    // Validate that annotations are shared
+    private static void validateAnnotationSharing(AccessibleObject m1, AccessibleObject m2) {
+        Bar b1 = m1.getAnnotation(Bar.class);
+        Bar b2 = m2.getAnnotation(Bar.class);
+
+        if (b1 != b2)
+            throw new RuntimeException(b1 + " and " + b2 + " should be ==");
+
+    }
+
+    // Validate that Method instances representing the annotation elements
+    // behave as intended
+    private static void validateAnnotationSharingIsSafe(AccessibleObject m1, AccessibleObject m2)
+            throws Exception {
+        Bar b1 = m1.getAnnotation(Bar.class);
+        Bar b2 = m2.getAnnotation(Bar.class);
+
+        Method mm1 = b1.annotationType().getMethod("value", (Class<?>[]) null);
+        Method mm2 = b2.annotationType().getMethod("value", (Class<?>[]) null);
+        inner(mm1, mm2);
+
+        mm1 = b1.getClass().getMethod("value", (Class<?>[]) null);
+        mm2 = b2.getClass().getMethod("value", (Class<?>[]) null);
+        inner(mm1, mm2);
+
+    }
+    private static void inner(Method mm1, Method mm2)
+            throws Exception {
+        if (!mm1.equals(mm2))
+            throw new RuntimeException(mm1 + " and " + mm2 + " should be equal()");
+
+        mm1.setAccessible(false);
+        mm2.setAccessible(true);
+
+        if (mm1.isAccessible())
+            throw new RuntimeException(mm1 + " should not be accessible");
+
+        if (!mm2.isAccessible())
+            throw new RuntimeException(mm2 + " should be accessible");
+    }
+
+    // Validate that array element values are not shared
+    private static void validateArrayValues(Baz a, Baz b) {
+        String[] s1 = a.value();
+        String[] s2 = b.value();
+
+        s1[0] = "22";
+
+        if (!s2[0].equals("1"))
+            throw new RuntimeException("Mutation of array elements should not be detectable");
+    }
+
+    @Foo @Bar("val") @Baz({"1", "2"})
+    public void m() {
+        return ;
+    }
+
+    @Foo @Bar("someValue") @Baz({"1", "22", "33"})
+    public Object f = new Object();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Foo {}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Bar {
+    String value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Baz {
+    String [] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8029516
+ * @summary Bash on WatchKey.cancel with a view to causing a crash when
+ *    an outstanding I/O operation on directory completes after the
+ *    directory has been closed
+ */
+
+import java.nio.file.ClosedWatchServiceException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import static java.nio.file.StandardWatchEventKinds.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class LotsOfCancels {
+
+    // set to true for any exceptions
+    static volatile boolean failed;
+
+    public static void main(String[] args) throws Exception {
+
+        // create a bunch of directories. Create two tasks for each directory,
+        // one to bash on cancel, the other to poll the events
+        ExecutorService pool = Executors.newCachedThreadPool();
+        try {
+            Path top = Files.createTempDirectory("work");
+            top.toFile().deleteOnExit();
+            for (int i=1; i<=16; i++) {
+                Path dir = Files.createDirectory(top.resolve("dir-" + i));
+                WatchService watcher = FileSystems.getDefault().newWatchService();
+                pool.submit(() -> handle(dir, watcher));
+                pool.submit(() -> poll(watcher));
+            }
+        } finally {
+            pool.shutdown();
+        }
+
+        // give thread pool lots of time to terminate
+        if (!pool.awaitTermination(5L, TimeUnit.MINUTES))
+            throw new RuntimeException("Thread pool did not terminate");
+
+        if (failed)
+            throw new RuntimeException("Test failed, see log for details");
+    }
+
+    /**
+     * Stress the given WatchService, specifically the cancel method, in
+     * the given directory. Closes the WatchService when done.
+     */
+    static void handle(Path dir, WatchService watcher) {
+        try {
+            try {
+                Path file = dir.resolve("anyfile");
+                for (int i=0; i<2000; i++) {
+                    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
+                    Files.createFile(file);
+                    Files.delete(file);
+                    key.cancel();
+                }
+            } finally {
+                watcher.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            failed = true;
+        }
+    }
+
+    /**
+     * Polls the given WatchService in a tight loop. This keeps the event
+     * queue drained, it also hogs a CPU core which seems necessary to
+     * tickle the original bug.
+     */
+    static void poll(WatchService watcher) {
+        try {
+            for (;;) {
+                WatchKey key = watcher.take();
+                if (key != null) {
+                    key.pollEvents();
+                    key.reset();
+                }
+            }
+        } catch (ClosedWatchServiceException expected) {
+            // nothing to do
+        } catch (Exception e) {
+            e.printStackTrace();
+            failed = true;
+        }
+    }
+
+}
+
--- a/jdk/test/java/sql/test/sql/DateTests.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/sql/test/sql/DateTests.java	Wed Jul 05 20:00:59 2017 +0200
@@ -26,261 +26,43 @@
 import java.time.Instant;
 import java.time.LocalDate;
 import static org.testng.Assert.*;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
-public class DateTests {
-
-    public DateTests() {
-    }
-
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-    }
-
-    @BeforeMethod
-    public void setUpMethod() throws Exception {
-    }
+import util.BaseTest;
 
-    @AfterMethod
-    public void tearDownMethod() throws Exception {
-    }
+public class DateTests extends BaseTest {
 
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_year() throws Exception {
-        String expResult = "20009-11-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_year2() throws Exception {
-        String expResult = "09-11-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for an invalid Date string
      */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_year3() throws Exception {
-        String expResult = "-11-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_month() throws Exception {
-        String expResult = "2009-111-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_month3() throws Exception {
-        String expResult = "2009--01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_month4() throws Exception {
-        String expResult = "2009-13-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_day() throws Exception {
-        String expResult = "2009-11-011";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_day3() throws Exception {
-        String expResult = "2009-11-";
-        Date.valueOf(expResult);
+    @Test(dataProvider = "invalidDateValues",
+            expectedExceptions = IllegalArgumentException.class)
+    public void test(String d) throws Exception {
+        Date.valueOf(d);
     }
 
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_day4() throws Exception {
-        String expResult = "2009-11-00";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_day5() throws Exception {
-        String expResult = "2009-11-33";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf() throws Exception {
-        String expResult = "--";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf2() throws Exception {
-        String expResult = "";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf3() throws Exception {
-        String expResult = null;
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf4() throws Exception {
-        String expResult = "-";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf5() throws Exception {
-        String expResult = "2009";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf6() throws Exception {
-        String expResult = "2009-01";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf7() throws Exception {
-        String expResult = "---";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf8() throws Exception {
-        String expResult = "2009-13--1";
-        Date.valueOf(expResult);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Date string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_valueOf10() {
-        String expResult = "1900-1-0";
-        Date.valueOf(expResult);
-    }
-
-    /**
+    /*
      * Test that a date created from a date string is equal to the value
      * returned from toString()
      */
-    @Test
-    public void test_valueOf() {
-        String expResult = "2009-08-30";
-        Date d = Date.valueOf(expResult);
-        assertEquals(expResult, d.toString());
-    }
-
-    /**
-     * Test that two dates, one with lead 0s omitted for month are equal
-     */
-    @Test
-    public void testValid_month_single_digit() {
-        String testDate = "2009-1-01";
-        String expResult = "2009-01-01";
-        Date d = Date.valueOf(testDate);
-        Date d2 = Date.valueOf(expResult);
-        assertEquals(d, d2);
+    @Test(dataProvider = "validDateValues")
+    public void test00(String d, String expectedD) {
+        Date d1 = Date.valueOf(d);
+        Date d2 = Date.valueOf(expectedD);
+        assertTrue(d1.equals(d2) && d2.equals(d1)
+                && d1.toString().equals(expectedD), "Error d1 != d2");
     }
 
-    /**
-     * Test that two dates, one with lead 0s omitted for day are equal
-     */
-    @Test
-    public void testValid_day_single_digit() {
-        String testDate = "2009-11-1";
-        String expResult = "2009-11-01";
-        Date d = Date.valueOf(testDate);
-        Date d2 = Date.valueOf(expResult);
-        assertEquals(d, d2);
-    }
-
-    /**
-     * Test that two dates, one with lead 0s omitted for month and day are equal
-     */
-    @Test
-    public void testValid_month_day_single_digit() {
-        String testDate = "2009-1-1";
-        String expResult = "2009-01-01";
-        Date d = Date.valueOf(testDate);
-        Date d2 = Date.valueOf(expResult);
-        assertEquals(d, d2);
-    }
-
-    /**
+    /*
      * Validate that a Date.after() returns false when same date is compared
      */
     @Test
-    public void test1() {
+    public void test01() {
         Date d = Date.valueOf("1961-08-30");
         assertFalse(d.after(d), "Error d.after(d) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.after() returns true when later date is compared to
      * earlier date
      */
@@ -291,7 +73,7 @@
         assertTrue(d2.after(d), "Error d2.after(d) = false");
     }
 
-    /**
+    /*
      * Validate that a Date.after() returns false when earlier date is compared
      * to later date
      */
@@ -302,7 +84,7 @@
         assertFalse(d.after(d2), "Error d.after(d2) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.after() returns false when date compared to another
      * date created from the original date
      */
@@ -314,7 +96,7 @@
         assertFalse(d2.after(d), "Error d2.after(d) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.before() returns false when same date is compared
      */
     @Test
@@ -323,7 +105,7 @@
         assertFalse(d.before(d), "Error d.before(d) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.before() returns true when earlier date is compared
      * to later date
      */
@@ -334,7 +116,7 @@
         assertTrue(d.before(d2), "Error d.before(d2) = false");
     }
 
-    /**
+    /*
      * Validate that a Date.before() returns false when later date is compared
      * to earlier date
      */
@@ -345,7 +127,7 @@
         assertFalse(d2.before(d), "Error d2.before(d) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.before() returns false when date compared to another
      * date created from the original date
      */
@@ -357,7 +139,7 @@
         assertFalse(d2.before(d), "Error d2.before(d) = true");
     }
 
-    /**
+    /*
      * Validate that a Date.compareTo returns 0 when both Date objects are the
      * same
      */
@@ -367,7 +149,7 @@
         assertTrue(d.compareTo(d) == 0, "Error d.compareTo(d) !=0");
     }
 
-    /**
+    /*
      * Validate that a Date.compareTo returns 0 when both Date objects represent
      * the same date
      */
@@ -378,7 +160,7 @@
         assertTrue(d.compareTo(d2) == 0, "Error d.compareTo(d2) !=0");
     }
 
-    /**
+    /*
      * Validate that a Date.compareTo returns -1 when comparing a date to a
      * later date
      */
@@ -389,7 +171,7 @@
         assertTrue(d.compareTo(d2) == -1, "Error d.compareTo(d2) != -1");
     }
 
-    /**
+    /*
      * Validate that a Date.compareTo returns 1 when comparing a date to an
      * earlier date
      */
@@ -400,7 +182,7 @@
         assertTrue(d2.compareTo(d) == 1, "Error d.compareTo(d2) != 1");
     }
 
-    /**
+    /*
      * Validate that a Date made from a LocalDate are equal
      */
     @Test
@@ -411,7 +193,7 @@
         assertTrue(d.equals(d2), "Error d != d2");
     }
 
-    /**
+    /*
      * Validate that a Date LocalDate value, made from a LocalDate are equal
      */
     @Test
@@ -422,7 +204,7 @@
                 "Error LocalDate values are not equal");
     }
 
-    /**
+    /*
      * Validate an NPE occurs when a null LocalDate is passed to valueOf
      */
     @Test(expectedExceptions = NullPointerException.class)
@@ -431,7 +213,7 @@
         Date.valueOf(ld);
     }
 
-    /**
+    /*
      * Validate an UnsupportedOperationException occurs when toInstant() is
      * called
      */
@@ -441,7 +223,7 @@
         Instant instant = d.toInstant();
     }
 
-    /**
+    /*
      * Validate that two Date objects are equal when one is created from the
      * toString() of the other
      */
@@ -452,7 +234,7 @@
         assertTrue(d.equals(d2) && d2.equals(d), "Error d != d2");
     }
 
-    /**
+    /*
      * Validate that two Date values one created using valueOf and another via a
      * constructor are equal
      */
@@ -464,7 +246,7 @@
         assertTrue(d.equals(d2), "Error d != d2");
     }
 
-    /**
+    /*
      * Validate that two Date values one created using getTime() of the other
      * are equal
      */
@@ -476,7 +258,7 @@
         assertTrue(d.equals(d2), "Error d != d2");
     }
 
-    /**
+    /*
      * Validate that a Date value is equal to itself
      */
     @Test
@@ -486,7 +268,7 @@
         assertTrue(d.equals(d), "Error d != d");
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getHours
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -495,7 +277,7 @@
         d.getHours();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getMinutes
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -504,7 +286,7 @@
         d.getMinutes();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getSeconds
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -513,7 +295,7 @@
         d.getSeconds();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setHours
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -522,7 +304,7 @@
         d.setHours(8);
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setMinutes
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -531,7 +313,7 @@
         d.setMinutes(0);
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setSeconds
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -539,4 +321,53 @@
         Date d = Date.valueOf("1961-08-30");
         d.setSeconds(0);
     }
+
+    /*
+     * DataProvider used to provide Date which are not valid and are used
+     * to validate that an IllegalArgumentException will be thrown from the
+     * valueOf method
+     */
+    @DataProvider(name = "invalidDateValues")
+    private Object[][] invalidDateValues() {
+        return new Object[][]{
+            {"20009-11-01"},
+            {"09-11-01"},
+            {"-11-01"},
+            {"2009-111-01"},
+            {"2009--01"},
+            {"2009-13-01"},
+            {"2009-11-011"},
+            {"2009-11-"},
+            {"2009-11-00"},
+            {"2009-11-33"},
+            {"--"},
+            {""},
+            {null},
+            {"-"},
+            {"2009"},
+            {"2009-01"},
+            {"---"},
+            {"2009-13--1"},
+            {"1900-1-0"},
+            {"2009-01-01 10:50:01"},
+            {"1996-12-10 12:26:19.1"},
+            {"10:50:01"}
+        };
+    }
+
+    /*
+     * DataProvider used to provide Dates which are  valid and are used
+     * to validate that an IllegalArgumentException will not be thrown from the
+     * valueOf method and the corect value from toString() is returned
+     */
+    @DataProvider(name = "validDateValues")
+    private Object[][] validDateValues() {
+        return new Object[][]{
+            {"2009-08-30", "2009-08-30"},
+            {"2009-01-8", "2009-01-08"},
+            {"2009-1-01", "2009-01-01"},
+            {"2009-1-1", "2009-01-01"}
+
+        };
+    }
 }
--- a/jdk/test/java/sql/test/sql/TimeTests.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/sql/test/sql/TimeTests.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,56 +25,35 @@
 import java.sql.Time;
 import java.time.LocalTime;
 import static org.testng.Assert.*;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
-public class TimeTests {
-
-    public TimeTests() {
-    }
+import util.BaseTest;
 
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-    }
+public class TimeTests extends BaseTest {
 
-    @BeforeMethod
-    public void setUpMethod() throws Exception {
-    }
-
-    @AfterMethod
-    public void tearDownMethod() throws Exception {
-    }
-
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getYear
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test1() {
+    public void test01() {
         Time t = Time.valueOf("08:30:59");
         t.getYear();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getMonth
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test2() {
+    public void test02() {
         Time t = Time.valueOf("08:30:59");
         t.getMonth();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getDay
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test3() {
+    public void test03() {
         Time t = Time.valueOf("08:30:59");
         t.getDay();
     }
@@ -83,62 +62,62 @@
      * Validate an IllegalArgumentException is thrown for calling getDate
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test4() {
+    public void test04() {
         Time t = Time.valueOf("08:30:59");
         t.getDate();
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setYear
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test5() {
+    public void test05() {
         Time t = Time.valueOf("08:30:59");
         t.setYear(8);
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setMonth
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test6() {
+    public void test06() {
         Time t = Time.valueOf("08:30:59");
         t.setMonth(8);
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling setDate
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test7() {
+    public void test07() {
         Time t = Time.valueOf("08:30:59");
         t.setDate(30);
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for calling getDate
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test8() {
+    public void test08() {
         Time t = Time.valueOf("08:30:59");
         t.getDate();
     }
 
-    /**
+    /*
      * Validate that a Time made from a toLocalTime() LocalTime are equal
      */
     @Test
-    public void test13() {
+    public void test09() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = Time.valueOf(t.toLocalTime());
         assertTrue(t.equals(t2), "Error t != t2");
     }
 
-    /**
+    /*
      * Validate that a Time LocalTime value, made from a LocalTime are equal
      */
     @Test
-    public void test14() {
+    public void test10() {
         LocalTime lt = LocalTime.of(8, 30, 59);
         Time t = Time.valueOf(lt);
         System.out.println("lt=" + lt + ",t=" + t.toLocalTime());
@@ -146,231 +125,224 @@
                 "Error LocalTime values are not equal");
     }
 
-    /**
+    /*
      * Validate an NPE occurs when a null LocalDate is passed to valueOf
      */
     @Test(expectedExceptions = NullPointerException.class)
-    public void test15() throws Exception {
+    public void test11() throws Exception {
         LocalTime ld = null;
         Time.valueOf(ld);
     }
 
-    /**
+    /*
      * Validate an UnsupportedOperationException occurs when toInstant() is
      * called
      */
     @Test(expectedExceptions = UnsupportedOperationException.class)
-    public void test16() throws Exception {
+    public void test12() throws Exception {
         Time t = new Time(System.currentTimeMillis());
         t.toInstant();
     }
 
-    /**
-     * Validate that a Time made from valueOf(String) returns the same String
-     * from Time.toString();
+    /*
+     * Validate that two Time objects are equal when one is created from the
+     * toString() of the other and that the correct value is returned from
+     * toString()
      */
-    @Test
-    public void test17() {
-        String time = "08:30:59";
-        Time t = Time.valueOf(time);
-        assertTrue(time.equals(t.toString()), "Error t != t2");
+    @Test(dataProvider = "validTimeValues")
+    public void test13(String time, String expected) {
+        Time t1 = Time.valueOf(time);
+        Time t2 = Time.valueOf(t1.toString());
+        assertTrue(t1.equals(t2) && t2.equals(t1)
+                && t1.toString().equals(expected), "Error t1 != t2");
     }
 
-    /**
-     * Validate that two Time objects are equal when one is created from the
-     * toString() of the other
-     */
-    @Test
-    public void test18() {
-        Time t = Time.valueOf("08:30:59");
-        Time t2 = Time.valueOf(t.toString());
-        assertTrue(t.equals(t2) && t2.equals(t), "Error t != t2");
-    }
-
-    /**
+    /*
      * Validate that two Time values one created using valueOf and another via a
      * constructor are equal
      */
     @Test
-    public void test19() {
+    public void test14() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(8, 30, 59);
         assertTrue(t.equals(t2) && t2.equals(t), "Error t != t2");
     }
 
-    /**
+    /*
      * Validate that two Time values one created using valueOf and another via a
      * constructor are equal
      */
     @Test
-    public void test20() {
+    public void test15() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime());
         assertTrue(t.equals(t2) && t2.equals(t), "Error t != t2");
     }
 
-    /**
-     * Validate an IllegalArgumentException is thrown for calling valueOf with a
-     * null String
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test21() {
-        String time = null;
-        Time t = Time.valueOf(time);
-
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Time string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test22() throws Exception {
-        Time.valueOf("1961-08-30");
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Time string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test23() throws Exception {
-        Time.valueOf("8:");
-    }
-
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for an invalid Time string
      */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test24() throws Exception {
-        Time.valueOf("a:b:c");
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Time string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test25() throws Exception {
-        Time.valueOf("08:10");
+    @Test(dataProvider = "invalidTimeValues",
+            expectedExceptions = IllegalArgumentException.class)
+    public void test16(String time) throws Exception {
+        Time.valueOf(time);
     }
 
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Time string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test26() throws Exception {
-        Time.valueOf("08:10:10:10");
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Time string
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void test27() throws Exception {
-        Time.valueOf("08:10:Batman");
-    }
-
-    /**
+    /*
      * Validate that Time.after() returns false when same date is compared
      */
     @Test
-    public void test28() {
+    public void test17() {
         Time t = Time.valueOf("08:30:59");
         assertFalse(t.after(t), "Error t.after(t) = true");
     }
 
-    /**
+    /*
      * Validate that Time.after() returns true when later date is compared to
      * earlier date
      */
     @Test
-    public void test29() {
+    public void test18() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(System.currentTimeMillis());
         assertTrue(t2.after(t), "Error t2.after(t) = false");
     }
 
-    /**
+    /*
      * Validate that Time.after() returns false when earlier date is compared to
      * itself
      */
     @Test
-    public void test30() {
+    public void test19() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime());
         assertFalse(t.after(t2), "Error t.after(t2) = true");
         assertFalse(t2.after(t), "Error t2.after(t) = true");
     }
 
-    /**
+    /*
      * Validate that Time.before() returns false when same date is compared
      */
     @Test
-    public void test31() {
+    public void test20() {
         Time t = Time.valueOf("08:30:59");
         assertFalse(t.before(t), "Error t.before(t) = true");
     }
 
-    /**
+    /*
      * Validate that Time.before() returns true when earlier date is compared to
      * later date
      */
     @Test
-    public void test32() {
+    public void test21() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(System.currentTimeMillis());
         assertTrue(t.before(t2), "Error t.before(t2) = false");
     }
 
-    /**
+    /*
      * Validate that Time.before() returns false when earlier date is compared
      * to itself
      */
     @Test
-    public void test33() {
+    public void test22() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime());
         assertFalse(t.before(t2), "Error t.after(t2) = true");
         assertFalse(t2.before(t), "Error t2.after(t) = true");
     }
 
-    /**
+    /*
      * Validate that Time.compareTo returns 0 when both Date objects are the
      * same
      */
     @Test
-    public void test34() {
+    public void test23() {
         Time t = Time.valueOf("08:30:59");
         assertTrue(t.compareTo(t) == 0, "Error t.compareTo(t) !=0");
     }
 
-    /**
+    /*
      * Validate thatTime.compareTo returns 0 when both Time objects are the same
      */
     @Test
-    public void test35() {
+    public void test24() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime());
         assertTrue(t.compareTo(t2) == 0, "Error t.compareTo(t2) !=0");
     }
 
-    /**
+    /*
      * Validate that Time.compareTo returns 1 when comparing a later Time to an
      * earlier Time
      */
     @Test
-    public void test36() {
+    public void test25() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime() + 1);
         assertTrue(t2.compareTo(t) == 1, "Error t2.compareTo(t) !=1");
     }
 
-    /**
+    /*
      * Validate thatTime.compareTo returns 1 when comparing a later Time to an
      * earlier Time
      */
     @Test
-    public void test37() {
+    public void test26() {
         Time t = Time.valueOf("08:30:59");
         Time t2 = new Time(t.getTime() + 1);
         assertTrue(t.compareTo(t2) == -1, "Error t.compareTo(t2) != -1");
     }
+
+    /*
+     * DataProvider used to provide Time values which are not valid and are used
+     * to validate that an IllegalArgumentException will be thrown from the
+     * valueOf method
+     */
+    @DataProvider(name = "invalidTimeValues")
+    private Object[][] invalidTimeValues() {
+        return new Object[][]{
+            {"2009-11-01 10:50:01"},
+            {"1961-08-30 10:50:01.1"},
+            {"1961-08-30"},
+            {"00:00:00."},
+            {"10:50:0.1"},
+            {":00:00"},
+            {"00::00"},
+            {"00:00:"},
+            {"::"},
+            {" : : "},
+            {"0a:00:00"},
+            {"00:bb:00"},
+            {"00:01:cc"},
+            {"08:10:Batman"},
+            {"08:10:10:10"},
+            {"08:10"},
+            {"a:b:c"},
+            {null},
+            {"8:"}
+        };
+    }
+
+    /*
+     * DataProvider used to provide Time values which are  valid and are used
+     * to validate that an IllegalArgumentException will  not be thrown from the
+     * valueOf method.  It also contains the expected return value from
+     * toString()
+     */
+    @DataProvider(name = "validTimeValues")
+    private Object[][] validTimeValues() {
+        return new Object[][]{
+            {"10:50:01", "10:50:01"},
+            {"01:1:1", "01:01:01"},
+            {"01:01:1", "01:01:01"},
+            {"1:01:1", "01:01:01"},
+            {"2:02:02", "02:02:02"},
+            {"2:02:2", "02:02:02"},
+            {"10:50:1", "10:50:01"},
+            {"00:00:00", "00:00:00"},
+            {"08:30:59", "08:30:59"},
+            {"9:0:1", "09:00:01"}
+        };
+    }
 }
--- a/jdk/test/java/sql/test/sql/TimestampTests.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/sql/test/sql/TimestampTests.java	Wed Jul 05 20:00:59 2017 +0200
@@ -29,66 +29,27 @@
 import java.time.LocalDateTime;
 import java.util.Calendar;
 import static org.testng.Assert.*;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
-public class TimestampTests {
+import util.BaseTest;
 
-    public TimestampTests() {
-    }
+public class TimestampTests extends BaseTest {
 
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-    }
-
-    @BeforeMethod
-    public void setUpMethod() throws Exception {
-    }
-
-    @AfterMethod
-    public void tearDownMethod() throws Exception {
+    /*
+     * Validate an IllegalArgumentException is thrown for an invalid Timestamp
+     */
+    @Test(dataProvider = "invalidTimestampValues",
+            expectedExceptions = IllegalArgumentException.class)
+    public void test(String ts) throws Exception {
+        Timestamp.valueOf(ts);
     }
 
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Timestamp
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_timestamp() throws Exception {
-        String testTS = "2009-11-01-01 10:50";
-        Timestamp.valueOf(testTS);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Timestamp
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_year2() throws Exception {
-        String testTS = "aaaa-11-01-01 10:50";
-        Timestamp.valueOf(testTS);
-    }
-
-    /**
-     * Validate an IllegalArgumentException is thrown for an invalid Timestamp
-     */
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testInvalid_year3() throws Exception {
-        String testTS = "aaaa-11-01 10:50";
-        Timestamp.valueOf(testTS);
-    }
-
-    /**
+    /*
      * Validate that two Timestamp are equal when the leading 0 in seconds is
      * omitted
      */
     @Test
-    public void test1() throws Exception {
+    public void test01() throws Exception {
         String testTS = "2009-01-01 10:50:00";
         String ExpectedTS = "2009-01-01 10:50:0";
         Timestamp ts = Timestamp.valueOf(testTS);
@@ -96,23 +57,23 @@
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate two Timestamps created from the same string are equal
      */
     @Test
-    public void test2() throws Exception {
+    public void test02() throws Exception {
         String testTS = "2009-01-01 10:50:0";
         Timestamp ts = Timestamp.valueOf(testTS);
         Timestamp ts2 = Timestamp.valueOf(testTS);
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one with leading 0s for month and day
      * equals same string without the leading 0s.
      */
     @Test
-    public void test3() throws Exception {
+    public void test03() throws Exception {
         String testTS = "2009-1-1 10:50:0";
         String ExpectedTS = "2009-01-01 10:50:0";
         Timestamp ts = Timestamp.valueOf(testTS);
@@ -120,12 +81,12 @@
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one with leading 0s for day omitted
      * are equal
      */
     @Test
-    public void test4() throws Exception {
+    public void test04() throws Exception {
         String testTS = "2009-01-1 10:50:0";
         String ExpectedTS = "2009-01-01 10:50:0";
         Timestamp ts = Timestamp.valueOf(testTS);
@@ -133,12 +94,12 @@
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one with leading 0s for month omitted
      * and both with leading 0s for seconds omitted are equal
      */
     @Test
-    public void test5() throws Exception {
+    public void test05() throws Exception {
         String testTS = "2009-1-01 10:50:0";
         String ExpectedTS = "2009-01-01 10:50:0";
         Timestamp ts = Timestamp.valueOf(testTS);
@@ -146,11 +107,11 @@
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one with leading 0s for month omitted
      */
     @Test
-    public void test6() throws Exception {
+    public void test06() throws Exception {
         String testTS = "2005-1-01 10:20:50.00";
         String ExpectedTS = "2005-01-01 10:20:50.00";
         Timestamp ts = Timestamp.valueOf(testTS);
@@ -158,52 +119,53 @@
         assertEquals(ts, ts2, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one created using valueOf and another
      * via a constructor are equal
      */
     @Test
-    public void test7() {
+    public void test07() {
 
         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.001");
         Timestamp ts2 = new Timestamp(96, 11, 13, 14, 15, 25, 1000000);
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one created using valueOf and another
      * via a constructor are equal
      */
     @Test
-    public void test8() {
+    public void test08() {
         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.001");
         Timestamp ts2 = new Timestamp(ts1.getTime());
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that two Timestamp values one created using valueOf and another
      * via a constructor are equal
      */
     @Test
-    public void test9() {
+    public void test09() {
 
         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.0");
         Timestamp ts2 = new Timestamp(96, 11, 13, 14, 15, 25, 0);
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that a Timestamp cannot be equal to null
      */
     @Test
     public void test10() {
 
         Timestamp ts1 = Timestamp.valueOf("1961-08-30 14:15:25.745634");
-        assertFalse(ts1.equals(null), "Error ts1 == null");
+        Timestamp ts2 = null;
+        assertFalse(ts1.equals(ts2), "Error ts1 == null");
     }
 
-    /**
+    /*
      * Validate that a Timestamp is equal to another timestamp created with the
      * using the same value but not equal to a Timestamp which is one day later
      */
@@ -218,7 +180,7 @@
 
     }
 
-    /**
+    /*
      * Validate that a Timestamp is equal to itself
      */
     @Test
@@ -227,19 +189,20 @@
         assertTrue(ts1.equals(ts1), "Error ts1 != ts1");
     }
 
-    /**
+    /*
      * Validate that two Timestamps are equal when one is created from the
      * toString() of the other
      */
-    @Test
-    public void test13() {
-        Timestamp ts1 = Timestamp.valueOf("1996-12-10 12:26:19.12");
+    @Test(dataProvider = "validTimestampValues")
+    public void test13(String ts, String expectedTS) {
+        Timestamp ts1 = Timestamp.valueOf(ts);
         Timestamp ts2 = Timestamp.valueOf(ts1.toString());
-        assertTrue(ts1.equals(ts2) && ts2.equals(ts1), "Error ts1 != ts2");
+        assertTrue(ts1.equals(ts2) && ts2.equals(ts1)
+                && ts1.toString().equals(expectedTS), "Error ts1 != ts2");
     }
 
     // Before Tests
-    /**
+    /*
      * Validate that Timestamp ts1 is before Timestamp ts2
      */
     @Test
@@ -249,7 +212,7 @@
         assertTrue(ts1.before(ts2), "Error ts1 not before ts2");
     }
 
-    /**
+    /*
      * Validate that Timestamp ts1 is before Timestamp ts2
      */
     @Test
@@ -259,7 +222,7 @@
         assertTrue(ts1.before(ts2), "Error ts1 not before ts2");
     }
 
-    /**
+    /*
      * Validate that Timestamp ts1 is before Timestamp ts2
      */
     @Test
@@ -289,7 +252,7 @@
         assertFalse(ts1.before(ts1), "Error ts1 before ts1!");
     }
 
-    /**
+    /*
      * Create 3 Timestamps and make sure the 1st is before the other two
      * Timestamps which are each greater than the one before it
      */
@@ -302,7 +265,7 @@
         assertTrue(ts1.before(ts2) && ts2.before(ts3) && ts1.before(ts3));
     }
 
-    /**
+    /*
      * Validate that Timestamp ts1 is not after Timestamp ts2
      */
     @Test
@@ -313,7 +276,7 @@
 
     }
 
-    /**
+    /*
      * Validate that Timestamp ts1 is after Timestamp ts2
      */
     @Test
@@ -323,7 +286,7 @@
         assertTrue(ts1.after(ts2), "Error ts1 not after ts2");
     }
 
-    /**
+    /*
      * Validate that a NullPointerException is thrown if a null is passed to the
      * after method
      */
@@ -333,7 +296,7 @@
         ts1.after(null);
     }
 
-    /**
+    /*
      * Validate that a Timestamp cannot be after itself
      */
     @Test
@@ -341,9 +304,10 @@
         Timestamp ts1 = Timestamp.valueOf("1999-11-10 12:26:19.3456543");
         assertFalse(ts1.after(ts1), "Error ts1 is after itself");
     }
-    /**
-     * Validate that a Timestamp after() works correctly with Timestamp
-     * created using milliseconds
+
+    /*
+     * Validate that a Timestamp after() works correctly with Timestamp created
+     * using milliseconds
      */
     @Test
     public void test24() {
@@ -354,7 +318,7 @@
         assertTrue(ts1.after(ts2) && ts2.after(ts3) && ts1.after(ts3));
     }
 
-    /**
+    /*
      * Validate compareTo returns 0 for Timestamps that are the same
      */
     @Test
@@ -364,7 +328,7 @@
         assertTrue(ts1.compareTo(ts2) == 0, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate compareTo returns -1 for when the 1st Timestamp is earlier than
      * the 2nd Timestamp
      */
@@ -376,7 +340,7 @@
         assertTrue(ts2.compareTo(ts1) == 1, "Error ts1 is not before ts2");
     }
 
-    /**
+    /*
      * Validate compareTo returns 1 for when the 1st Timestamp is later than the
      * 2nd Timestamp
      */
@@ -388,7 +352,7 @@
         assertTrue(ts2.compareTo(ts1) == -1, "Error ts1 not after ts2");
     }
 
-    /**
+    /*
      * Validate compareTo returns 0 for Timestamps that are the same
      */
     @Test
@@ -398,7 +362,7 @@
         assertTrue(ts1.compareTo(ts2) == 0, "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate compareTo returns 0 for Timestamps that are the same
      */
     @Test
@@ -408,7 +372,7 @@
         assertFalse(ts1.equals(d), "Error ts1 == d");
     }
 
-    /**
+    /*
      * Validate compareTo returns 0 for Timestamps that are the same
      */
     @Test
@@ -418,7 +382,7 @@
         assertTrue(ts1.equals(d), "Error ts1 != d");
     }
 
-    /**
+    /*
      * Validate equals returns false when a Date object is passed to equals
      */
     @Test
@@ -428,7 +392,7 @@
         assertFalse(ts1.equals(d), "Error ts1 != d");
     }
 
-    /**
+    /*
      * Validate equals returns false when a Date object is passed to equals
      */
     @Test
@@ -438,7 +402,7 @@
         assertFalse(ts1.equals(d), "Error ts1 != d");
     }
 
-    /**
+    /*
      * Validate equals returns false when a Time object is passed to equals
      */
     @Test
@@ -448,7 +412,7 @@
         assertFalse(ts1.equals(t1), "Error ts1 == t1");
     }
 
-    /**
+    /*
      * Validate equals returns false when a String object is passed to equals
      */
     @Test
@@ -457,7 +421,7 @@
         assertFalse(ts1.equals("1966-08-30 08:08:08"), "Error ts1 == a String");
     }
 
-    /**
+    /*
      * Validate getTime() returns the same value from 2 timeStamps created by
      */
     @Test
@@ -469,7 +433,7 @@
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate getTime() returns the same value from 2 timeStamps when
      * setTime() is used to specify the same value for both Timestamps
      */
@@ -483,7 +447,7 @@
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for an invalid nanos value
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -493,7 +457,7 @@
 
     }
 
-    /**
+    /*
      * Validate an IllegalArgumentException is thrown for an invalid nanos value
      */
     @Test(expectedExceptions = IllegalArgumentException.class)
@@ -501,10 +465,9 @@
         int nanos = 999999999;
         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
         ts1.setNanos(nanos + 1);
-
     }
 
-    /**
+    /*
      * Validate you can set nanos to 999999999
      */
     @Test
@@ -513,10 +476,9 @@
         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
         ts1.setNanos(nanos);
         assertTrue(ts1.getNanos() == nanos, "Error Invalid Nanos value");
-
     }
 
-    /**
+    /*
      * Validate you can set nanos to 0
      */
     @Test
@@ -525,10 +487,9 @@
         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
         ts1.setNanos(nanos);
         assertTrue(ts1.getNanos() == nanos, "Error Invalid Nanos value");
-
     }
 
-    /**
+    /*
      * Validate that a Timestamp made from a LocalDateTime are equal
      */
     @Test
@@ -539,7 +500,7 @@
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that a Timestamp LocalDateTime value, made from a LocalDateTime
      * are equal
      */
@@ -551,7 +512,7 @@
                 "Error LocalDateTime values are not equal");
     }
 
-    /**
+    /*
      * Validate an NPE occurs when a null LocalDateTime is passed to valueOF
      */
     @Test(expectedExceptions = NullPointerException.class)
@@ -560,7 +521,7 @@
         Timestamp.valueOf(ldt);
     }
 
-    /**
+    /*
      * Validate that a Timestamp made from a Instant are equal
      */
     @Test
@@ -571,7 +532,7 @@
         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
     }
 
-    /**
+    /*
      * Validate that a Timestamp made from a Instant are equal
      */
     @Test
@@ -582,7 +543,7 @@
                 "Error Instant values do not match");
     }
 
-    /**
+    /*
      * Validate an NPE occurs when a null instant is passed to from
      */
     @Test(expectedExceptions = NullPointerException.class)
@@ -592,7 +553,7 @@
     }
 
     // Added SQE tests
-    /**
+    /*
      * Create a Timestamp and a 2nd Timestamp that is 1 month earlier and
      * validate that it is not before or after the original Timestamp
      */
@@ -607,7 +568,7 @@
         assertFalse(ts1.before(ts2) || ts2.after(ts1));
     }
 
-    /**
+    /*
      * Create two Timestamps and validate that compareTo returns 1 to indicate
      * the 1st Timestamp is greater than the 2nd Timestamp
      */
@@ -622,7 +583,7 @@
         assertTrue(ts1.compareTo(ts2) == 1);
     }
 
-    /**
+    /*
      * Create two Timestamps and validate that the 1st Timestamp is not equal to
      * the 2nd Timestamp but equal to itself
      */
@@ -637,4 +598,114 @@
         assertTrue(!ts1.equals(ts2) && ts1.equals(ts1));
     }
 
+    /*
+     * Validate that two Timestamps are equal when one is created from the
+     * toString() of the other
+     */
+    @Test(dataProvider = "validateNanos")
+    public void test51(String ts, int nanos) {
+        Timestamp ts1 = Timestamp.valueOf(ts);
+        Timestamp ts2 = Timestamp.valueOf(ts1.toString());
+        assertTrue(ts1.getNanos() == nanos && ts1.equals(ts2),
+                "Error with Nanos");
+    }
+
+    /*
+     * DataProvider used to provide Timestamps which are not valid and are used
+     * to validate that an IllegalArgumentException will be thrown from the
+     * valueOf method
+     */
+    @DataProvider(name = "invalidTimestampValues")
+    private Object[][] invalidTimestampValues() {
+        return new Object[][]{
+            {"2009-11-01-01 10:50:01"},
+            {"aaaa-11-01-01 10:50"},
+            {"aaaa-11-01 10:50"},
+            {"1961--30 00:00:00"},
+            {"--30 00:00:00"},
+            {"-- 00:00:00"},
+            {"1961-1- 00:00:00"},
+            {"2009-11-01"},
+            {"10:50:01"},
+            {"1961-a-30 00:00:00"},
+            {"1961-01-bb 00:00:00"},
+            {"1961-08-30 00:00:00."},
+            {"1961-08-30 :00:00"},
+            {"1961-08-30 00::00"},
+            {"1961-08-30 00:00:"},
+            {"1961-08-30 ::"},
+            {"1961-08-30 0a:00:00"},
+            {"1961-08-30 00:bb:00"},
+            {"1961-08-30 00:01:cc"},
+            {"1961-08-30 00:00:00.01a"},
+            {"1961-08-30 00:00:00.a"},
+            {"1996-12-10 12:26:19.1234567890"},
+            {null}
+        };
+    }
+
+    /*
+     * DataProvider used to provide Timestamps which are  valid and are used
+     * to validate that an IllegalArgumentException will not be thrown from the
+     * valueOf method and the corect value from toString() is returned
+     */
+    @DataProvider(name = "validTimestampValues")
+    private Object[][] validTimestampValues() {
+        return new Object[][]{
+            {"1961-08-30 00:00:00", "1961-08-30 00:00:00.0"},
+            {"1961-08-30 11:22:33", "1961-08-30 11:22:33.0"},
+            {"1961-8-30 00:00:00", "1961-08-30 00:00:00.0"},
+            {"1966-08-1 00:00:00", "1966-08-01 00:00:00.0"},
+            {"1996-12-10 12:26:19.1", "1996-12-10 12:26:19.1"},
+            {"1996-12-10 12:26:19.12", "1996-12-10 12:26:19.12"},
+            {"1996-12-10 12:26:19.123", "1996-12-10 12:26:19.123"},
+            {"1996-12-10 12:26:19.1234", "1996-12-10 12:26:19.1234"},
+            {"1996-12-10 12:26:19.12345", "1996-12-10 12:26:19.12345"},
+            {"1996-12-10 12:26:19.123456", "1996-12-10 12:26:19.123456"},
+            {"1996-12-10 12:26:19.1234567", "1996-12-10 12:26:19.1234567"},
+            {"1996-12-10 12:26:19.12345678", "1996-12-10 12:26:19.12345678"},
+            {"1996-12-10 12:26:19.123456789", "1996-12-10 12:26:19.123456789"},
+            {"1996-12-10 12:26:19.000000001", "1996-12-10 12:26:19.000000001"},
+            {"1996-12-10 12:26:19.000000012", "1996-12-10 12:26:19.000000012"},
+            {"1996-12-10 12:26:19.000000123", "1996-12-10 12:26:19.000000123"},
+            {"1996-12-10 12:26:19.000001234", "1996-12-10 12:26:19.000001234"},
+            {"1996-12-10 12:26:19.000012345", "1996-12-10 12:26:19.000012345"},
+            {"1996-12-10 12:26:19.000123456", "1996-12-10 12:26:19.000123456"},
+            {"1996-12-10 12:26:19.001234567", "1996-12-10 12:26:19.001234567"},
+            {"1996-12-10 12:26:19.12345678", "1996-12-10 12:26:19.12345678"},
+            {"1996-12-10 12:26:19.0", "1996-12-10 12:26:19.0"},
+            {"1996-12-10 12:26:19.01230", "1996-12-10 12:26:19.0123"}
+        };
+    }
+
+    /*
+     * DataProvider used to provide Timestamp and Nanos values in order to
+     * validate that the correct Nanos value is generated from the specified
+     * Timestamp
+     */
+    @DataProvider(name = "validateNanos")
+    private Object[][] validateNanos() {
+        return new Object[][]{
+            {"1961-08-30 00:00:00", 0},
+            {"1996-12-10 12:26:19.1", 100000000},
+            {"1996-12-10 12:26:19.12", 120000000},
+            {"1996-12-10 12:26:19.123", 123000000},
+            {"1996-12-10 12:26:19.1234", 123400000},
+            {"1996-12-10 12:26:19.12345", 123450000},
+            {"1996-12-10 12:26:19.123456", 123456000},
+            {"1996-12-10 12:26:19.1234567", 123456700},
+            {"1996-12-10 12:26:19.12345678", 123456780},
+            {"1996-12-10 12:26:19.123456789", 123456789},
+            {"1996-12-10 12:26:19.000000001", 1},
+            {"1996-12-10 12:26:19.000000012", 12},
+            {"1996-12-10 12:26:19.000000123", 123},
+            {"1996-12-10 12:26:19.000001234", 1234},
+            {"1996-12-10 12:26:19.000012345", 12345},
+            {"1996-12-10 12:26:19.000123456", 123456},
+            {"1996-12-10 12:26:19.001234567", 1234567},
+            {"1996-12-10 12:26:19.012345678", 12345678},
+            {"1996-12-10 12:26:19.0", 0},
+            {"1996-12-10 12:26:19.01230", 12300000}
+        };
+    }
 }
--- a/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -138,7 +138,7 @@
             {"Asia/Taipei",      "China Standard Time",   preferred, Locale.ENGLISH, TextStyle.FULL},
             {"America/Chicago",  "CST",                   none,      Locale.ENGLISH, TextStyle.SHORT},
             {"Asia/Taipei",      "CST",                   preferred, Locale.ENGLISH, TextStyle.SHORT},
-            {"Australia/South",  "CST",                   preferred_s, Locale.ENGLISH, TextStyle.SHORT},
+            {"Australia/South",  "ACST",                  preferred_s, Locale.ENGLISH, TextStyle.SHORT},
             {"America/Chicago",  "CDT",                   none,        Locale.ENGLISH, TextStyle.SHORT},
             {"Asia/Shanghai",    "CDT",                   preferred_s, Locale.ENGLISH, TextStyle.SHORT},
        };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/loading/MLetInternalsTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.loading.MLet;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8058089
+ * @summary Tests various internal functions provided by MLet for correctness
+ * @author Jaroslav Bachorik
+ * @run testng MLetInternalsTest
+ */
+public class MLetInternalsTest {
+    private final static String CONSTRUCT_PARAMETER = "constructParameter";
+
+    private final static Map<String, Method> testedMethods = new HashMap<>();
+
+    @BeforeClass
+    public static void setupClass() {
+        testedMethods.clear();
+        try {
+            Method m = MLet.class.getDeclaredMethod(
+                    CONSTRUCT_PARAMETER,
+                    String.class, String.class
+            );
+            m.setAccessible(true);
+
+            testedMethods.put(CONSTRUCT_PARAMETER, m);
+        } catch (Exception ex) {
+            throw new Error(ex);
+        }
+    }
+
+    private MLet mlet;
+
+    @BeforeTest
+    public void setupTest() {
+        mlet = new MLet();
+    }
+
+    @Test
+    public void testConstructParameter() throws Exception {
+        assertEquals(constructParameter("120", "int"), 120);
+        assertEquals(constructParameter("120", "java.lang.Integer"), Integer.valueOf(120));
+        assertEquals(constructParameter("120", "long"), 120L);
+        assertEquals(constructParameter("120", "java.lang.Long"), Long.valueOf(120));
+        assertEquals(constructParameter("120.0", "float"), 120.0f);
+        assertEquals(constructParameter("120.0", "java.lang.Float"), Float.valueOf(120.0f));
+        assertEquals(constructParameter("120.0", "double"), 120.0d);
+        assertEquals(constructParameter("120", "java.lang.Double"), Double.valueOf(120d));
+        assertEquals(constructParameter("120", "java.lang.String"), "120");
+        assertEquals(constructParameter("120", "byte"), (byte)120);
+        assertEquals(constructParameter("120", "java.lang.Byte"), (byte)120);
+        assertEquals(constructParameter("120", "short"), (short)120);
+        assertEquals(constructParameter("120", "java.lang.Short"), (short)120);
+        assertEquals(constructParameter("true", "boolean"), true);
+        assertEquals(constructParameter("true", "java.lang.Boolean"), Boolean.valueOf(true));
+    }
+
+    private Object constructParameter(String param, String type) throws Exception {
+        return testedMethods.get(CONSTRUCT_PARAMETER).invoke(mlet, param, type);
+    }
+}
--- a/jdk/test/sun/invoke/util/ValueConversionsTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/invoke/util/ValueConversionsTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,11 +25,11 @@
 
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.Wrapper;
+import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.MethodHandle;
 import java.io.Serializable;
 import java.util.Arrays;
-import java.util.Collections;
 import org.junit.Test;
 import static org.junit.Assert.*;
 
@@ -37,24 +37,13 @@
  * @summary unit tests for value-type conversion utilities
  * @compile -XDignore.symbol.file ValueConversionsTest.java
  * @run junit/othervm test.sun.invoke.util.ValueConversionsTest
- * @run junit/othervm
- *          -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.START_ARITY=250
- *              test.sun.invoke.util.ValueConversionsTest
  */
 
-// This might take a while and burn lots of metadata:
-// @run junit/othervm -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.EXHAUSTIVE=true test.sun.invoke.util.ValueConversionsTest
-
 /**
  *
  * @author jrose
  */
 public class ValueConversionsTest {
-    private static final Class<?> CLASS = ValueConversionsTest.class;
-    private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);
-    private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0);
-    private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE");
-
     @Test
     public void testUnbox() throws Throwable {
         testUnbox(false);
@@ -66,9 +55,7 @@
     }
 
     private void testUnbox(boolean doCast) throws Throwable {
-        //System.out.println("unbox");
         for (Wrapper dst : Wrapper.values()) {
-            //System.out.println(dst);
             for (Wrapper src : Wrapper.values()) {
                 testUnbox(doCast, dst, src);
             }
@@ -78,6 +65,7 @@
     private void testUnbox(boolean doCast, Wrapper dst, Wrapper src) throws Throwable {
         boolean expectThrow = !doCast && !dst.isConvertibleFrom(src);
         if (dst == Wrapper.OBJECT || src == Wrapper.OBJECT)  return;  // must have prims
+        if (dst == Wrapper.VOID   || src == Wrapper.VOID  )  return;  // must have values
         if (dst == Wrapper.OBJECT)
             expectThrow = false;  // everything (even VOID==null here) converts to OBJECT
         try {
@@ -91,9 +79,9 @@
                 }
                 MethodHandle unboxer;
                 if (doCast)
-                    unboxer = ValueConversions.unboxCast(dst.primitiveType());
+                    unboxer = ValueConversions.unboxCast(dst);
                 else
-                    unboxer = ValueConversions.unbox(dst.primitiveType());
+                    unboxer = ValueConversions.unboxWiden(dst);
                 Object expResult = (box == null) ? dst.zero() : dst.wrap(box);
                 Object result = null;
                 switch (dst) {
@@ -104,9 +92,7 @@
                     case CHAR:    result = (char)    unboxer.invokeExact(box); break;
                     case BYTE:    result = (byte)    unboxer.invokeExact(box); break;
                     case SHORT:   result = (short)   unboxer.invokeExact(box); break;
-                    case OBJECT:  result = (Object)  unboxer.invokeExact(box); break;
                     case BOOLEAN: result = (boolean) unboxer.invokeExact(box); break;
-                    case VOID:    result = null;     unboxer.invokeExact(box); break;
                 }
                 if (expectThrow) {
                     expResult = "(need an exception)";
@@ -123,25 +109,23 @@
 
     @Test
     public void testBox() throws Throwable {
-        //System.out.println("box");
         for (Wrapper w : Wrapper.values()) {
-            if (w == Wrapper.VOID)  continue;  // skip this; no unboxed form
-            //System.out.println(w);
+            if (w == Wrapper.VOID)    continue;  // skip this; no unboxed form
+            if (w == Wrapper.OBJECT)  continue;  // skip this; already unboxed
             for (int n = -5; n < 10; n++) {
                 Object box = w.wrap(n);
-                MethodHandle boxer = ValueConversions.box(w.primitiveType());
+                MethodHandle boxer = ValueConversions.boxExact(w);
                 Object expResult = box;
                 Object result = null;
                 switch (w) {
-                    case INT:     result = boxer.invokeExact(/*int*/n); break;
-                    case LONG:    result = boxer.invokeExact((long)n); break;
-                    case FLOAT:   result = boxer.invokeExact((float)n); break;
-                    case DOUBLE:  result = boxer.invokeExact((double)n); break;
-                    case CHAR:    result = boxer.invokeExact((char)n); break;
-                    case BYTE:    result = boxer.invokeExact((byte)n); break;
-                    case SHORT:   result = boxer.invokeExact((short)n); break;
-                    case OBJECT:  result = boxer.invokeExact((Object)n); break;
-                    case BOOLEAN: result = boxer.invokeExact((n & 1) != 0); break;
+                    case INT:     result = (Integer) boxer.invokeExact(/*int*/n); break;
+                    case LONG:    result = (Long)    boxer.invokeExact((long)n); break;
+                    case FLOAT:   result = (Float)   boxer.invokeExact((float)n); break;
+                    case DOUBLE:  result = (Double)  boxer.invokeExact((double)n); break;
+                    case CHAR:    result = (Character) boxer.invokeExact((char)n); break;
+                    case BYTE:    result = (Byte)    boxer.invokeExact((byte)n); break;
+                    case SHORT:   result = (Short)   boxer.invokeExact((short)n); break;
+                    case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break;
                 }
                 assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
                              expResult, result);
@@ -151,16 +135,14 @@
 
     @Test
     public void testCast() throws Throwable {
-        //System.out.println("cast");
         Class<?>[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class };
         Object[] objects = { new Object(), Boolean.FALSE,      "hello",      (Long)12L,    (Integer)6    };
         for (Class<?> dst : types) {
-            MethodHandle caster = ValueConversions.cast(dst);
-            assertEquals(caster.type(), ValueConversions.identity().type());
+            MethodHandle caster = ValueConversions.cast().bindTo(dst);
+            assertEquals(caster.type(), MethodHandles.identity(Object.class).type());
             for (Object obj : objects) {
                 Class<?> src = obj.getClass();
                 boolean canCast = dst.isAssignableFrom(src);
-                //System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)"));
                 try {
                     Object result = caster.invokeExact(obj);
                     if (canCast)
@@ -176,25 +158,12 @@
     }
 
     @Test
-    public void testIdentity() throws Throwable {
-        //System.out.println("identity");
-        MethodHandle id = ValueConversions.identity();
-        Object expResult = "foo";
-        Object result = id.invokeExact(expResult);
-        // compiler bug:  ValueConversions.identity().invokeExact("bar");
-        assertEquals(expResult, result);
-    }
-
-    @Test
     public void testConvert() throws Throwable {
-        //System.out.println("convert");
         for (long tval = 0, ctr = 0;;) {
             if (++ctr > 99999)  throw new AssertionError("too many test values");
-            // next test value:
-            //System.out.println(Long.toHexString(tval)); // prints 3776 test patterns
+            // prints 3776 test patterns (3776 = 8*59*8)
             tval = nextTestValue(tval);
             if (tval == 0) {
-                //System.out.println("test value count = "+ctr);  // 3776 = 8*59*8
                 break;  // repeat
             }
         }
@@ -205,15 +174,12 @@
         }
     }
     static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable {
-        //System.out.println(src+" => "+dst);
+        if (dst == Wrapper.OBJECT || src == Wrapper.OBJECT)  return;  // must have prims
+        if (dst == Wrapper.VOID   || src == Wrapper.VOID  )  return;  // must have values
         boolean testSingleCase = (tval != 0);
         final long tvalInit = tval;
         MethodHandle conv = ValueConversions.convertPrimitive(src, dst);
-        MethodType convType;
-        if (src == Wrapper.VOID)
-            convType = MethodType.methodType(dst.primitiveType() /* , void */);
-        else
-            convType = MethodType.methodType(dst.primitiveType(), src.primitiveType());
+        MethodType convType = MethodType.methodType(dst.primitiveType(), src.primitiveType());
         assertEquals(convType, conv.type());
         MethodHandle converter = conv.asType(conv.type().changeReturnType(Object.class));
         for (;;) {
@@ -229,9 +195,7 @@
                 case CHAR:    result = converter.invokeExact((char)n); break;
                 case BYTE:    result = converter.invokeExact((byte)n); break;
                 case SHORT:   result = converter.invokeExact((short)n); break;
-                case OBJECT:  result = converter.invokeExact((Object)n); break;
                 case BOOLEAN: result = converter.invokeExact((n & 1) != 0); break;
-                case VOID:    result = converter.invokeExact(); break;
                 default:  throw new AssertionError();
             }
             assertEquals("(src,dst,n,testValue)="+Arrays.asList(src,dst,"0x"+Long.toHexString(n),testValue),
@@ -269,169 +233,4 @@
         }
         return tweakSign(ux);
     }
-
-    @Test
-    public void testVarargsArray() throws Throwable {
-        //System.out.println("varargsArray");
-        final int MIN = START_ARITY;
-        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
-        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
-            MethodHandle target = ValueConversions.varargsArray(nargs);
-            Object[] args = new Object[nargs];
-            for (int i = 0; i < nargs; i++)
-                args[i] = "#"+i;
-            Object res = target.invokeWithArguments(args);
-            assertArrayEquals(args, (Object[])res);
-        }
-    }
-
-    @Test
-    public void testVarargsReferenceArray() throws Throwable {
-        //System.out.println("varargsReferenceArray");
-        testTypedVarargsArray(Object[].class);
-        testTypedVarargsArray(String[].class);
-        testTypedVarargsArray(Number[].class);
-    }
-
-    @Test
-    public void testVarargsPrimitiveArray() throws Throwable {
-        //System.out.println("varargsPrimitiveArray");
-        testTypedVarargsArray(int[].class);
-        testTypedVarargsArray(long[].class);
-        testTypedVarargsArray(byte[].class);
-        testTypedVarargsArray(boolean[].class);
-        testTypedVarargsArray(short[].class);
-        testTypedVarargsArray(char[].class);
-        testTypedVarargsArray(float[].class);
-        testTypedVarargsArray(double[].class);
-    }
-
-    private static int nextArgCount(int nargs, int density, int MAX) {
-        if (EXHAUSTIVE)  return nargs + 1;
-        if (nargs >= MAX)  return Integer.MAX_VALUE;
-        int BOT = 20, TOP = MAX-5;
-        if (density < 10) { BOT = 10; MAX = TOP-2; }
-        if (nargs <= BOT || nargs >= TOP) {
-            ++nargs;
-        } else {
-            int bump = Math.max(1, 100 / density);
-            nargs += bump;
-            if (nargs > TOP)  nargs = TOP;
-        }
-        return nargs;
-    }
-
-    private void testTypedVarargsArray(Class<?> arrayType) throws Throwable {
-        //System.out.println(arrayType.getSimpleName());
-        Class<?> elemType = arrayType.getComponentType();
-        int MIN = START_ARITY;
-        int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
-        int density = 3;
-        if (elemType == int.class || elemType == long.class)  density = 7;
-        if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
-        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
-            Object[] args = makeTestArray(elemType, nargs);
-            MethodHandle varargsArray = ValueConversions.varargsArray(arrayType, nargs);
-            MethodType vaType = varargsArray.type();
-            assertEquals(arrayType, vaType.returnType());
-            if (nargs != 0) {
-                assertEquals(elemType, vaType.parameterType(0));
-                assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1));
-            }
-            assertEquals(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)),
-                         vaType);
-            Object res = varargsArray.invokeWithArguments(args);
-            String resString = toArrayString(res);
-            assertEquals(Arrays.toString(args), resString);
-
-            MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs);
-            MethodType stype = spreader.type();
-            assert(stype == MethodType.methodType(arrayType, arrayType));
-            if (nargs <= 5) {
-                // invoke target as a spreader also:
-                @SuppressWarnings("cast")
-                Object res2 = spreader.invokeWithArguments((Object)res);
-                String res2String = toArrayString(res2);
-                assertEquals(Arrays.toString(args), res2String);
-                // invoke the spreader on a generic Object[] array; check for error
-                try {
-                    Object res3 = spreader.invokeWithArguments((Object)args);
-                    String res3String = toArrayString(res3);
-                    assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
-                    assertEquals(Arrays.toString(args), res3String);
-                } catch (ClassCastException ex) {
-                    assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
-                }
-            }
-            if (nargs == 0) {
-                // invoke spreader on null arglist
-                Object res3 = spreader.invokeWithArguments((Object)null);
-                String res3String = toArrayString(res3);
-                assertEquals(Arrays.toString(args), res3String);
-            }
-        }
-    }
-
-    private static Object[] makeTestArray(Class<?> elemType, int len) {
-        Wrapper elem = null;
-        if (elemType.isPrimitive())
-            elem = Wrapper.forPrimitiveType(elemType);
-        else if (Wrapper.isWrapperType(elemType))
-            elem = Wrapper.forWrapperType(elemType);
-        Object[] args = new Object[len];
-        for (int i = 0; i < len; i++) {
-            Object arg = i * 100;
-            if (elem == null) {
-                if (elemType == String.class)
-                    arg = "#"+arg;
-                arg = elemType.cast(arg);  // just to make sure
-            } else {
-                switch (elem) {
-                    case BOOLEAN: arg = (i % 3 == 0);           break;
-                    case CHAR:    arg = 'a' + i;                break;
-                    case LONG:    arg = (long)i * 1000_000_000; break;
-                    case FLOAT:   arg = (float)i / 100;         break;
-                    case DOUBLE:  arg = (double)i / 1000_000;   break;
-                }
-                arg = elem.cast(arg, elemType);
-            }
-            args[i] = arg;
-        }
-        //System.out.println(elemType.getName()+Arrays.toString(args));
-        return args;
-    }
-
-    private static String toArrayString(Object a) {
-        if (a == null)  return "null";
-        Class<?> elemType = a.getClass().getComponentType();
-        if (elemType == null)  return a.toString();
-        if (elemType.isPrimitive()) {
-            switch (Wrapper.forPrimitiveType(elemType)) {
-                case INT:      return Arrays.toString((int[])a);
-                case BYTE:     return Arrays.toString((byte[])a);
-                case BOOLEAN:  return Arrays.toString((boolean[])a);
-                case SHORT:    return Arrays.toString((short[])a);
-                case CHAR:     return Arrays.toString((char[])a);
-                case FLOAT:    return Arrays.toString((float[])a);
-                case LONG:     return Arrays.toString((long[])a);
-                case DOUBLE:   return Arrays.toString((double[])a);
-            }
-        }
-        return Arrays.toString((Object[])a);
-    }
-
-    @Test
-    public void testVarargsList() throws Throwable {
-        //System.out.println("varargsList");
-        final int MIN = START_ARITY;
-        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
-        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 7, MAX)) {
-            MethodHandle target = ValueConversions.varargsList(nargs);
-            Object[] args = new Object[nargs];
-            for (int i = 0; i < nargs; i++)
-                args[i] = "#"+i;
-            Object res = target.invokeWithArguments(args);
-            assertEquals(Arrays.asList(args), res);
-        }
-    }
 }
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -115,8 +115,7 @@
     throws Exception {
 
         Set<ObjectName> names = server.queryNames(pattern,query);
-        for (Iterator<ObjectName> i = names.iterator(); i.hasNext(); ) {
-            ObjectName name = (ObjectName)i.next();
+        for (ObjectName name : names) {
             MBeanInfo info = server.getMBeanInfo(name);
             dbg_print("Got MBean: " + name);
 
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION	Wed Jul 05 20:00:59 2017 +0200
@@ -1,24 +1,24 @@
 #
 # 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.
 #
-tzdata2014c
+tzdata2014g
--- a/jdk/test/sun/util/calendar/zi/tzdata/africa	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/africa	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 #
@@ -49,8 +49,8 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -58,13 +58,13 @@
 # Previous editions of this database used WAT, CAT, SAT, and EAT
 # for +0:00 through +3:00, respectively,
 # but Mark R V Murray reports that
-# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
-# `CAT' is commonly used for +2:00 in countries north of South Africa, and
-# `WAT' is probably the best name for +1:00, as the common phrase for
-# the area that includes Nigeria is ``West Africa''.
-# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
+# 'SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# 'CAT' is commonly used for +2:00 in countries north of South Africa, and
+# 'WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is "West Africa".
+# He has heard of "Western Sahara Time" for +0:00 but can find no reference.
 #
-# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# To make things confusing, 'WAT' seems to have been used for -1:00 long ago;
 # I'd guess that this was because people needed _some_ name for -1:00,
 # and at the time, far west Africa was the only major land area in -1:00.
 # This usage is now obsolete, as the last use of -1:00 on the African
@@ -77,7 +77,7 @@
 #	 2:00	SAST	South Africa Standard Time
 # and Murray suggests the following abbreviation:
 #	 1:00	WAT	West Africa Time
-# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# I realize that this leads to 'WAT' being used for both -1:00 and 1:00
 # for times before 1976, but this is the best I can think of
 # until we get more information.
 #
@@ -117,9 +117,9 @@
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	Algeria	WE%sT	1940 Feb 25 2:00
+Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15  0:01
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	Algeria	WE%sT	1940 Feb 25  2:00
 			1:00	Algeria	CE%sT	1946 Oct  7
 			0:00	-	WET	1956 Jan 29
 			1:00	-	CET	1963 Apr 14
@@ -129,18 +129,8 @@
 			1:00	-	CET
 
 # Angola
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Luanda	0:52:56	-	LMT	1892
-			0:52:04	-	AOT	1911 May 26 # Angola Time
-			1:00	-	WAT
-
 # Benin
-# Whitman says they switched to 1:00 in 1946, not 1934;
-# go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
-			0:00	-	GMT	1934 Feb 26
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Botswana
 # From Paul Eggert (2013-02-21):
@@ -149,14 +139,12 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Gaborone	1:43:40 -	LMT	1885
 			1:30	-	SAST	1903 Mar
-			2:00	-	CAT	1943 Sep 19 2:00
-			2:00	1:00	CAST	1944 Mar 19 2:00
+			2:00	-	CAT	1943 Sep 19  2:00
+			2:00	1:00	CAST	1944 Mar 19  2:00
 			2:00	-	CAT
 
 # Burkina Faso
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Burundi
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -164,52 +152,60 @@
 			2:00	-	CAT
 
 # Cameroon
-# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Douala	0:38:48	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Cape Verde
+#
+# Shanks gives 1907 for the transition to CVT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907			# Praia
+Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907        # Praia
 			-2:00	-	CVT	1942 Sep
 			-2:00	1:00	CVST	1945 Oct 15
-			-2:00	-	CVT	1975 Nov 25 2:00
+			-2:00	-	CVT	1975 Nov 25  2:00
 			-1:00	-	CVT
 
 # Central African Republic
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bangui	1:14:20	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Chad
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Ndjamena	1:00:12 -	LMT	1912
+Zone	Africa/Ndjamena	1:00:12 -	LMT	1912        # N'Djamena
 			1:00	-	WAT	1979 Oct 14
 			1:00	1:00	WAST	1980 Mar  8
 			1:00	-	WAT
 
 # Comoros
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul   # Moroni, Gran Comoro
+Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul # Moroni, Gran Comoro
 			3:00	-	EAT
 
-# Democratic Republic of Congo
+# Democratic Republic of the Congo
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov 9
-			1:00	-	WAT
 Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
 			2:00	-	CAT
+# The above is for the eastern part; see Africa/Lagos for the western part.
 
 # Republic of the Congo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Brazzaville	1:01:08 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
-# Cote D'Ivoire
+# Côte d'Ivoire / Ivory Coast
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
 			 0:00	-	GMT
+Link Africa/Abidjan Africa/Bamako	# Mali
+Link Africa/Abidjan Africa/Banjul	# Gambia
+Link Africa/Abidjan Africa/Conakry	# Guinea
+Link Africa/Abidjan Africa/Dakar	# Senegal
+Link Africa/Abidjan Africa/Freetown	# Sierra Leone
+Link Africa/Abidjan Africa/Lome		# Togo
+Link Africa/Abidjan Africa/Nouakchott	# Mauritania
+Link Africa/Abidjan Africa/Ouagadougou	# Burkina Faso
+Link Africa/Abidjan Africa/Sao_Tome	# São Tomé and Príncipe
+Link Africa/Abidjan Atlantic/St_Helena	# St Helena
 
 # Djibouti
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -254,30 +250,26 @@
 # Egyptians would approve the cancellation."
 #
 # Egypt to cancel daylight saving time
-# <a href="http://www.almasryalyoum.com/en/node/407168">
 # http://www.almasryalyoum.com/en/node/407168
-# </a>
 # or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_egypt04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_egypt04.html
-# </a>
 Rule	Egypt	1995	2010	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	1995	2005	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	1995	2005	-	Sep	lastThu	24:00	0	-
 # From Steffen Thorsen (2006-09-19):
 # The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
 # Egypt will turn back clocks by one hour at the midnight of Thursday
 # after observing the daylight saving time since May.
 # http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
-Rule	Egypt	2006	only	-	Sep	21	23:00s	0	-
+Rule	Egypt	2006	only	-	Sep	21	24:00	0	-
 # From Dirk Losch (2007-08-14):
 # I received a mail from an airline which says that the daylight
 # saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
-# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
+# From Jesper Nørgaard Welen (2007-08-15): [The following agree:]
 # http://www.nentjes.info/Bill/bill5.htm
 # http://www.timeanddate.com/worldclock/city.html?n=53
 # From Steffen Thorsen (2007-09-04): The official information...:
 # http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
-Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
+Rule	Egypt	2007	only	-	Sep	Thu>=1	24:00	0	-
 # From Abdelrahman Hassan (2007-09-06):
 # Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
 # than the year of the Gregorian calendar, Ramadan shifts earlier each
@@ -311,15 +303,9 @@
 #
 # timeanddate[2] and another site I've found[3] also support that.
 #
-# [1] <a href="https://bugzilla.redhat.com/show_bug.cgi?id=492263">
-# https://bugzilla.redhat.com/show_bug.cgi?id=492263
-# </a>
-# [2] <a href="http://www.timeanddate.com/worldclock/clockchange.html?n=53">
-# http://www.timeanddate.com/worldclock/clockchange.html?n=53
-# </a>
-# [3] <a href="http://wwp.greenwichmeantime.com/time-zone/africa/egypt/">
-# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
-# </a>
+# [1] https://bugzilla.redhat.com/show_bug.cgi?id=492263
+# [2] http://www.timeanddate.com/worldclock/clockchange.html?n=53
+# [3] http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
 
 # From Arthur David Olson (2009-04-20):
 # In 2009 (and for the next several years), Ramadan ends before the fourth
@@ -329,14 +315,10 @@
 # From Steffen Thorsen (2009-08-11):
 # We have been able to confirm the August change with the Egyptian Cabinet
 # Information and Decision Support Center:
-# <a href="http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html">
 # http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
-# </a>
 #
 # The Middle East News Agency
-# <a href="http://www.mena.org.eg/index.aspx">
 # http://www.mena.org.eg/index.aspx
-# </a>
 # also reports "Egypt starts winter time on August 21"
 # today in article numbered "71, 11/08/2009 12:25 GMT."
 # Only the title above is available without a subscription to their service,
@@ -344,19 +326,14 @@
 # (at least today).
 
 # From Alexander Krivenyshev (2010-07-20):
-# According to News from Egypt -  Al-Masry Al-Youm Egypt's cabinet has
+# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has
 # decided that Daylight Saving Time will not be used in Egypt during
 # Ramadan.
 #
 # Arabic translation:
-# "Clocks to go back during Ramadan--and then forward again"
-# <a href="http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again">
+# "Clocks to go back during Ramadan - and then forward again"
 # http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_egypt02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
-# </a>
 
 # From Ahmad El-Dardiry (2014-05-07):
 # Egypt is to change back to Daylight system on May 15
@@ -365,46 +342,77 @@
 # From Gunther Vermier (2015-05-13):
 # our Egypt office confirms that the change will be at 15 May "midnight" (24:00)
 
-# From Paul Eggert (2014-05-13):
+# From Imed Chihi (2014-06-04):
+# We have finally "located" a precise official reference about the DST changes
+# in Egypt.  The Ministers Cabinet decision is explained at
+# http://www.cabinet.gov.eg/Media/CabinetMeetingsDetails.aspx?id=347 ...
+# [T]his (Arabic) site is not accessible outside Egypt, but the page ...
+# translates into: "With regard to daylight saving time, it is scheduled to
+# take effect at exactly twelve o'clock this evening, Thursday, 15 MAY 2014,
+# to be suspended by twelve o'clock on the evening of Thursday, 26 JUN 2014,
+# and re-established again at the end of the month of Ramadan, at twelve
+# o'clock on the evening of Thursday, 31 JUL 2014."  This statement has been
+# reproduced by other (more accessible) sites[, e.g.,]...
+# http://elgornal.net/news/news.aspx?id=4699258
+
+# From Paul Eggert (2014-06-04):
 # Sarah El Deeb and Lee Keath of AP report that the Egyptian government says
 # the change is because of blackouts in Cairo, even though Ahram Online (cited
-# above) says DST had no affect on electricity consumption.  The AP story says
-# DST will not be observed during Ramadan.  There is no information about when
-# DST will end.  See:
+# above) says DST had no affect on electricity consumption.  There is
+# no information about when DST will end this fall.  See:
 # http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833
 #
-# For now, guess that later transitions will use 2010's rules, and that
-# Egypt will agree with Morocco (see below) about the date Ramadan starts and
-# ends, though (unlike Morocco) it will switch at 00:00 standard time.  In
-# Egypt the spring-forward transitions are removed for 2020-2022, when the
-# guessed spring-forward date falls during the estimated Ramadan, and all
-# transitions removed for 2023-2038, where the estimated Ramadan falls entirely
-# outside the guessed daylight-saving time.  Ramadan intrudes on the guessed
-# DST starting in 2039, but that's beyond our somewhat-arbitrary cutoff.
-
-Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
-Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
-Rule	Egypt	2010	only	-	Aug	11	0:00	0	-
-Rule	Egypt	2010	only	-	Sep	10	0:00	1:00	S
-Rule	Egypt	2010	only	-	Sep	lastThu	23:00s	0	-
+# For now, guess that later spring and fall transitions will use
+# 2010's rules, and guess that Egypt will switch to standard time at
+# 24:00 the last Thursday before Ramadan, and back to DST at 00:00 the
+# first Friday after Ramadan.  To implement this,
+# transition dates for 2015 through 2037 were determined by running
+# the following program under GNU Emacs 24.3, with the results integrated
+# by hand into the table below.  Ramadan again intrudes on the guessed
+# DST starting in 2038, but that's beyond our somewhat-arbitrary cutoff.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (friday 5))
+#       (while (/= friday (mod a 7))
+#         (setq a (1- a)))
+#       (while (/= friday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (1- a))
+#       (setq b (1- b))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t0\t-\n"
+#                 "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+#     (setq islamic-year (+ 1 islamic-year))))
+Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
+Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
+Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
+Rule	Egypt	2010	only	-	Sep	 9	24:00	1:00	S
+Rule	Egypt	2010	only	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2014	only	-	May	15	24:00	1:00	S
-Rule	Egypt	2014	only	-	Jun	29	 0:00s	0	-
-Rule	Egypt	2014	only	-	Jul	29	 0:00s	1:00	S
-Rule	Egypt	2014	max	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	2014	only	-	Jun	26	24:00	0	-
+Rule	Egypt	2014	only	-	Jul	31	24:00	1:00	S
+Rule	Egypt	2014	max	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2015	2019	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	2015	only	-	Jun	18	 0:00s	0	-
-Rule	Egypt	2015	only	-	Jul	18	 0:00s	1:00	S
-Rule	Egypt	2016	only	-	Jun	 7	 0:00s	0	-
-Rule	Egypt	2016	only	-	Jul	 7	 0:00s	1:00	S
-Rule	Egypt	2017	only	-	May	27	 0:00s	0	-
-Rule	Egypt	2017	only	-	Jun	26	 0:00s	1:00	S
-Rule	Egypt	2018	only	-	May	16	 0:00s	0	-
-Rule	Egypt	2018	only	-	Jun	15	 0:00s	1:00	S
-Rule	Egypt	2019	only	-	May	 6	 0:00s	0	-
-Rule	Egypt	2019	only	-	Jun	 5	 0:00s	1:00	S
-Rule	Egypt	2020	only	-	May	24	 0:00s	1:00	S
-Rule	Egypt	2021	only	-	May	13	 0:00s	1:00	S
-Rule	Egypt	2022	only	-	May	 3	 0:00s	1:00	S
+Rule	Egypt	2015	only	-	Jun	11	24:00	0	-
+Rule	Egypt	2015	only	-	Jul	23	24:00	1:00	S
+Rule	Egypt	2016	only	-	Jun	 2	24:00	0	-
+Rule	Egypt	2016	only	-	Jul	 7	24:00	1:00	S
+Rule	Egypt	2017	only	-	May	25	24:00	0	-
+Rule	Egypt	2017	only	-	Jun	29	24:00	1:00	S
+Rule	Egypt	2018	only	-	May	10	24:00	0	-
+Rule	Egypt	2018	only	-	Jun	14	24:00	1:00	S
+Rule	Egypt	2019	only	-	May	 2	24:00	0	-
+Rule	Egypt	2019	only	-	Jun	 6	24:00	1:00	S
+Rule	Egypt	2020	only	-	May	28	24:00	1:00	S
+Rule	Egypt	2021	only	-	May	13	24:00	1:00	S
+Rule	Egypt	2022	only	-	May	 5	24:00	1:00	S
 Rule	Egypt	2023	max	-	Apr	lastFri	 0:00s	1:00	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -412,60 +420,63 @@
 			2:00	Egypt	EE%sT
 
 # Equatorial Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Malabo	0:35:08 -	LMT	1912
-			0:00	-	GMT	1963 Dec 15
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Eritrea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Asmara	2:35:32 -	LMT	1870
-			2:35:32	-	AMT	1890	      # Asmara Mean Time
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:32	-	AMT	1890        # Asmara Mean Time
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Ethiopia
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
-# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
-# We'll guess that 38E50 is for Adis Dera.
+# From Paul Eggert (2014-07-31):
+# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
+# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
+# 02:00 or 14:00.  Keep this in mind when you ask the time in Amharic.
+#
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
+# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
+# 1890, and that they switched to 3:00 on 1936-05-05.  Perhaps 38E50
+# was for Adis Dera.  Quite likely the Shanks data entries are wrong
+# anyway.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Gabon
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Libreville	0:37:48 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Gambia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Banjul	-1:06:36 -	LMT	1912
-			-1:06:36 -	BMT	1935	# Banjul Mean Time
-			-1:00	-	WAT	1964
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Ghana
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman says DST was observed from 1931 to ``the present'';
-# go with Shanks & Pottenger.
-Rule	Ghana	1936	1942	-	Sep	 1	0:00	0:20	GHST
-Rule	Ghana	1936	1942	-	Dec	31	0:00	0	GMT
+# Whitman says DST was observed from 1931 to "the present";
+# Shanks & Pottenger say 1936 to 1942;
+# and September 1 to January 1 is given by:
+# Scott Keltie J, Epstein M (eds), The Statesman's Year-Book,
+# 57th ed. Macmillan, London (1920), OCLC 609408015, pp xxviii.
+# For lack of better info, assume DST was observed from 1920 to 1942.
+Rule	Ghana	1920	1942	-	Sep	 1	0:00	0:20	GHST
+Rule	Ghana	1920	1942	-	Dec	31	0:00	0	GMT
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Accra	-0:00:52 -	LMT	1918
 			 0:00	Ghana	%s
 
 # Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Conakry	-0:54:52 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Guinea-Bissau
+#
+# Shanks gives 1911-05-26 for the transition to WAT,
+# evidently confusing the date of the Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# with the date that it took effect, namely 1912-01-01.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bissau	-1:02:20 -	LMT	1911 May 26
+Zone	Africa/Bissau	-1:02:20 -	LMT	1912 Jan  1
 			-1:00	-	WAT	1975
 			 0:00	-	GMT
 
@@ -480,8 +491,8 @@
 # Lesotho
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
-			2:00	-	SAST	1943 Sep 19 2:00
-			2:00	1:00	SAST	1944 Mar 19 2:00
+			2:00	-	SAST	1943 Sep 19  2:00
+			2:00	1:00	SAST	1944 Mar 19  2:00
 			2:00	-	SAST
 
 # Liberia
@@ -549,11 +560,11 @@
 			2:00	-	EET	1982
 			1:00	Libya	CE%sT	1990 May  4
 # The 1996 and 1997 entries are from Shanks & Pottenger;
-# the IATA SSIM data contain some obvious errors.
+# the IATA SSIM data entries contain some obvious errors.
 			2:00	-	EET	1996 Sep 30
 			1:00	Libya	CE%sT	1997 Oct  4
-			2:00	-	EET	2012 Nov 10 2:00
-			1:00	Libya	CE%sT	2013 Oct 25 2:00
+			2:00	-	EET	2012 Nov 10  2:00
+			1:00	Libya	CE%sT	2013 Oct 25  2:00
 			2:00	-	EET
 
 # Madagascar
@@ -569,18 +580,8 @@
 			2:00	-	CAT
 
 # Mali
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bamako	-0:32:00 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Jun 20
-			 0:00	-	GMT
-
 # Mauritania
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Nov 28
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Mauritius
 
@@ -604,9 +605,7 @@
 
 # From Steffen Thorsen (2008-07-10):
 # According to
-# <a href="http://www.lexpress.mu/display_article.php?news_id=111216">
 # http://www.lexpress.mu/display_article.php?news_id=111216
-# </a>
 # (in French), Mauritius will start and end their DST a few days earlier
 # than previously announced (2008-11-01 to 2009-03-31).  The new start
 # date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
@@ -621,22 +620,17 @@
 
 # From Alex Krivenyshev (2008-07-11):
 # Seems that English language article "The revival of daylight saving
-# time:  Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
 # published on Monday, June 30, 2008...
 #
 # I guess that article in French "Le gouvernement avance l'introduction
-# de l'heure d'ete" stating that DST in Mauritius starting on October 26
-# and ending on March 27, 2009 is the most recent one.
-# ...
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html">
+# de l'heure d'été" stating that DST in Mauritius starting on October 26
+# and ending on March 27, 2009 is the most recent one....
 # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
-# </a>
 
 # From Riad M. Hossen Ally (2008-08-03):
 # The Government of Mauritius weblink
-# <a href="http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD">
 # http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
-# </a>
 # Cabinet Decision of July 18th, 2008 states as follows:
 #
 # 4. ...Cabinet has agreed to the introduction into the National Assembly
@@ -646,33 +640,25 @@
 # States of America. It will start at two o'clock in the morning on the
 # last Sunday of October and will end at two o'clock in the morning on
 # the last Sunday of March the following year. The summer time for the
-# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
+# year 2008-2009 will, therefore, be effective as from 26 October 2008
 # and end on 29 March 2009.
 
 # From Ed Maste (2008-10-07):
 # THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
 # beginning / ending of summer time is 2 o'clock standard time in the
 # morning of the last Sunday of October / last Sunday of March.
-# <a href="http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf">
 # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
-# </a>
 
 # From Steffen Thorsen (2009-06-05):
 # According to several sources, Mauritius will not continue to observe
 # DST the coming summer...
 #
 # Some sources, in French:
-# <a href="http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB">
 # http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
-# </a>
-# <a href="http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-">
 # http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
-# </a>
 #
 # Our wrap-up:
-# <a href="http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html">
 # http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
-# </a>
 
 # From Arthur David Olson (2009-07-11):
 # The "mauritius-dst-will-not-repeat" wrapup includes this:
@@ -685,18 +671,18 @@
 Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
 Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
+Zone Indian/Mauritius	3:50:00 -	LMT	1907 # Port Louis
 			4:00 Mauritius	MU%sT	# Mauritius Time
 # Agalega Is, Rodriguez
 # no information; probably like Indian/Mauritius
 
 # Mayotte
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
+Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul # Mamoutzou
 			3:00	-	EAT
 
 # Morocco
-# See the `europe' file for Spanish Morocco (Africa/Ceuta).
+# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
 
 # From Alex Krivenyshev (2008-05-09):
 # Here is an article that Morocco plan to introduce Daylight Saving Time between
@@ -704,60 +690,44 @@
 #
 # "... Morocco is to save energy by adjusting its clock during summer so it will
 # be one hour ahead of GMT between 1 June and 27 September, according to
-# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
+# Communication Minister and Government Spokesman, Khalid Naciri...."
 #
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_morocco01.html">
 # http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
-# </a>
-# OR
-# <a href="http://en.afrik.com/news11892.html">
 # http://en.afrik.com/news11892.html
-# </a>
 
 # From Alex Krivenyshev (2008-05-09):
-# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
-# <a href="http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view">
+# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe
+# Presse:
 # http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
-# </a>
 #
 # Morocco shifts to daylight time on June 1st through September 27, Govt.
 # spokesman.
 
 # From Patrice Scattolin (2008-05-09):
 # According to this article:
-# <a href="http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html">
 # http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
-# </a>
-# (and republished here:
-# <a href="http://www.actu.ma/heure-dete-comment_i127896_0.html">
-# http://www.actu.ma/heure-dete-comment_i127896_0.html
-# </a>
-# )
-# the changes occurs at midnight:
+# (and republished here: <http://www.actu.ma/heure-dete-comment_i127896_0.html>)
+# the changes occur at midnight:
 #
-# saturday night may 31st at midnight (which in french is to be
-# intrepreted as the night between saturday and sunday)
-# sunday night the 28th  at midnight
+# Saturday night May 31st at midnight (which in French is to be
+# interpreted as the night between Saturday and Sunday)
+# Sunday night the 28th at midnight
 #
-# Seeing that the 28th is monday, I am guessing that she intends to say
-# the midnight of the 28th which is the midnight between sunday and
-# monday, which jives with other sources that say that it's inclusive
-# june1st to sept 27th.
+# Seeing that the 28th is Monday, I am guessing that she intends to say
+# the midnight of the 28th which is the midnight between Sunday and
+# Monday, which jives with other sources that say that it's inclusive
+# June 1st to Sept 27th.
 #
 # The decision was taken by decree *2-08-224 *but I can't find the decree
 # published on the web.
 #
 # It's also confirmed here:
-# <a href="http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm">
 # http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
-# </a>
-# on a government portal as being  between june 1st and sept 27th (not yet
-# posted in english).
+# on a government portal as being between June 1st and Sept 27th (not yet
+# posted in English).
 #
-# The following google query will generate many relevant hits:
-# <a href="http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search">
+# The following Google query will generate many relevant hits:
 # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
-# </a>
 
 # From Steffen Thorsen (2008-08-27):
 # Morocco will change the clocks back on the midnight between August 31
@@ -765,47 +735,32 @@
 # of September:
 #
 # One article about it (in French):
-# <a href="http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default">
 # http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
-# </a>
 #
 # We have some further details posted here:
-# <a href="http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html">
 # http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
-# </a>
 
 # From Steffen Thorsen (2009-03-17):
 # Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
 # to many sources, such as
-# <a href="http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html">
 # http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
-# </a>
-# <a href="http://www.medi1sat.ma/fr/depeche.aspx?idp=2312">
 # http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
-# </a>
 # (French)
 #
 # Our summary:
-# <a href="http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html">
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to official document from Royaume du Maroc Premier Ministre,
-# Ministere de la Modernisation des Secteurs Publics
+# Ministère de la Modernisation des Secteurs Publics
 #
 # Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
 # concerning the amendment of the legal time, the Ministry of Modernization of
 # Public Sectors announced that the official time in the Kingdom will be
 # advanced 60 minutes from Sunday 31 May 2009 at midnight.
 #
-# <a href="http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf">
 # http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
-# </a>
-#
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_morocco03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
-# </a>
 
 # From Steffen Thorsen (2010-04-13):
 # Several news media in Morocco report that the Ministry of Modernization
@@ -813,51 +768,33 @@
 # 2010-05-02 to 2010-08-08.
 #
 # Example:
-# <a href="http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html">
 # http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html
-# </a>
 # (French)
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html">
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html
-# </a>
 
 # From Dan Abitol (2011-03-30):
 # ...Rules for Africa/Casablanca are the following (24h format)
-# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00
-# The 31th july 2011 at 00:59:59,  [it] will be 31th July 00:00:00
+# The 3rd April 2011 at 00:00:00, [it] will be 3rd April 01:00:00
+# The 31st July 2011 at 00:59:59, [it] will be 31st July 00:00:00
 # ...Official links of change in morocco
 # The change was broadcast on the FM Radio
 # I ve called ANRT (telecom regulations in Morocco) at
 # +212.537.71.84.00
-# <a href="http://www.anrt.net.ma/fr/">
 # http://www.anrt.net.ma/fr/
-# </a>
 # They said that
-# <a href="http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view">
 # http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view
-# </a>
 # is the official publication to look at.
 # They said that the decision was already taken.
 #
 # More articles in the press
-# <a href="http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev">
-# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev
-# </a>
-# e.html
-# <a href="http://www.lematin.ma/Actualite/Express/Article.asp?id=148923">
+# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-leve.html
 # http://www.lematin.ma/Actualite/Express/Article.asp?id=148923
-# </a>
-# <a href="http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim">
 # http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim
-# anche-prochain-5538.html
-# </a>
 
 # From Petr Machata (2011-03-30):
 # They have it written in English here:
-# <a href="http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view">
 # http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view
-# </a>
 #
 # It says there that "Morocco will resume its standard time on July 31,
 # 2011 at midnight." Now they don't say whether they mean midnight of
@@ -865,20 +802,16 @@
 # also been like that in the past.
 
 # From Alexander Krivenyshev (2012-03-09):
-# According to Infom&eacute;diaire web site from Morocco (infomediaire.ma),
-# on March 9, 2012, (in French) Heure l&eacute;gale:
-# Le Maroc adopte officiellement l'heure d'&eacute;t&eacute;
-# <a href="http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9">
+# According to Infomédiaire web site from Morocco (infomediaire.ma),
+# on March 9, 2012, (in French) Heure légale:
+# Le Maroc adopte officiellement l'heure d'été
 # http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9
-# </a>
 # Governing Council adopted draft decree, that Morocco DST starts on
 # the last Sunday of March (March 25, 2012) and ends on
 # last Sunday of September (September 30, 2012)
 # except the month of Ramadan.
 # or (brief)
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_morocco06.html">
 # http://www.worldtimezone.com/dst_news/dst_news_morocco06.html
-# </a>
 
 # From Arthur David Olson (2012-03-10):
 # The infomediaire.ma source indicates that the system is to be in
@@ -889,17 +822,13 @@
 
 # From Christophe Tropamer (2012-03-16):
 # Seen Morocco change again:
-# <a href="http://www.le2uminutes.com/actualite.php">
 # http://www.le2uminutes.com/actualite.php
-# </a>
-# "...&agrave; partir du dernier dimance d'avril et non fins mars,
-# comme annonc&eacute; pr&eacute;c&eacute;demment."
+# "...à partir du dernier dimanche d'avril et non fins mars,
+# comme annoncé précédemment."
 
 # From Milamber Space Network (2012-07-17):
 # The official return to GMT is announced by the Moroccan government:
-# <a href="http://www.mmsp.gov.ma/fr/actualites.aspx?id=288">
 # http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
-# </a>
 #
 # Google translation, lightly edited:
 # Back to the standard time of the Kingdom (GMT)
@@ -917,7 +846,7 @@
 # announced a bit in advance.  On 2012-07-11 the Moroccan government
 # announced that year's Ramadan daylight-saving transitions would be
 # 2012-07-20 and 2012-08-20; see
-# <http://www.mmsp.gov.ma/fr/actualites.aspx?id=288>.
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288
 
 # From Andrew Paprocki (2013-07-02):
 # Morocco announced that the year's Ramadan daylight-savings
@@ -937,39 +866,36 @@
 # From Sebastien Willemijns (2014-03-18):
 # http://www.afriquinfos.com/articles/2014/3/18/maroc-heure-dete-avancez-tous-horloges-247891.asp
 
-# From Paul Eggert (2014-03-19):
-# To estimate what the Moroccan government will do in future years,
-# transition dates for 2014 through 2038 were determined by running
-# the following program under GNU Emacs 24.3:
-#
-# (let ((islamic-year 1435))
-#   (while (< islamic-year 1461)
-#     (let ((a
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 9 1 islamic-year))))
-#	    (b
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 10 1 islamic-year)))))
-#	(insert
-#	 (format
-#	  (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n"
-#		  "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n")
-#	  (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
-#	  (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# From Milamber Space Network (2014-06-05):
+# The Moroccan government has recently announced that the country will return
+# to standard time at 03:00 on Saturday, June 28, 2014 local time....  DST
+# will resume again at 02:00 on Saturday, August 2, 2014....
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=586
+
+# From Paul Eggert (2014-06-05):
+# For now, guess that later spring and fall transitions will use 2014's rules,
+# and guess that Morocco will switch to standard time at 03:00 the last
+# Saturday before Ramadan, and back to DST at 02:00 the first Saturday after
+# Ramadan.  To implement this, transition dates for 2015 through 2037 were
+# determined by running the following program under GNU Emacs 24.3, with the
+# results integrated by hand into the table below.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (saturday 6))
+#       (while (/= saturday (mod (setq a (1- a)) 7)))
+#       (while (/= saturday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t0\t-\n"
+#                 "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
 #     (setq islamic-year (+ 1 islamic-year))))
-#
-# with spring-forward transitions removed for 2023-2025, when the
-# normal spring-forward date falls during the estimated Ramadan; with
-# all transitions removed for 2026-2035, where the estimated Ramadan
-# falls entirely outside daylight-saving time; and with fall-back
-# transitions removed for 2036-2037, where the normal fall-back
-# date falls during the estimated Ramadan.  Normally, the table would
-# stop after 2037 because 32-bit time_t values roll around early in 2038,
-# but that would imply a prediction of perpetual DST after March 2038
-# due to the year-2037 glitches.  So, this table instead stops after
-# 2038, the first non-glitchy year after the 32-bit rollover.
-# An advantage of stopping after 2038 is that it lets zic guess
-# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future.
 
 # RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 
@@ -991,46 +917,44 @@
 Rule	Morocco	2008	only	-	Jun	 1	 0:00	1:00	S
 Rule	Morocco	2008	only	-	Sep	 1	 0:00	0	-
 Rule	Morocco	2009	only	-	Jun	 1	 0:00	1:00	S
-Rule	Morocco	2009	only	-	Aug	 21	 0:00	0	-
+Rule	Morocco	2009	only	-	Aug	21	 0:00	0	-
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	 31	 0	0	-
-Rule	Morocco	2012	2013	-	Apr	 lastSun 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2012	only	-	Jul	 20	 3:00	0	-
-Rule	Morocco	2012	only	-	Aug	 20	 2:00	1:00	S
-Rule	Morocco	2013	only	-	Jul	  7	 3:00	0	-
-Rule	Morocco	2013	only	-	Aug	 10	 2:00	1:00	S
-Rule	Morocco	2013	2035	-	Oct	 lastSun 3:00	0	-
-Rule	Morocco	2014	2022	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2014	only	-	Jun	 29	 3:00	0	-
-Rule	Morocco	2014	only	-	Jul	 29	 2:00	1:00	S
-Rule	Morocco	2015	only	-	Jun	 18	 3:00	0	-
-Rule	Morocco	2015	only	-	Jul	 18	 2:00	1:00	S
-Rule	Morocco	2016	only	-	Jun	  7	 3:00	0	-
-Rule	Morocco	2016	only	-	Jul	  7	 2:00	1:00	S
-Rule	Morocco	2017	only	-	May	 27	 3:00	0	-
-Rule	Morocco	2017	only	-	Jun	 26	 2:00	1:00	S
-Rule	Morocco	2018	only	-	May	 16	 3:00	0	-
-Rule	Morocco	2018	only	-	Jun	 15	 2:00	1:00	S
-Rule	Morocco	2019	only	-	May	  6	 3:00	0	-
-Rule	Morocco	2019	only	-	Jun	  5	 2:00	1:00	S
-Rule	Morocco	2020	only	-	Apr	 24	 3:00	0	-
-Rule	Morocco	2020	only	-	May	 24	 2:00	1:00	S
-Rule	Morocco	2021	only	-	Apr	 13	 3:00	0	-
-Rule	Morocco	2021	only	-	May	 13	 2:00	1:00	S
-Rule	Morocco	2022	only	-	Apr	  3	 3:00	0	-
-Rule	Morocco	2022	only	-	May	  3	 2:00	1:00	S
-Rule	Morocco	2023	only	-	Apr	 22	 2:00	1:00	S
-Rule	Morocco	2024	only	-	Apr	 10	 2:00	1:00	S
-Rule	Morocco	2025	only	-	Mar	 31	 2:00	1:00	S
-Rule	Morocco	2026	max	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2036	only	-	Oct	 21	 3:00	0	-
-Rule	Morocco	2037	only	-	Oct	 11	 3:00	0	-
-Rule	Morocco	2038	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2038	only	-	Oct	 30	 2:00	1:00	S
-Rule	Morocco	2038	max	-	Oct	 lastSun 3:00	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
+Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
+Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
+Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
+Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
+Rule	Morocco	2014	2022	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2014	only	-	Jun	28	 3:00	0	-
+Rule	Morocco	2014	only	-	Aug	 2	 2:00	1:00	S
+Rule	Morocco	2015	only	-	Jun	13	 3:00	0	-
+Rule	Morocco	2015	only	-	Jul	18	 2:00	1:00	S
+Rule	Morocco	2016	only	-	Jun	 4	 3:00	0	-
+Rule	Morocco	2016	only	-	Jul	 9	 2:00	1:00	S
+Rule	Morocco	2017	only	-	May	20	 3:00	0	-
+Rule	Morocco	2017	only	-	Jul	 1	 2:00	1:00	S
+Rule	Morocco	2018	only	-	May	12	 3:00	0	-
+Rule	Morocco	2018	only	-	Jun	16	 2:00	1:00	S
+Rule	Morocco	2019	only	-	May	 4	 3:00	0	-
+Rule	Morocco	2019	only	-	Jun	 8	 2:00	1:00	S
+Rule	Morocco	2020	only	-	Apr	18	 3:00	0	-
+Rule	Morocco	2020	only	-	May	30	 2:00	1:00	S
+Rule	Morocco	2021	only	-	Apr	10	 3:00	0	-
+Rule	Morocco	2021	only	-	May	15	 2:00	1:00	S
+Rule	Morocco	2022	only	-	Apr	 2	 3:00	0	-
+Rule	Morocco	2022	only	-	May	 7	 2:00	1:00	S
+Rule	Morocco	2023	only	-	Apr	22	 2:00	1:00	S
+Rule	Morocco	2024	only	-	Apr	13	 2:00	1:00	S
+Rule	Morocco	2025	only	-	Apr	 5	 2:00	1:00	S
+Rule	Morocco	2026	max	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2035	only	-	Oct	27	 3:00	0	-
+Rule	Morocco	2036	only	-	Oct	18	 3:00	0	-
+Rule	Morocco	2037	only	-	Oct	10	 3:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
@@ -1049,11 +973,17 @@
 # Assume that this has been true since Western Sahara switched to GMT,
 # since most of it was then controlled by Morocco.
 
-Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan
+Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan # El Aaiún
 			-1:00	-	WAT	1976 Apr 14
 			 0:00	Morocco	WE%sT
 
 # Mozambique
+#
+# Shanks gives 1903-03-01 for the transition to CAT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 			2:00	-	CAT
@@ -1062,8 +992,8 @@
 # The 1994-04-03 transition is from Shanks & Pottenger.
 # Shanks & Pottenger report no DST after 1998-04; go with IATA.
 
-# From Petronella Sibeene (2007-03-30) in
-# <http://allafrica.com/stories/200703300178.html>:
+# From Petronella Sibeene (2007-03-30):
+# http://allafrica.com/stories/200703300178.html
 # While the entire country changes its time, Katima Mulilo and other
 # settlements in Caprivi unofficially will not because the sun there
 # rises and sets earlier compared to other regions.  Chief of
@@ -1080,34 +1010,41 @@
 Rule	Namibia	1995	max	-	Apr	Sun>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
-			1:30	-	SWAT	1903 Mar	# SW Africa Time
-			2:00	-	SAST	1942 Sep 20 2:00
-			2:00	1:00	SAST	1943 Mar 21 2:00
+			1:30	-	SWAT	1903 Mar    # SW Africa Time
+			2:00	-	SAST	1942 Sep 20  2:00
+			2:00	1:00	SAST	1943 Mar 21  2:00
 			2:00	-	SAST	1990 Mar 21 # independence
 			2:00	-	CAT	1994 Apr  3
 			1:00	Namibia	WA%sT
 
 # Niger
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Niamey	 0:08:28 -	LMT	1912
-			-1:00	-	WAT	1934 Feb 26
-			 0:00	-	GMT	1960
-			 1:00	-	WAT
+# See Africa/Lagos.
 
 # Nigeria
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
 			1:00	-	WAT
+Link Africa/Lagos Africa/Bangui	     # Central African Republic
+Link Africa/Lagos Africa/Brazzaville # Rep. of the Congo
+Link Africa/Lagos Africa/Douala	     # Cameroon
+Link Africa/Lagos Africa/Kinshasa    # Dem. Rep. of the Congo (west)
+Link Africa/Lagos Africa/Libreville  # Gabon
+Link Africa/Lagos Africa/Luanda	     # Angola
+Link Africa/Lagos Africa/Malabo	     # Equatorial Guinea
+Link Africa/Lagos Africa/Niamey	     # Niger
+Link Africa/Lagos Africa/Porto-Novo  # Benin
 
-# Reunion
+# Réunion
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun	# Saint-Denis
-			4:00	-	RET	# Reunion Time
+Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun # Saint-Denis
+			4:00	-	RET	# Réunion Time
+#
+# Crozet Islands also observes Réunion time; see the 'antarctica' file.
 #
-# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# Scattered Islands (Îles Éparses) administered from Réunion are as follows.
 # The following information about them is taken from
-# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
-# no longer available as of 1999-08-17).
+# Îles Éparses (<http://www.outre-mer.gouv.fr/domtom/ile.htm>, 1997-07-22,
+# in French; no longer available as of 1999-08-17).
 # We have no info about their time zone histories.
 #
 # Bassas da India - uninhabited
@@ -1122,32 +1059,21 @@
 			2:00	-	CAT
 
 # St Helena
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890		# Jamestown
-			-0:22:48 -	JMT	1951	# Jamestown Mean Time
-			 0:00	-	GMT
+# See Africa/Abidjan.
 # The other parts of the St Helena territory are similar:
 #	Tristan da Cunha: on GMT, say Whitman and the CIA
-#	Ascension: on GMT, says usno1995 and the CIA
+#	Ascension: on GMT, say the USNO (1995-12-21) and the CIA
 #	Gough (scientific station since 1955; sealers wintered previously):
 #		on GMT, says the CIA
-#	Inaccessible, Nightingale: no information, but probably GMT
+#	Inaccessible, Nightingale: uninhabited
 
-# Sao Tome and Principe
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
-			-0:36:32 -	LMT	1912	# Lisbon Mean Time
-			 0:00	-	GMT
-
+# São Tomé and Príncipe
 # Senegal
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Dakar	-1:09:44 -	LMT	1912
-			-1:00	-	WAT	1941 Jun
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Seychelles
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
+Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun # Victoria
 			4:00	-	SCT	# Seychelles Time
 # From Paul Eggert (2001-05-30):
 # Aldabra, Farquhar, and Desroches, originally dependencies of the
@@ -1157,17 +1083,7 @@
 # Possibly the islands were uninhabited.
 
 # Sierra Leone
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
-Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
-Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
-Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
-Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Freetown	-0:53:00 -	LMT	1882
-			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
-			-1:00	SL	%s	1957
-			 0:00	SL	%s
+# See Africa/Abidjan.
 
 # Somalia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1190,9 +1106,9 @@
 
 # Sudan
 #
-# From <a href="http://www.sunanews.net/sn13jane.html">
-# Sudan News Agency (2000-01-13)
-# </a>, also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# From <http://www.sunanews.net/sn13jane.html>
+# Sudan News Agency (2000-01-13),
+# also reported by Michaël De Beukelaer-Dossche via Steffen Thorsen:
 # Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
 # Saturday....  This was announced Thursday by Caretaker State Minister for
 # Manpower Abdul-Rahman Nur-Eddin.
@@ -1223,14 +1139,12 @@
 			3:00	-	EAT
 
 # Togo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Lome	0:04:52 -	LMT	1893
-			0:00	-	GMT
+# See Africa/Abidjan.
 
 # Tunisia
 
 # From Gwillim Law (2005-04-30):
-# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
+# My correspondent, Risto Nykänen, has alerted me to another adoption of DST,
 # this time in Tunisia.  According to Yahoo France News
 # <http://fr.news.yahoo.com/050426/5/4dumk.html>, in a story attributed to AP
 # and dated 2005-04-26, "Tunisia has decided to advance its official time by
@@ -1239,8 +1153,8 @@
 # Saturday."  (My translation)
 #
 # From Oscar van Vlijmen (2005-05-02):
-# LaPresse, the first national daily newspaper ...
-# <http://www.lapresse.tn/archives/archives280405/actualites/lheure.html>
+# La Presse, the first national daily newspaper ...
+# http://www.lapresse.tn/archives/archives280405/actualites/lheure.html
 # ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
 # 1h standard time.
 #
@@ -1253,18 +1167,12 @@
 # From Steffen Thorsen (2009-03-16):
 # According to several news sources, Tunisia will not observe DST this year.
 # (Arabic)
-# <a href="http://www.elbashayer.com/?page=viewn&nid=42546">
 # http://www.elbashayer.com/?page=viewn&nid=42546
-# </a>
-# <a href="http://www.babnet.net/kiwidetail-15295.asp">
 # http://www.babnet.net/kiwidetail-15295.asp
-# </a>
 #
 # We have also confirmed this with the US embassy in Tunisia.
 # We have a wrap-up about this on the following page:
-# <a href="http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html">
 # http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to Tunis Afrique Presse News Agency
@@ -1272,20 +1180,17 @@
 # Standard time to be kept the whole year long (tap.info.tn):
 #
 # (in English)
-# <a href="http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157">
 # http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
-# </a>
 #
 # (in Arabic)
-# <a href="http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1">
 # http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
-# </a>
 
-# From Arthur David Olson (2009--3-18):
-# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
-# that the fasting month of ramadan coincides with the period concerned by summer time.
-# Therefore, the standard time will be kept unchanged the whole year long."
-# So foregoing DST seems to be an exception (albeit one that may be repeated in the  future).
+# From Arthur David Olson (2009-03-18):
+# The Tunis Afrique Presse News Agency notice contains this: "This measure is
+# due to the fact that the fasting month of Ramadan coincides with the period
+# concerned by summer time.  Therefore, the standard time will be kept
+# unchanged the whole year long."  So foregoing DST seems to be an exception
+# (albeit one that may be repeated in the future).
 
 # From Alexander Krivenyshev (2010-03-27):
 # According to some news reports Tunis confirmed not to use DST in 2010
@@ -1297,12 +1202,8 @@
 # coincided with the month of Ramadan..."
 #
 # (in Arabic)
-# <a href="http://www.moheet.com/show_news.aspx?nid=358861&pg=1">
 # http://www.moheet.com/show_news.aspx?nid=358861&pg=1
-# <a href="http://www.almadenahnews.com/newss/news.php?c=118&id=38036">
 # http://www.almadenahnews.com/newss/news.php?c=118&id=38036
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_tunis02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_tunis02.html
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1337,7 +1238,7 @@
 # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			1:00	Tunisia	CE%sT
 
 # Uganda
--- a/jdk/test/sun/util/calendar/zi/tzdata/antarctica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/antarctica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,19 +21,16 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # From Paul Eggert (1999-11-15):
 # To keep things manageable, we list only locations occupied year-round; see
-# <a href="http://www.comnap.aq/comnap/comnap.nsf/P/Stations/">
 # COMNAP - Stations and Bases
-# </a>
+# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
 # and
-# <a href="http://www.spri.cam.ac.uk/bob/periant.htm">
 # Summary of the Peri-Antarctic Islands (1998-07-23)
-# </a>
+# http://www.spri.cam.ac.uk/bob/periant.htm
 # for information.
 # Unless otherwise specified, we have no time zone information.
 #
@@ -78,19 +75,19 @@
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
-# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
-# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
-# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
+# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
+# Marambio, -6414-05637, since 1969-10-29
 # Orcadas, Laurie I, -6016-04444, since 1904-02-22
-# San Martin, Debenham I, -6807-06708, since 1951-03-21
+# San Martín, Barry I, -6808-06706, since 1951-03-21
 #	(except 1960-03 / 1976-03-21)
 
 # Australia - territories
 # Heard Island, McDonald Islands (uninhabited)
 #	previously sealers and scientific personnel wintered
-#	<a href="http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html">
 #	Margaret Turner reports
-#	</a> (1999-09-30) that they're UTC+5, with no DST;
+#	http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
+#	(1999-09-30) that they're UTC+5, with no DST;
 #	presumably this is when they have visitors.
 #
 # year-round bases
@@ -107,14 +104,10 @@
 # The changes occurred on 2009-10-18 at 02:00 (local times).
 #
 # Government source: (Australian Antarctic Division)
-# <a href="http://www.aad.gov.au/default.asp?casid=37079">
 # http://www.aad.gov.au/default.asp?casid=37079
-# </a>
 #
 # We have more background information here:
-# <a href="http://www.timeanddate.com/news/time/antarctica-new-times.html">
 # http://www.timeanddate.com/news/time/antarctica-new-times.html
-# </a>
 
 # From Steffen Thorsen (2010-03-10):
 # We got these changes from the Australian Antarctic Division: ...
@@ -129,50 +122,49 @@
 # - Mawson station stays on UTC+5.
 #
 # Background:
-# <a href="http://www.timeanddate.com/news/time/antartica-time-changes-2010.html">
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
-# </a>
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	zzz	1969
-			8:00	-	WST	2009 Oct 18 2:00
-						# Western (Aus) Standard Time
-			11:00	-	CAST	2010 Mar 5 2:00
-						# Casey Time
-			8:00	-	WST	2011 Oct 28 2:00
+			8:00	-	AWST	2009 Oct 18  2:00
+						# Australian Western Std Time
+			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
+			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
-			8:00	-	WST
+			8:00	-	AWST
 Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
-			7:00	-	DAVT	1964 Nov # Davis Time
+			7:00	-	DAVT	1964 Nov    # Davis Time
 			0	-	zzz	1969 Feb
-			7:00	-	DAVT	2009 Oct 18 2:00
+			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
-			7:00	-	DAVT	2011 Oct 28 2:00
+			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
 Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
-			6:00	-	MAWT	2009 Oct 18 2:00
-						# Mawson Time
+			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
 # Casey Weather (1998-02-26)
-# </a>
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html">
+# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
 # Davis Station, Antarctica (1998-02-26)
-# </a>
-# <a href="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html">
+# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
 # Mawson Station, Antarctica (1998-02-25)
-# </a>
+# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
+
+# Belgium - year-round base
+# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
 
 # Brazil - year-round base
-# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
+# Ferraz, King George Island, -6205+05824, since 1983/4
+
+# Bulgaria - year-round base
+# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
 
 # Chile - year-round bases and towns
 # Escudero, South Shetland Is, -621157-0585735, since 1994
-# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
-# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
-# Capitan Arturo Prat, -6230-05941
+# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
+# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Prat, -6230-05941
 # Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
 # These locations have always used Santiago time; use TZ='America/Santiago'.
 
@@ -180,31 +172,35 @@
 # Great Wall, King George Island, -6213-05858, since 1985-02-20
 # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
 
-# France - year-round bases
+# France - year-round bases (also see "France & Italy")
 #
 # From Antoine Leca (1997-01-20):
-# Time data are from Nicole Pailleau at the IFRTP
+# Time data entries are from Nicole Pailleau at the IFRTP
 # (French Institute for Polar Research and Technology).
-# She confirms that French Southern Territories and Terre Adelie bases
-# don't observe daylight saving time, even if Terre Adelie supplies came
+# She confirms that French Southern Territories and Terre Adélie bases
+# don't observe daylight saving time, even if Terre Adélie supplies came
 # from Tasmania.
 #
 # French Southern Territories with year-round inhabitants
 #
-# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
-# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
-# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
+#	sealing & whaling stations operated variously 1802/1911+;
+#	see Indian/Reunion.
+#
+# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
+# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
 #	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
 #
 # St Paul Island - near Amsterdam, uninhabited
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
+Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
-# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
+# <http://en.wikipedia.org/wiki/Dumont_d'Urville_Station> (2005-12-05)
 #
 # Another base at Port-Martin, 50km east, began operation in 1947.
 # It was destroyed by fire on 1952-01-14.
@@ -214,20 +210,22 @@
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
 			0	-	zzz	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
-# Reference:
-# <a href="http://en.wikipedia.org/wiki/Dumont_d'Urville_Station">
-# Dumont d'Urville Station (2005-12-05)
-# </a>
+
+# France & Italy - year-round base
+# Concordia, -750600+1232000, since 2005
 
 # Germany - year-round base
-# Georg von Neumayer, -7039-00815
+# Neumayer III, -704080-0081602, since 2009
 
-# India - year-round base
-# Dakshin Gangotri, -7005+01200
+# India - year-round bases
+# Bharati, -692428+0761114, since 2012
+# Maitri, -704558+0114356, since 1989
+
+# Italy - year-round base (also see "France & Italy")
+# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
 
 # Japan - year-round bases
-# Dome Fuji, -7719+03942
-# Syowa, -690022+0393524
+# Syowa (also known as Showa), -690022+0393524, since 1957
 #
 # From Hideyuki Suzuki (1999-02-06):
 # In all Japanese stations, +0300 is used as the standard time.
@@ -239,11 +237,11 @@
 Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
-# <a href="http://www.nipr.ac.jp/english/ara01.html">
 # NIPR Antarctic Research Activities (1999-08-17)
-# </a>
+# http://www.nipr.ac.jp/english/ara01.html
 
 # S Korea - year-round base
+# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
 # King Sejong, King George Island, -6213-05847, since 1988
 
 # New Zealand - claims
@@ -287,11 +285,14 @@
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
-     			0:00	Troll	%s
+			0:00	Troll	%s
 
 # Poland - year-round base
 # Arctowski, King George Island, -620945-0582745, since 1977
 
+# Romania - year-bound base
+# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
+
 # Russia - year-round bases
 # Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
 # Mirny, Davis coast, -6633+09301, since 1956-02
@@ -301,8 +302,8 @@
 #	year-round from 1960/61 to 1992
 
 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
-# <a href="http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP">
-# From Craig Mundell (1994-12-15)</a>:
+# From Craig Mundell (1994-12-15):
+# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
 # Vostok, which is one of the Russian stations, is set on the same
 # time as Moscow, Russia.
 #
@@ -317,7 +318,7 @@
 #
 # From Paul Eggert (2001-05-04):
 # This seems to be hopelessly confusing, so I asked Lee Hotz about it
-# in person.  He said that some Antartic locations set their local
+# in person.  He said that some Antarctic locations set their local
 # time so that noon is the warmest part of the day, and that this
 # changes during the year and does not necessarily correspond to mean
 # solar noon.  So the Vostok time might have been whatever the clocks
@@ -329,9 +330,12 @@
 
 # S Africa - year-round bases
 # Marion Island, -4653+03752
-# Sanae, -7141-00250
+# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
 
-# UK
+# Ukraine - year-round base
+# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
+
+# United Kingdom
 #
 # British Antarctic Territories (BAT) claims
 # South Orkney Islands
@@ -387,7 +391,7 @@
 # but that he found it more convenient to keep GMT+12
 # as supplies for the station were coming from McMurdo Sound,
 # which was on GMT+12 because New Zealand was on GMT+12 all year
-# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
+# at that time (1957).  (Source: Siple's book 90 Degrees South.)
 #
 # From Susan Smith
 # http://www.cybertours.com/whs/pole10.html
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-08-11):
 #
@@ -49,13 +49,17 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
+#
+# For Russian data circa 1919, a source is:
+# Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+# (See the 'europe' file for a fuller citation.)
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
 #	     std  dst
@@ -70,13 +74,14 @@
 #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
 #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
 #	8:00 CST	China
-#	9:00 CJT	Central Japanese Time (1896/1937)*
+#	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
+#	9:00 JCST	Central Standard Time (Japan, 1896/1937)
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
 #	9:00 KST  KDT	Korea
-#	9:30 CST	(Australian) Central Standard Time
+#	9:30 ACST	Australian Central Standard Time
 #
-# See the `europe' file for Russia and Turkey in Asia.
+# See the 'europe' file for Russia and Turkey in Asia.
 
 # From Guy Harris:
 # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
@@ -86,7 +91,7 @@
 
 ###############################################################################
 
-# These rules are stolen from the `europe' file.
+# These rules are stolen from the 'europe' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
@@ -138,11 +143,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
 			3:00	-	YERT	1957 Mar    # Yerevan Time
-			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia YER%sT	1991 Mar 31  2:00s
 			3:00	1:00	YERST	1991 Sep 23 # independence
-			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
+			3:00 RussiaAsia	AM%sT	1995 Sep 24  2:00s
 			4:00	-	AMT	1997
-			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
+			4:00 RussiaAsia	AM%sT	2012 Mar 25  2:00s
 			4:00	-	AMT
 
 # Azerbaijan
@@ -155,16 +160,16 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
 			3:00	-	BAKT	1957 Mar    # Baku Time
-			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
 			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
-			4:00	-	AZT	1996 # Azerbaijan time
+			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
 
 # Bahrain
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
+Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
@@ -174,13 +179,8 @@
 # Daylight Saving Time from June 16 to Sept 30
 #
 # Bangladesh to introduce daylight saving time likely from June 16
-# <a href="http://www.asiantribune.com/?q=node/17288">
 # http://www.asiantribune.com/?q=node/17288
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
-# </a>
 #
 # "... Bangladesh government has decided to switch daylight saving time from
 # June
@@ -195,17 +195,11 @@
 # the 19th and 20th, and they have not set the end date yet.
 #
 # Some sources:
-# <a href="http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601">
 # http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
-# </a>
-# <a href="http://bdnews24.com/details.php?id=85889&cid=2">
 # http://bdnews24.com/details.php?id=85889&cid=2
-# </a>
 #
 # Our wrap-up:
-# <a href="http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html">
 # http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
-# </a>
 
 # From A. N. M. Kamrus Saadat (2009-06-15):
 # Finally we've got the official mail regarding DST start time where DST start
@@ -220,13 +214,8 @@
 #
 # Following report by same newspaper-"The Daily Star Friday":
 # "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
-# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=107021">
 # http://www.thedailystar.net/newDesign/news-details.php?nid=107021
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
-# </a>
 
 # From Steffen Thorsen (2009-10-13):
 # IANS (Indo-Asian News Service) now reports:
@@ -235,22 +224,15 @@
 # "continue for an indefinite period."
 #
 # One of many places where it is published:
-# <a href="http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html">
 # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
-# </a>
 
 # From Alexander Krivenyshev (2009-12-24):
 # According to Bangladesh newspaper "The Daily Star,"
 # Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
 #
 # Clock goes back 1-hr on Dec 31 night.
-# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=119228">
 # http://www.thedailystar.net/newDesign/news-details.php?nid=119228
-# </a>
-# and
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
-# </a>
 #
 # "...The government yesterday decided to put the clock back by one hour
 # on December 31 midnight and the new time will continue until March 31,
@@ -260,17 +242,12 @@
 # From Alexander Krivenyshev (2010-03-22):
 # According to Bangladesh newspaper "The Daily Star,"
 # Cabinet cancels Daylight Saving Time
-# <a href="http://www.thedailystar.net/newDesign/latest_news.php?nid=22817">
 # http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html">
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
-Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
+Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
@@ -301,7 +278,7 @@
 
 # Brunei
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
+Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
 			7:30	-	BNT	1933
 			8:00	-	BNT
 
@@ -310,16 +287,16 @@
 # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
-			6:24:40	-	RMT	1920	   # Rangoon Mean Time?
-			6:30	-	BURT	1942 May   # Burma Time
-			9:00	-	JST	1945 May 3
-			6:30	-	MMT		   # Myanmar Time
+Zone	Asia/Rangoon	6:24:40 -	LMT	1880        # or Yangon
+			6:24:40	-	RMT	1920        # Rangoon Mean Time?
+			6:30	-	BURT	1942 May    # Burma Time
+			9:00	-	JST	1945 May  3
+			6:30	-	MMT	# Myanmar Time
 
 # Cambodia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -332,12 +309,12 @@
 # From Bob Devine (1988-01-28):
 # No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
 # China is across 4 physical time zones, before Feb 1, 1986 only the
-# Peking (Bejing) time zone was recognized.  Since that date, China
-# has two of 'em -- Peking's and Urumqi (named after the capital of
+# Peking (Beijing) time zone was recognized.  Since that date, China
+# has two of 'em - Peking's and Ürümqi (named after the capital of
 # the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
 #
 # . . .I just deleted the DST table and this editor makes it too
-# painful to suck in another copy..  So, here is what I have for
+# painful to suck in another copy.  So, here is what I have for
 # DST start/end dates for Peking's time zone (info from AP):
 #
 #     1986 May 4 - Sept 14
@@ -347,15 +324,16 @@
 # CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
 # CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
 
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that China (except for Hong Kong and Macau)
-# has had a single time zone since 1980 May 1, observing summer DST
-# from 1986 through 1991; this contradicts Devine's
-# note about Time magazine, though apparently _something_ happened in 1986.
-# Go with Shanks & Pottenger for now.  I made up names for the other
-# pre-1980 time zones.
+# From Paul Eggert (2008-02-11):
+# Jim Mann, "A clumsy embrace for another western custom: China on daylight
+# time - sort of", Los Angeles Times, 1986-05-05 ... [says] that China began
+# observing daylight saving time in 1986.
 
-# From Shanks & Pottenger:
+# From Paul Eggert (2014-06-30):
+# Shanks & Pottenger have China switching to a single time zone in 1980, but
+# this doesn't seem to be correct.  They also write that China observed summer
+# DST from 1986 through 1991, which seems to match the above commentary, so
+# go with them for DST rules as follows:
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
 Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
@@ -369,7 +347,7 @@
 # historic timezones from some Taiwan websites.  And yes, there are official
 # Chinese names for these locales (before 1949).
 #
-# From Jesper Norgaard Welen (2006-07-14):
+# From Jesper Nørgaard Welen (2006-07-14):
 # I have investigated the timezones around 1970 on the
 # http://www.astro.com/atlas site [with provinces and county
 # boundaries summarized below]....  A few other exceptions were two
@@ -380,65 +358,97 @@
 # (could be true), for the moment I am assuming that those two
 # counties are mistakes in the astro.com data.
 
-# From Paul Eggert (2008-02-11):
-# I just now checked Google News for western news sources that talk
-# about China's single time zone, and couldn't find anything before 1986
-# talking about China being in one time zone.  (That article was: Jim
-# Mann, "A clumsy embrace for another western custom: China on daylight
-# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
-# article confirms the tz database's data claiming that China began
-# observing daylight saving time in 1986.
+# From Paul Eggert (2014-06-30):
+# Alois Treindl kindly sent me translations of the following two sources:
 #
-# From Thomas S. Mullaney (2008-02-11):
-# I think you're combining two subjects that need to treated
-# separately: daylight savings (which, you're correct, wasn't
-# implemented until the 1980s) and the unified time zone centered near
-# Beijing (which was implemented in 1949). Briefly, there was also a
-# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
-# ceased, and the second eventually recognized (again, in the 1980s).
+# (1)
+# Guo Qingsheng (National Time-Service Center, CAS, Xi'an 710600, China)
+# Beijing Time at the Beginning of the PRC
+# China Historical Materials of Science and Technology
+# (Zhongguo ke ji shi liao, 中国科技史料), Vol. 24, No. 1 (2003)
+# It gives evidence that at the beginning of the PRC, Beijing time was
+# officially apparent solar time!  However, Guo also says that the
+# evidence is dubious, as the relevant institute of astronomy had not
+# been taken over by the PRC yet.  It's plausible that apparent solar
+# time was announced but never implemented, and that people continued
+# to use UT+8.  As the Shanghai radio station (and I presume the
+# observatory) was still under control of French missionaries, it
+# could well have ignored any such mandate.
 #
-# From Paul Eggert (2008-06-30):
-# There seems to be a good chance China switched to a single time zone in 1949
-# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
-# reliable documentary source saying so yet, so for now we still go with
-# Shanks & Pottenger.
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# (2)
+# Guo Qing-sheng (Shaanxi Astronomical Observatory, CAS, Xi'an 710600, China)
+# A Study on the Standard Time Changes for the Past 100 Years in China
+# [undated and unknown publication location]
+# It says several things:
+#   * The Qing dynasty used local apparent solar time throughout China.
+#   * The Republic of China instituted Beijing mean solar time effective
+#     the official calendar book of 1914.
+#   * The French Concession in Shanghai set up signal stations in
+#     French docks in the 1890s, controlled by Xujiahui (Zikawei)
+#     Observatory and set to local mean time.
+#   * "From the end of the 19th century" it changed to UT+8.
+#   * Chinese Customs (by then reduced to a tool of foreign powers)
+#     eventually standardized on this time for all ports, and it
+#     became used by railways as well.
+#   * In 1918 the Central Observatory proposed dividing China into
+#     five time zones (see below for details).  This caught on
+#     at first only in coastal areas observing UT+8.
+#   * During WWII all of China was in theory was at UT+7.  In practice
+#     this was ignored in the west, and I presume was ignored in
+#     Japanese-occupied territory.
+#   * Japanese-occupied Manchuria was at UT+9, i.e., Japan time.
+#   * The five-zone plan was resurrected after WWII and officially put into
+#     place (with some modifications) in March 1948.  It's not clear
+#     how well it was observed in areas under Nationalist control.
+#   * The People's Liberation Army used UT+8 during the civil war.
+#
+# An AP article "Shanghai Internat'l Area Little Changed" in the
+# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
+# different - the occupied districts going by Tokyo time, an hour
+# ahead of that prevailing in the rest of Shanghai."  Guess that the
+# Xujiahui Observatory was under French control and stuck with UT+8.
+#
+# In earlier versions of this file, China had many separate Zone entries, but
+# this was based on what were apparently incorrect data in Shanks & Pottenger.
+# This has now been simplified to the two entries Asia/Shanghai and
+# Asia/Urumqi, with the others being links for backward compatibility.
+# Proposed in 1918 and theoretically in effect until 1949 (although in practice
+# mainly observed in coastal areas), the five zones were:
+#
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Asia/Harbin (currently a link to Asia/Shanghai)
 # Heilongjiang (except Mohe county), Jilin
-Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
-			8:30	-	CHAT	1932 Mar # Changbai Time
-			8:00	-	CST	1940
-			9:00	-	CHAT	1966 May
-			8:30	-	CHAT	1980 May
-			8:00	PRC	C%sT
-# Zhongyuan Time ("Central plain Time")
+#
+# Zhongyuan Time ("Central plain Time") UT+8
+# Asia/Shanghai
 # most of China
-# Milne gives 8:05:56.7; round to nearest.
-Zone	Asia/Shanghai	8:05:57	-	LMT	1928
-			8:00	Shang	C%sT	1949
-			8:00	PRC	C%sT
-# Long-shu Time (probably due to Long and Shu being two names of that area)
+# This currently represents most other zones as well,
+# as apparently these regions have been the same since 1970.
+# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
+# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+#
+# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Asia/Chongqing (currently a link to Asia/Shanghai)
 # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
 # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
 # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
 # Yangchun, Yangjiang, Yu'nan, and Yunfu.
-Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
-			7:00	-	LONT	1980 May # Long-shu Time
-			8:00	PRC	C%sT
-# Xin-zang Time ("Xinjiang-Tibet Time")
+#
+# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Asia/Urumqi
+# This currently represents Kunlun Time as well,
+# as apparently the two regions have been the same since 1970.
 # The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
 # the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
 # Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
 # east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
-# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
+# east Xinjiang, including Ürümqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
 # Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
 # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
 # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
-Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
-			6:00	-	URUT	1980 May # Urumqi Time
-			8:00	PRC	C%sT
-# Kunlun Time
+#
+# Kunlun Time UT+5.5
+# Asia/Kashgar (currently a link to Asia/Urumqi)
 # West Tibet, including Pulan, Aheqi, Shufu, Shule;
 # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
 # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
@@ -455,9 +465,9 @@
 # population of Xinjiang, typically use "Xinjiang time" which is two
 # hours behind Beijing time, or UTC +0600. The government of the Xinjiang
 # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
-# local governments such as the Urumqi city government use both times in
+# local governments such as the Ürümqi city government use both times in
 # publications, referring to what is popularly called Xinjiang time as
-# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
+# "Ürümqi time." When Uyghurs make an appointment in the Uyghur language
 # they almost invariably use Xinjiang time.
 #
 # (Their ethnic Han compatriots would typically have no clue of its
@@ -469,21 +479,6 @@
 # the province not having dual times but four times in use at the same
 # time. Some areas remained on standard Xinjiang time or Beijing time and
 # others moving their clocks ahead.)
-#
-# ...an example of an official website using of Urumqi time.
-#
-# The first few lines of the Google translation of
-# <a href="http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39">
-# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
-# </a>
-# (retrieved 2009-10-13)
-# > Urumqi fire seven people are missing the alleged losses of at least
-# > 500 million yuan
-# >
-# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
-# > Urumqi City Department of International Plaza Luther Qiantang River
-# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
-# > have worked continuously for 22 hours...
 
 # From Luther Ma (2009-11-19):
 # With the risk of being redundant to previous answers these are the most common
@@ -494,7 +489,7 @@
 # 3. Urumqi...
 # 4. Kashgar...
 # ...
-# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
+# 5. It seems that Uyghurs in Ürümqi has been using Xinjiang since at least the
 # 1960's. I know of one Han, now over 50, who grew up in the surrounding
 # countryside and used Xinjiang time as a child.
 #
@@ -506,10 +501,55 @@
 # Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
 # not be using Beijing time, but some local time.)
 
-Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
-			5:30	-	KAST	1940	 # Kashgar Time
-			5:00	-	KAST	1980 May
+# From David Cochrane (2014-03-26):
+# Just a confirmation that Ürümqi time was implemented in Ürümqi on 1 Feb 1986:
+# http://content.time.com/time/magazine/article/0,9171,960684,00.html
+
+# From Luther Ma (2014-04-22):
+# I have interviewed numerous people of various nationalities and from
+# different localities in Xinjiang and can confirm the information in Guo's
+# report regarding Xinjiang, as well as the Time article reference by David
+# Cochrane.  Whether officially recognized or not (and both are officially
+# recognized), two separate times have been in use in Xinjiang since at least
+# the Cultural Revolution: Xinjiang Time (XJT), aka Ürümqi Time or local time;
+# and Beijing Time.  There is no confusion in Xinjiang as to which name refers
+# to which time. Both are widely used in the province, although in some
+# population groups might be use one to the exclusion of the other.  The only
+# problem is that computers and smart phones list Ürümqi (or Kashgar) as
+# having the same time as Beijing.
+
+# From Paul Eggert (2014-06-30):
+# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
+# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
+# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
+# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
+#
+# Xinjiang Time is well-documented as being officially recognized.  E.g., see
+# "The Working-Calendar for The Xinjiang Uygur Autonomous Region Government"
+# <http://www.sinkiang.gov.cn/service/ourworking/> (2014-04-22).
+# Unfortunately, we have no good records of time in Xinjiang before 1986.
+# During the 20th century parts of Xinjiang were ruled by the Qing dynasty,
+# the Republic of China, various warlords, the First and Second East Turkestan
+# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
+# China, and tracking down all these organizations' timekeeping rules would be
+# quite a trick.  Approximate this lost history by a transition from LMT to
+# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# which happens to be the date given by Shanks & Pottenger (no doubt as a
+# guess) as the transition from LMT.  Ignore the usage of UT+8 before
+# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# that the sort of users who prefer Asia/Urumqi now typically ignored the
+# UT+8 mandate back then.
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Beijing time, used throughout China; represented by Shanghai.
+Zone	Asia/Shanghai	8:05:43	-	LMT	1901
+			8:00	Shang	C%sT	1949
 			8:00	PRC	C%sT
+# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
+# / Wulumuqi.  (Please use Asia/Shanghai if you prefer Beijing time.)
+Zone	Asia/Urumqi	5:50:20	-	LMT	1928
+			6:00	-	XJT
 
 
 # Hong Kong (Xianggang)
@@ -524,15 +564,11 @@
 # and incorrect rules. Although the exact switch over time is missing, I
 # think 3:30 is correct. The official DST record for Hong Kong can be
 # obtained from
-# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# </a>.
 
 # From Arthur David Olson (2009-10-28):
 # Here are the dates given at
-# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# </a>
 # as of 2009-10-28:
 # Year        Period
 # 1941        1 Apr to 30 Sep
@@ -612,35 +648,113 @@
 
 # Taiwan
 
-# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
-# was still controlled by Japan.  This is hard to believe, but we don't
-# have any other information.
-
 # From smallufo (2010-04-03):
-# According to Taiwan's CWB,
-# <a href="http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm">
+# According to Taiwan's CWB [Central Weather Bureau],
 # http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
-# </a>
 # Taipei has DST in 1979 between July 1st and Sep 30.
 
-# From Arthur David Olson (2010-04-07):
-# Here's Google's translation of the table at the bottom of the "summert.htm" page:
-# Decade 	                                                    Name                      Start and end date
-# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
-# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
-# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
-# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
-# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
-# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
-# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
-# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
-# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
-# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
-# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
+# From Yu-Cheng Chuang (2013-07-12):
+# On Dec 28, 1895, the Meiji Emperor announced Ordinance No. 167 of
+# Meiji Year 28 "The clause about standard time", mentioned that
+# Taiwan and Penghu Islands, as well as Yaeyama and Miyako Islands
+# (both in Okinawa) adopt the Western Standard Time which is based on
+# 120E. The adoption began from Jan 1, 1896. The original text can be
+# found on Wikisource:
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+# ... This could be the first adoption of time zone in Taiwan, because
+# during the Qing Dynasty, it seems that there was no time zone
+# declared officially.
+#
+# Later, in the beginning of World War II, on Sep 25, 1937, the Showa
+# Emperor announced Ordinance No. 529 of Showa Year 12 "The clause of
+# revision in the ordinance No. 167 of Meiji year 28 about standard
+# time", in which abolished the adoption of Western Standard Time in
+# western islands (listed above), which means the whole Japan
+# territory, including later occupations, adopt Japan Central Time
+# (UTC+9). The adoption began on Oct 1, 1937. The original text can
+# be found on Wikisource:
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
+#
+# That is, the time zone of Taipei switched to UTC+9 on Oct 1, 1937.
+
+# From Yu-Cheng Chuang (2014-07-02):
+# I've found more evidence about when the time zone was switched from UTC+9
+# back to UTC+8 after WW2.  I believe it was on Sep 21, 1945.  In a document
+# during Japanese era [1] in which the officer told the staff to change time
+# zone back to Western Standard Time (UTC+8) on Sep 21.  And in another
+# history page of National Cheng Kung University [2], on Sep 21 there is a
+# note "from today, switch back to Western Standard Time".  From these two
+# materials, I believe that the time zone change happened on Sep 21.  And
+# today I have found another monthly journal called "The Astronomical Herald"
+# from The Astronomical Society of Japan [3] in which it mentioned the fact
+# that:
+#
+# 1. Standard Time of the Country (Japan) was adopted on Jan 1, 1888, using
+# the time at 135E (GMT+9)
+#
+# 2. Standard Time of the Country was renamed to Central Standard Time, on Jan
+# 1, 1898, and on the same day, the new territories Taiwan and Penghu islands,
+# as well as Yaeyama and Miyako islands, adopted a new time zone called
+# Western Standard Time, which is in GMT+8.
+#
+# 3. Western Standard Time was deprecated on Sep 30, 1937. From then all the
+# territories of Japan adopted the same time zone, which is Central Standard
+# Time.
+#
+# [1] Academica Historica, Taiwan:
+# http://163.29.208.22:8080/govsaleShowImage/connect_img.php?s=00101738900090036&e=00101738900090037
+# [2] Nat'l Cheng Kung University 70th Anniversary Special Site:
+# http://www.ncku.edu.tw/~ncku70/menu/001/01_01.htm
+# [3] Yukio Niimi, The Standard Time in Japan (1997), p.475:
+# http://www.asj.or.jp/geppou/archive_open/1997/pdf/19971001c.pdf
+
+# Yu-Cheng Chuang (2014-07-03):
+# I finally have found the real official gazette about changing back to
+# Western Standard Time on Sep 21 in Taiwan.  It's Taiwan Governor-General
+# Bulletin No. 386 in Showa 20 years (1945), published on Sep 19, 1945. [1] ...
+# [It] abolishes Bulletin No. 207 in Showa 12 years (1937), which is a local
+# bulletin in Taiwan for that Ordinance No. 529. It also mentioned that 1am on
+# Sep 21, 1945 will be 12am on Sep 21.  I think this bulletin is much more
+# official than the one I mentioned in my first mail, because it's from the
+# top-level government in Taiwan. If you're going to quote any resource, this
+# would be a good one.
+# [1] Taiwan Governor-General Gazette, No. 1018, Sep 19, 1945:
+# http://db2.th.gov.tw/db2/view/viewImg.php?imgcode=0072031018a&num=19&bgn=019&end=019&otherImg=&type=gener
+
+# From Yu-Cheng Chuang (2014-07-02):
+# In 1946, DST in Taiwan was from May 15 and ended on Sep 30. The info from
+# Central Weather Bureau website was not correct.
+#
+# Original Bulletin:
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=03502F0AKM1AF
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0350300AKM1B0 (cont.)
+#
+# In 1947, DST in Taiwan was expanded to Oct 31. There is a backup of that
+# telegram announcement from Taiwan Province Government:
+#
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0360310AKZ431
+#
+# Here is a brief translation:
+#
+#   The Summer Time this year is adopted from midnight Apr 15 until Sep 20
+#   midnight. To save (energy?) consumption, we're expanding Summer Time
+#   adoption till Oct 31 midnight.
+#
+# The Central Weather Bureau website didn't mention that, however it can
+# be found from historical government announcement database.
+
+# From Paul Eggert (2014-07-03):
+# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
+# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
-Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
+Rule	Taiwan	1946	only	-	May	15	0:00	1:00	D
+Rule	Taiwan	1946	only	-	Oct	1	0:00	0	S
+Rule	Taiwan	1947	only	-	Apr	15	0:00	1:00	D
+Rule	Taiwan	1947	only	-	Nov	1	0:00	0	S
+Rule	Taiwan	1948	1951	-	May	1	0:00	1:00	D
+Rule	Taiwan	1948	1951	-	Oct	1	0:00	0	S
 Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
 Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
 Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
@@ -648,11 +762,14 @@
 Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
-Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
-Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
+Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
+Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
+# Taipei or Taibei or T'ai-pei
+Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
+			8:00	-	JWST	1937 Oct  1
+			9:00	-	JST	1945 Sep 21  1:00
 			8:00	Taiwan	C%sT
 
 # Macau (Macao, Aomen)
@@ -672,7 +789,7 @@
 Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
 Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Macau	7:34:20 -	LMT	1912
+Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
 			8:00	Macau	MO%sT	1999 Dec 20 # return to China
 			8:00	PRC	C%sT
 
@@ -721,7 +838,7 @@
 # republic has changed its time zone back to that of Moscow.  As a result it
 # is now just four hours ahead of Greenwich Mean Time, rather than five hours
 # ahead.  The switch was decreed by the pro-Western president of Georgia,
-# Mikhail Saakashvili, who said the change was partly prompted by the process
+# Mikheil Saakashvili, who said the change was partly prompted by the process
 # of integration into Europe.
 
 # From Teimuraz Abashidze (2005-11-07):
@@ -734,29 +851,31 @@
 # I don't know what can be done, especially knowing that some years ago our
 # DST rules where changed THREE TIMES during one month.
 
+# Milne 1899 says Tbilisi (Tiflis) time was 2:59:05.7.
+# Byalokoz 1919 says Georgia was 2:59:11.
+# Go with Byalokoz.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
-			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
+Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
+			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
 			3:00	-	TBIT	1957 Mar    # Tbilisi Time
-			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia TBI%sT	1991 Mar 31  2:00s
 			3:00	1:00	TBIST	1991 Apr  9 # independence
-			3:00 RussiaAsia GE%sT	1992 # Georgia Time
+			3:00 RussiaAsia GE%sT	1992        # Georgia Time
 			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
 			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
 			4:00	1:00	GEST	1997 Mar lastSun
 			4:00 E-EurAsia	GE%sT	2004 Jun 27
-			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
+			3:00 RussiaAsia	GE%sT	2005 Mar lastSun  2:00
 			4:00	-	GET
 
 # East Timor
 
 # See Indonesia for the 1945 transition.
 
-# From Joao Carrascalao, brother of the former governor of East Timor, in
-# <a href="http://etan.org/et99c/december/26-31/30ETMAY.htm">
+# From João Carrascalão, brother of the former governor of East Timor, in
 # East Timor may be late for its millennium
-# </a> (1999-12-26/31):
+# <http://etan.org/et99c/december/26-31/30ETMAY.htm> (1999-12-26/31):
 # Portugal tried to change the time forward in 1974 because the sun
 # rises too early but the suggestion raised a lot of problems with the
 # Timorese and I still don't think it would work today because it
@@ -766,25 +885,25 @@
 # We don't have any record of the above attempt.
 # Most likely our records are incomplete, but we have no better data.
 
-# <a href="http://www.hri.org/news/world/undh/last/00-08-16.undh.html">
 # From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
-# (2000-08-16)</a>:
+# http://www.hri.org/news/world/undh/2000/00-08-16.undh.html
+# (2000-08-16):
 # The Cabinet of the East Timor Transition Administration decided
 # today to advance East Timor's time by one hour.  The time change,
 # which will be permanent, with no seasonal adjustment, will happen at
 # midnight on Saturday, September 16.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Dili	8:22:20 -	LMT	1912
+Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
 			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
 			9:00	-	JST	1945 Sep 23
 			9:00	-	TLT	1976 May  3
-			8:00	-	WITA	2000 Sep 17 00:00
+			8:00	-	WITA	2000 Sep 17  0:00
 			9:00	-	TLT
 
 # India
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
+Zone	Asia/Kolkata	5:53:28 -	LMT	1880        # Kolkata
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
 			6:30	-	BURT	1942 May 15 # Burma Time
 			5:30	-	IST	1942 Sep
@@ -798,7 +917,7 @@
 # Indonesia
 #
 # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
-# <http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime>
+# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
 # says that Indonesia's time zones changed on 1988-01-01.  Looking at some
 # time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
 # and Kalimantan Tengah) switching from UTC+8 to UTC+7.
@@ -810,7 +929,7 @@
 # other formal surrender ceremonies were September 9, 11, and 13, plus
 # September 12 for the regional surrender to Mountbatten in Singapore.
 # These would be the earliest possible times for a change.
-# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
+# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
 # Traditionnelles, 1987, Paris) says that Java and Madura switched
 # from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
 # (Hollandia).  For now, assume all Indonesian locations other than Jayapura
@@ -835,7 +954,7 @@
 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
 # but this must be a typo.
 			7:07:12	-	BMT	1923 Dec 31 23:47:12 # Batavia
-			7:20	-	JAVT	1932 Nov	 # Java Time
+			7:20	-	JAVT	1932 Nov    # Java Time
 			7:30	-	WIB	1942 Mar 23
 			9:00	-	JST	1945 Sep 23
 			7:30	-	WIB	1948 May
@@ -861,7 +980,7 @@
 # Maluku Islands, West Papua, Papua
 Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 			9:00	-	WIT	1944 Sep  1
-			9:30	-	CST	1964
+			9:30	-	ACST	1964
 			9:00	-	WIT
 
 # Iran
@@ -927,7 +1046,7 @@
 # Several of my users have reported that Iran will not observe DST anymore:
 # http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
 #
-# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
+# From Reuters (2007-09-16), with a heads-up from Jesper Nørgaard Welen:
 # ... the Guardian Council ... approved a law on Sunday to re-introduce
 # daylight saving time ...
 # http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
@@ -993,7 +1112,7 @@
 Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
-			3:25:44	-	TMT	1946	# Tehran Mean Time
+			3:25:44	-	TMT	1946     # Tehran Mean Time
 			3:30	-	IRST	1977 Nov
 			4:00	Iran	IR%sT	1979
 			3:30	Iran	IR%sT
@@ -1018,17 +1137,11 @@
 # From Steffen Thorsen (2008-03-10):
 # The cabinet in Iraq abolished DST last week, according to the following
 # news sources (in Arabic):
-# <a href="http://www.aljeeran.net/wesima_articles/news-20080305-98602.html">
 # http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
-# </a>
-# <a href="http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10">
 # http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
-# </a>
 #
 # We have published a short article in English about the change:
-# <a href="http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html">
 # http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
@@ -1037,14 +1150,14 @@
 Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
 Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
 Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
-# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the ':01' is a typo.
 # Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
 #
 Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
 Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baghdad	2:57:40	-	LMT	1890
-			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
+			2:57:36	-	BMT	1918     # Baghdad Mean Time?
 			3:00	-	AST	1982 May
 			3:00	Iraq	A%sT
 
@@ -1272,7 +1385,7 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
-			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
+			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
 			2:00	Zion	I%sT
 
 
@@ -1281,15 +1394,15 @@
 
 # Japan
 
-# `9:00' and `JST' is from Guy Harris.
+# '9:00' and 'JST' is from Guy Harris.
 
 # From Paul Eggert (1995-03-06):
 # Today's _Asahi Evening News_ (page 4) reports that Japan had
-# daylight saving between 1948 and 1951, but ``the system was discontinued
-# because the public believed it would lead to longer working hours.''
+# daylight saving between 1948 and 1951, but "the system was discontinued
+# because the public believed it would lead to longer working hours."
 
-# From Mayumi Negishi in the 2005-08-10 Japan Times
-# <http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm>:
+# From Mayumi Negishi in the 2005-08-10 Japan Times:
+# http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm
 # Occupation authorities imposed daylight-saving time on Japan on
 # [1948-05-01]....  But lack of prior debate and the execution of
 # daylight-saving time just three days after the bill was passed generated
@@ -1313,7 +1426,8 @@
 
 # From Hideyuki Suzuki (1998-11-09):
 # 'Tokyo' usually stands for the former location of Tokyo Astronomical
-# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# Observatory: 139 degrees 44' 40.90" E (9h 18m 58.727s),
+# 35 degrees 39' 16.0" N.
 # This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
 # edited by National Astronomical Observatory of Japan....
 # JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
@@ -1321,10 +1435,10 @@
 
 # From Hideyuki Suzuki (1998-11-16):
 # The ordinance No. 51 (1886) established "standard time" in Japan,
-# which stands for the time on E 135 degree.
+# which stands for the time on 135 degrees E.
 # In the ordinance No. 167 (1895), "standard time" was renamed to "central
 # standard time".  And the same ordinance also established "western standard
-# time", which stands for the time on E 120 degree....  But "western standard
+# time", which stands for the time on 120 degrees E....  But "western standard
 # time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
 # 167, there is no mention regarding for what place western standard time is
 # standard....
@@ -1332,27 +1446,33 @@
 # I wrote "ordinance" above, but I don't know how to translate.
 # In Japanese it's "chokurei", which means ordinance from emperor.
 
-# Shanks & Pottenger claim JST in use since 1896, and that a few
-# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
-# ordinances took effect on Jan 1.
+# From Yu-Cheng Chuang (2013-07-12):
+# ...the Meiji Emperor announced Ordinance No. 167 of Meiji Year 28 "The clause
+# about standard time" ... The adoption began from Jan 1, 1896.
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+#
+# ...the Showa Emperor announced Ordinance No. 529 of Showa Year 12 ... which
+# means the whole Japan territory, including later occupations, adopt Japan
+# Central Time (UTC+9). The adoption began on Oct 1, 1937.
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
-			9:00	-	JST	1896
-			9:00	-	CJT	1938
+			9:00	-	JST	1896 Jan  1
+			9:00	-	JCST	1937 Oct  1
 			9:00	Japan	J%sT
 # Since 1938, all Japanese possessions have been like Asia/Tokyo.
 
 # Jordan
 #
-# From <a href="http://star.arabia.com/990701/JO9.html">
-# Jordan Week (1999-07-01) </a> via Steffen Thorsen (1999-09-09):
+# From <http://star.arabia.com/990701/JO9.html>
+# Jordan Week (1999-07-01) via Steffen Thorsen (1999-09-09):
 # Clocks in Jordan were forwarded one hour on Wednesday at midnight,
 # in accordance with the government's decision to implement summer time
 # all year round.
 #
-# From <a href="http://star.arabia.com/990930/JO9.html">
-# Jordan Week (1999-09-30) </a> via Steffen Thorsen (1999-11-09):
+# From <http://star.arabia.com/990930/JO9.html>
+# Jordan Week (1999-09-30) via Steffen Thorsen (1999-11-09):
 # Winter time starts today Thursday, 30 September. Clocks will be turned back
 # by one hour.  This is the latest government decision and it's final!
 # The decision was taken because of the increase in working hours in
@@ -1372,9 +1492,7 @@
 
 # From Steffen Thorsen (2009-04-02):
 # This single one might be good enough, (2009-03-24, Arabic):
-# <a href="http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279">
 # http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
-# </a>
 #
 # Google's translation:
 #
@@ -1465,9 +1583,8 @@
 # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
 # - Oral switched from +5:00 to +4:00 in spring 1989.
 
-# <a href="http://www.kazsociety.org.uk/news/2005/03/30.htm">
-# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
-# </a>
+# From Kazakhstan Embassy's News Bulletin #11
+# <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
 # The Government of Kazakhstan passed a resolution March 15 abolishing
 # daylight saving time citing lack of economic benefits and health
 # complications coupled with a decrease in productivity.
@@ -1500,10 +1617,10 @@
 			6:00	-	KIZT	1982 Apr  1
 			5:00 RussiaAsia	KIZ%sT	1991
 			5:00	-	KIZT	1991 Dec 16 # independence
-			5:00	-	QYZT	1992 Jan 19 2:00
+			5:00	-	QYZT	1992 Jan 19  2:00
 			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
 			6:00	-	QYZT
-# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
+# Aqtobe (aka Aktobe, formerly Aktyubinsk)
 Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
 			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
 			5:00	-	AKTT	1981 Apr  1
@@ -1523,7 +1640,7 @@
 			6:00	-	SHET	1982 Apr  1
 			5:00 RussiaAsia	SHE%sT	1991
 			5:00	-	SHET	1991 Dec 16 # independence
-			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
+			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun  2:00 # Aqtau Time
 			4:00 RussiaAsia	AQT%sT	2005 Mar 15
 			5:00	-	AQTT
 # West Kazakhstan
@@ -1532,7 +1649,7 @@
 			5:00	-	URAT	1981 Apr  1
 			5:00	1:00	URAST	1981 Oct  1
 			6:00	-	URAT	1982 Apr  1
-			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
+			5:00 RussiaAsia	URA%sT	1989 Mar 26  2:00
 			4:00 RussiaAsia	URA%sT	1991
 			4:00	-	URAT	1991 Dec 16 # independence
 			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
@@ -1543,7 +1660,7 @@
 
 # From Paul Eggert (2005-08-15):
 # According to an article dated today in the Kyrgyzstan Development Gateway
-# <http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml>
+# http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml
 # Kyrgyzstan is canceling the daylight saving time system.  I take the article
 # to mean that they will leave their clocks at 6 hours ahead of UTC.
 # From Malik Abdugaliev (2005-09-21):
@@ -1558,17 +1675,17 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
 			5:00	-	FRUT	1930 Jun 21 # Frunze Time
-			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
-			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
-			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
+			6:00 RussiaAsia FRU%sT	1991 Mar 31  2:00s
+			5:00	1:00	FRUST	1991 Aug 31  2:00 # independence
+			5:00	Kyrgyz	KG%sT	2005 Aug 12 # Kyrgyzstan Time
 			6:00	-	KGT
 
 ###############################################################################
 
 # Korea (North and South)
 
-# From Annie I. Bang (2006-07-10) in
-# <http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp>:
+# From Annie I. Bang (2006-07-10):
+# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
 # The Ministry of Commerce, Industry and Energy has already
 # commissioned a research project [to reintroduce DST] and has said
 # the system may begin as early as 2008....  Korea ran a daylight
@@ -1581,19 +1698,29 @@
 Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
 Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
 
+# From Paul Eggert (2014-07-01):
+# The following entries are from Shanks & Pottenger, except that I
+# guessed that time zone abbreviations through 1945 followed the same
+# rules as discussed under Taiwan, with nominal switches from JST to KST
+# when the respective cities were taken over by the Allies after WWII.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Sep  8
 			9:00	-	KST	1954 Mar 21
 			8:00	ROK	K%sT	1961 Aug 10
 			8:30	-	KST	1968 Oct
 			9:00	ROK	K%sT
 Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Aug 24
 			9:00	-	KST	1954 Mar 21
 			8:00	-	KST	1961 Aug 10
 			9:00	-	KST
@@ -1602,21 +1729,13 @@
 
 # Kuwait
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# From the Arab Times (2007-03-14):
-# The Civil Service Commission (CSC) has approved a proposal forwarded
-# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
-# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
-# <http://www.arabtimesonline.com/arabtimes/kuwait/Viewdet.asp?ID=9950>.
-# From Paul Eggert (2007-03-29):
-# We don't know the details, or whether the approval means it'll happen,
-# so for now we assume no DST.
 Zone	Asia/Kuwait	3:11:56 -	LMT	1950
 			3:00	-	AST
 
 # Laos
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9       # or Viangchan
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -1657,8 +1776,8 @@
 Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
 #
 # peninsular Malaysia
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -1670,12 +1789,12 @@
 			7:30	-	MALT	1982 Jan  1
 			8:00	-	MYT	# Malaysia Time
 # Sabah & Sarawak
-# From Paul Eggert (2006-03-22):
-# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
-# transition dates are from Mok Ly Yng.
+# From Paul Eggert (2014-08-12):
+# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
+# and 1982 transition dates are from Mok Ly Yng.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
-			7:30	-	BORT	1933	# Borneo Time
+			7:30	-	BORT	1933        # Borneo Time
 			8:00	NBorneo	BOR%sT	1942 Feb 16
 			9:00	-	JST	1945 Sep 12
 			8:00	-	BORT	1982 Jan  1
@@ -1683,22 +1802,21 @@
 
 # Maldives
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
-			4:54:00	-	MMT	1960	# Male Mean Time
-			5:00	-	MVT		# Maldives Time
+Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Male
+			4:54:00	-	MMT	1960 # Male Mean Time
+			5:00	-	MVT	# Maldives Time
 
 # Mongolia
 
 # Shanks & Pottenger say that Mongolia has three time zones, but
-# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
-# both say that it has just one.
+# The USNO (1995-12-21) and the CIA map Standard Time Zones of the World
+# (2005-03) both say that it has just one.
 
 # From Oscar van Vlijmen (1999-12-11):
-# <a href="http://www.mongoliatourism.gov.mn/general.htm">
 # General Information Mongolia
-# </a> (1999-09)
+# <http://www.mongoliatourism.gov.mn/general.htm> (1999-09)
 # "Time: Mongolia has two time zones. Three westernmost provinces of
-# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# Bayan-Ölgii, Uvs, and Hovd are one hour earlier than the capital city, and
 # the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
 # eight hours."
 
@@ -1709,7 +1827,7 @@
 # of implementation may have been different....
 # Some maps in the past have indicated that there was an additional time
 # zone in the eastern part of Mongolia, including the provinces of Dornod,
-# Suhbaatar, and possibly Khentij.
+# Sükhbaatar, and possibly Khentii.
 
 # From Paul Eggert (1999-12-15):
 # Naming and spelling is tricky in Mongolia.
@@ -1723,10 +1841,10 @@
 # (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
 # there are three time zones.
 #
-# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
-# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
-#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
-# Provinces [at 9:00]: Dornod, Sukhbaatar
+# Provinces [at 7:00]: Bayan-Ölgii, Uvs, Khovd, Zavkhan, Govi-Altai
+# Provinces [at 8:00]: Khövsgöl, Bulgan, Arkhangai, Khentii, Töv,
+#	Bayankhongor, Övörkhangai, Dundgovi, Dornogovi, Ömnögovi
+# Provinces [at 9:00]: Dornod, Sükhbaatar
 #
 # [The province of Selenge is omitted from the above lists.]
 
@@ -1743,16 +1861,16 @@
 # We have wildly conflicting information about Mongolia's time zones.
 # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
 # there is only one time zone and that DST is observed, citing Microsoft
-# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
+# Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
 # travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
 # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
 # Washington, DC says there are two time zones, with DST observed.
 # He also found
-# <http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&>
+# http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&
 # which also says that there is DST, and which has a comment by "Toddius"
 # (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
 # The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
-# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
+# and some Eastern provinces are +9 GMT but Sükhbaatar Aimag is SUHK +8.5 GMT.
 # The SUKH timezone is new this year, it is one of the few things the
 # parliament passed during the tumultuous winter session."
 # For now, let's ignore this information, until we have more confirmation.
@@ -1768,29 +1886,23 @@
 # +08:00 instead. Different sources appear to disagree with the tz
 # database on this, e.g.:
 #
-# <a href="http://www.timeanddate.com/worldclock/city.html?n=1026">
 # http://www.timeanddate.com/worldclock/city.html?n=1026
-# </a>
-# <a href="http://www.worldtimeserver.com/current_time_in_MN.aspx">
 # http://www.worldtimeserver.com/current_time_in_MN.aspx
-# </a>
 #
 # both say GMT+08:00.
 
 # From Steffen Thorsen (2008-03-31):
 # eznis airways, which operates several domestic flights, has a flight
 # schedule here:
-# <a href="http://www.eznis.com/Container.jsp?id=112">
 # http://www.eznis.com/Container.jsp?id=112
-# </a>
 # (click the English flag for English)
 #
-# There it appears that flights between Choibalsan and Ulaanbatar arrive
+# There it appears that flights between Choibalsan and Ulaanbaatar arrive
 # about 1:35 - 1:50 hours later in local clock time, no matter the
-# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
-# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
+# direction, while Ulaanbaatar-Khovd takes 2 hours in the Eastern
+# direction and 3:35 back, which indicates that Ulaanbaatar and Khovd are
 # in different time zones (like we know about), while Choibalsan and
-# Ulaanbatar are in the same time zone (correction needed).
+# Ulaanbaatar are in the same time zone (correction needed).
 
 # From Arthur David Olson (2008-05-19):
 # Assume that Choibalsan is indeed offset by 8:00.
@@ -1806,7 +1918,7 @@
 # (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
 #
 # Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
-# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
+# in Choibalsan (more precisely, in Dornod and Sükhbaatar) took place
 # at 02:00 standard time, not at 00:00 local time as in the rest of
 # the country.  That would be odd, and possibly is a result of their
 # correction of 02:00 (in the previous edition) not being done correctly
@@ -1822,13 +1934,13 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
 Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
-			6:00	-	HOVT	1978	# Hovd Time
+			6:00	-	HOVT	1978     # Hovd Time
 			7:00	Mongol	HOV%sT
 # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
 Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
-			7:00	-	ULAT	1978	# Ulaanbaatar Time
+			7:00	-	ULAT	1978     # Ulaanbaatar Time
 			8:00	Mongol	ULA%sT
-# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
+# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan,
 # Choybalsan, Sanbejse, Tchoibalsan
 Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
 			7:00	-	ULAT	1978
@@ -1860,7 +1972,7 @@
 # 00:01 was to make it clear which day it was on.
 
 # From Paul Eggert (2002-03-15):
-# Jesper Norgaard found this URL:
+# Jesper Nørgaard found this URL:
 # http://www.pak.gov.pk/public/news/app/app06_dec.htm
 # (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
 # advance the clocks by one hour on the night between the first
@@ -1892,43 +2004,30 @@
 # Here is an article that Pakistan plan to introduce Daylight Saving Time
 # on June 1, 2008 for 3 months.
 #
-# "... The federal cabinet on Wednesday announced a new conservation plan to help
-# reduce load shedding by approving the closure of commercial centres at 9pm and
-# moving clocks forward by one hour for the next three months.
-# ...."
+# "... The federal cabinet on Wednesday announced a new conservation plan to
+# help reduce load shedding by approving the closure of commercial centres at
+# 9pm and moving clocks forward by one hour for the next three months. ...."
 #
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html">
 # http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
-# </a>
-# OR
-# <a href="http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4">
 # http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
-# </a>
 
 # From Arthur David Olson (2008-05-19):
 # XXX--midnight transitions is a guess; 2008 only is a guess.
 
 # From Alexander Krivenyshev (2008-08-28):
 # Pakistan government has decided to keep the watches one-hour advanced
-# for another 2 months--plan to return to Standard Time on October 31
+# for another 2 months - plan to return to Standard Time on October 31
 # instead of August 31.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
-# </a>
-# OR
-# <a href="http://dailymailnews.com/200808/28/news/dmbrn03.html">
 # http://dailymailnews.com/200808/28/news/dmbrn03.html
-# </a>
 
 # From Alexander Krivenyshev (2009-04-08):
 # Based on previous media reports that "... proposed plan to
 # advance clocks by one hour from May 1 will cause disturbance
 # to the working schedules rather than bringing discipline in
 # official working."
-# <a href="http://www.thenews.com.pk/daily_detail.asp?id=171280">
 # http://www.thenews.com.pk/daily_detail.asp?id=171280
-# </a>
 #
 # recent news that instead of May 2009 - Pakistan plan to
 # introduce DST from April 15, 2009
@@ -1936,15 +2035,8 @@
 # FYI: Associated Press Of Pakistan
 # April 08, 2009
 # Cabinet okays proposal to advance clocks by one hour from April 15
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
-# </a>
-#
-# or
-#
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
-# </a>
 #
 # ....
 # The Federal Cabinet on Wednesday approved the proposal to
@@ -1957,34 +2049,20 @@
 # clocks backward by one hour from October 1. A formal announcement to
 # this effect will be made after the Prime Minister grants approval in
 # this regard."
-# <a href="http://www.thenews.com.pk/updates.asp?id=87168">
 # http://www.thenews.com.pk/updates.asp?id=87168
-# </a>
 
 # From Alexander Krivenyshev (2009-09-28):
 # According to Associated Press Of Pakistan, it is confirmed that
-# Pakistan clocks across the country would be turned back by an hour from October
-# 1, 2009.
+# Pakistan clocks across the country would be turned back by an hour from
+# October 1, 2009.
 #
 # "Clocks to go back one hour from 1 Oct"
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm">
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
-# </a>
-
+#
 # From Steffen Thorsen (2009-09-29):
-# Alexander Krivenyshev wrote:
-# > According to Associated Press Of Pakistan, it is confirmed that
-# > Pakistan clocks across the country would be turned back by an hour from October
-# > 1, 2009.
-#
 # Now they seem to have changed their mind, November 1 is the new date:
-# <a href="http://www.thenews.com.pk/top_story_detail.asp?Id=24742">
 # http://www.thenews.com.pk/top_story_detail.asp?Id=24742
-# </a>
 # "The country's clocks will be reversed by one hour on November 1.
 # Officials of Federal Ministry for Interior told this to Geo News on
 # Monday."
@@ -1996,11 +2074,9 @@
 #
 # We have confirmed this year's end date with both with the Ministry of
 # Water and Power and the Pakistan Electric Power Company:
-# <a href="http://www.timeanddate.com/news/time/pakistan-ends-dst09.html">
 # http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
-# </a>
 
-# From Christoph Goehre (2009-10-01):
+# From Christoph Göhre (2009-10-01):
 # [T]he German Consulate General in Karachi reported me today that Pakistan
 # will go back to standard time on 1st of November.
 
@@ -2016,22 +2092,17 @@
 # Now, it seems that the decision to not observe DST in final:
 #
 # "Govt Withdraws Plan To Advance Clocks"
-# <a href="http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041">
 # http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
-# </a>
 #
 # "People laud PM's announcement to end DST"
-# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2">
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
-# </a>
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
 Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
 Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
-Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
+Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
 Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
-Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
@@ -2105,10 +2176,9 @@
 # the PA has decided to implement DST in April.
 
 # From Paul Eggert (1999-09-20):
-# Daoud Kuttab writes in
-# <a href="http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html">
-# Holiday havoc
-# </a> (Jerusalem Post, 1999-04-22) that
+# Daoud Kuttab writes in Holiday havoc
+# http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html
+# (Jerusalem Post, 1999-04-22) that
 # the Palestinian National Authority changed to DST on 1999-04-15.
 # I vaguely recall that they switch back in October (sorry, forgot the source).
 # For now, let's assume that the spring switch was at 24:00,
@@ -2121,7 +2191,7 @@
 # A user from Gaza reported that Gaza made the change early because of
 # the Ramadan.  Next year Ramadan will be even earlier, so I think
 # there is a good chance next year's end date will be around two weeks
-# earlier--the same goes for Jordan.
+# earlier - the same goes for Jordan.
 
 # From Steffen Thorsen (2006-08-17):
 # I was informed by a user in Bethlehem that in Bethlehem it started the
@@ -2140,7 +2210,7 @@
 # I guess it is likely that next year's date will be moved as well,
 # because of the Ramadan.
 
-# From Jesper Norgaard Welen (2007-09-18):
+# From Jesper Nørgaard Welen (2007-09-18):
 # According to Steffen Thorsen's web site the Gaza Strip and the rest of the
 # Palestinian territories left DST early on 13.th. of September at 2:00.
 
@@ -2157,16 +2227,9 @@
 # Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
 # the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
 #
-# <a href="http://www.guardian.co.uk/world/feedarticle/7759001">
 # http://www.guardian.co.uk/world/feedarticle/7759001
-# </a>
-# <a href="http://www.abcnews.go.com/International/wireStory?id=5676087">
 # http://www.abcnews.go.com/International/wireStory?id=5676087
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
-# </a>
 
 # From Alexander Krivenyshev (2009-03-26):
 # According to the Palestine News Network (arabic.pnn.ps), Palestinian
@@ -2174,24 +2237,17 @@
 # 26 and continue until the night of 27 September 2009.
 #
 # (in Arabic)
-# <a href="http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850">
 # http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
-# </a>
 #
-# or
 # (English translation)
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_westbank01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
-# </a>
 
 # From Steffen Thorsen (2009-08-31):
 # Palestine's Council of Ministers announced that they will revert back to
 # winter time on Friday, 2009-09-04.
 #
 # One news source:
-# <a href="http://www.safa.ps/ara/?action=showdetail&seid=4158">
 # http://www.safa.ps/ara/?action=showdetail&seid=4158
-# </a>
 # (Palestinian press agency, Arabic),
 # Google translate: "Decided that the Palestinian government in Ramallah
 # headed by Salam Fayyad, the start of work in time for the winter of
@@ -2200,9 +2256,7 @@
 #
 # We are not sure if Gaza will do the same, last year they had a different
 # end date, we will keep this page updated:
-# <a href="http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html">
 # http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
-# </a>
 
 # From Alexander Krivenyshev (2009-09-02):
 # Seems that Gaza Strip will go back to Winter Time same date as West Bank.
@@ -2212,51 +2266,35 @@
 #
 # "Winter time unite the West Bank and Gaza"
 # (from Palestinian National Authority):
-# <a href="http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
 # http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html>
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
-# </a>
 
 # From Alexander Krivenyshev (2010-03-19):
 # According to Voice of Palestine DST will last for 191 days, from March
 # 26, 2010 till "the last Sunday before the tenth day of Tishri
 # (October), each year" (October 03, 2010?)
 #
-# <a href="http://palvoice.org/forums/showthread.php?t=245697">
 # http://palvoice.org/forums/showthread.php?t=245697
-# </a>
 # (in Arabic)
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_westbank03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
-# </a>
 
 # From Steffen Thorsen (2010-03-24):
 # ...Ma'an News Agency reports that Hamas cabinet has decided it will
 # start one day later, at 12:01am. Not sure if they really mean 12:01am or
 # noon though:
 #
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=271178">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
-# </a>
 # (Ma'an News Agency)
 # "At 12:01am Friday, clocks in Israel and the West Bank will change to
 # 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
 
 # From Steffen Thorsen (2010-08-11):
 # According to several sources, including
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=306795">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
-# </a>
 # the clocks were set back one hour at 2010-08-11 00:00:00 local time in
 # Gaza and the West Bank.
 # Some more background info:
-# <a href="http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html">
 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
-# </a>
 
 # From Steffen Thorsen (2011-08-26):
 # Gaza and the West Bank did go back to standard time in the beginning of
@@ -2264,13 +2302,9 @@
 # 00:00 (so two periods of DST in 2011). The pause was because of
 # Ramadan.
 #
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=416217">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
-# </a>
 # Additional info:
-# <a href="http://www.timeanddate.com/news/time/palestine-dst-2011.html">
 # http://www.timeanddate.com/news/time/palestine-dst-2011.html
-# </a>
 
 # From Alexander Krivenyshev (2011-08-27):
 # According to the article in The Jerusalem Post:
@@ -2280,14 +2314,9 @@
 # The Hamas government said on Saturday that it won't observe summertime after
 # the Muslim feast of Id al-Fitr, which begins on Tuesday..."
 # ...
-# <a href="http://www.jpost.com/MiddleEast/Article.aspx?id=235650">
 # http://www.jpost.com/MiddleEast/Article.aspx?id=235650
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
-# </a>
-# The rules for Egypt are stolen from the `africa' file.
+# The rules for Egypt are stolen from the 'africa' file.
 
 # From Steffen Thorsen (2011-09-30):
 # West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
@@ -2295,26 +2324,18 @@
 # So West Bank and Gaza now have the same time again.
 #
 # Many sources, including:
-# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=424808">
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
-# </a>
 
 # From Steffen Thorsen (2012-03-26):
 # Palestinian news sources tell that both Gaza and West Bank will start DST
 # on Friday (Thursday midnight, 2012-03-29 24:00).
 # Some of many sources in Arabic:
-# <a href="http://www.samanews.com/index.php?act=Show&id=122638">
 # http://www.samanews.com/index.php?act=Show&id=122638
-# </a>
 #
-# <a href="http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html">
 # http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
-# </a>
 #
 # Our brief summary:
-# <a href="http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html">
 # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
-# </a>
 
 # From Steffen Thorsen (2013-03-26):
 # The following news sources tells that Palestine will "start daylight saving
@@ -2374,10 +2395,10 @@
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
 			2:00	Zion	I%sT	1996
 			2:00	Jordan	EE%sT	1999
-			2:00 Palestine	EE%sT	2008 Aug 29 0:00
+			2:00 Palestine	EE%sT	2008 Aug 29  0:00
 			2:00	-	EET	2008 Sep
 			2:00 Palestine	EE%sT	2010
-			2:00	-	EET	2010 Mar 27 0:01
+			2:00	-	EET	2010 Mar 27  0:01
 			2:00 Palestine	EE%sT	2011 Aug  1
 			2:00	-	EET	2012
 			2:00 Palestine	EE%sT
@@ -2393,25 +2414,27 @@
 # no information
 
 # Philippines
-# On 1844-08-16, Narciso Claveria, governor-general of the
+# On 1844-08-16, Narciso Clavería, governor-general of the
 # Philippines, issued a proclamation announcing that 1844-12-30 was to
-# be immediately followed by 1845-01-01.  Robert H. van Gent has a
-# transcript of the decree in <http://www.phys.uu.nl/~vgent/idl/idl.htm>.
-# The rest of the data are from Shanks & Pottenger.
+# be immediately followed by 1845-01-01; see R.H. van Gent's
+# History of the International Date Line
+# http://www.staff.science.uu.nl/~gent0113/idl/idl_philippines.htm
+# The rest of the data entries are from Shanks & Pottenger.
 
-# From Paul Eggert (2006-04-25):
-# Tomorrow's Manila Standard reports that the Philippines Department of
-# Trade and Industry is considering adopting DST this June when the
-# rainy season begins.  See
-# <http://www.manilastandardtoday.com/?page=politics02_april26_2006>.
-# For now, we'll ignore this, since it's not definite and we lack details.
-#
-# From Jesper Norgaard Welen (2006-04-26):
+# From Jesper Nørgaard Welen (2006-04-26):
 # ... claims that Philippines had DST last time in 1990:
 # http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
 # [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
 # but no details]
 
+# From Paul Eggert (2014-08-14):
+# The following source says DST may be instituted November-January and again
+# March-June, but this is not definite.  It also says DST was last proclaimed
+# during the Ramos administration (1992-1998); but again, no details.
+# Carcamo D. PNoy urged to declare use of daylight saving time.
+# Philippine Star 2014-08-05
+# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
 Rule	Phil	1937	only	-	Feb	1	0:00	0	-
@@ -2428,18 +2451,39 @@
 
 # Qatar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
+Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
 # Saudi Arabia
+#
+# From Paul Eggert (2014-07-15):
+# Time in Saudi Arabia and other countries in the Arabian peninsula was not
+# standardized until relatively recently; we don't know when, and possibly it
+# has never been made official.  Richard P Hunt, in "Islam city yielding to
+# modern times", New York Times (1961-04-09), p 20, wrote that only airlines
+# observed standard time, and that people in Jeddah mostly observed quasi-solar
+# time, doing so by setting their watches at sunrise to 6 o'clock (or to 12
+# o'clock for "Arab" time).
+#
+# The TZ database cannot represent quasi-solar time; airline time is the best
+# we can do.  The 1946 foreign air news digest of the U.S. Civil Aeronautics
+# Board (OCLC 42299995) reported that the "... Arabian Government, inaugurated
+# a weekly Dhahran-Cairo service, via the Saudi Arabian cities of Riyadh and
+# Jidda, on March 14, 1947".  Shanks & Pottenger guessed 1950; go with the
+# earlier date.
+#
+# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
+# time zones; the other zone, at UTC+4, was in the far eastern part of
+# the country.  Ignore this, as it's before our 1970 cutoff.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Riyadh	3:06:52 -	LMT	1950
+Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
 			3:00	-	AST
 
 # Singapore
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -2465,26 +2509,24 @@
 
 # From Paul Eggert (1996-09-03):
 # "Sri Lanka advances clock by an hour to avoid blackout"
-# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# (<http://www.virtual-pc.com/lankaweb/news/items/240596-2.html>, 1996-05-24,
 # no longer available as of 1999-08-17)
-# reported ``the country's standard time will be put forward by one hour at
-# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
+# reported "the country's standard time will be put forward by one hour at
+# midnight Friday (1830 GMT) 'in the light of the present power crisis'."
 #
 # From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
-# by Shamindra in
-# <a href="news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net">
-# Daily News - Hot News Section (1996-10-26)
-# </a>:
+# by Shamindra in Daily News - Hot News Section
+# <news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net> (1996-10-26):
 # With effect from 12.30 a.m. on 26th October 1996
 # Sri Lanka will be six (06) hours ahead of GMT.
 
-# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
+# From Jesper Nørgaard Welen (2006-04-14), quoting Sri Lanka News Online
 # <http://news.sinhalaya.com/wmview.php?ArtID=11002> (2006-04-13):
 # 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
 # at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
 
 # From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
-# <http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML>
+# http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML
 # [The Tamil Tigers] never accepted the original 1996 time change and simply
 # kept their clocks set five and a half hours ahead of Greenwich Mean
 # Time (GMT), in line with neighbor India.
@@ -2498,7 +2540,7 @@
 # twice in 1996 and probably SL Government or its standardization
 # agencies never declared an abbreviation as a national standard.
 #
-# I recollect before the recent change the government annoucemments
+# I recollect before the recent change the government announcements
 # mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
 # Time and no mention was made about the abbreviation.
 #
@@ -2508,7 +2550,7 @@
 # item....
 #
 # Within Sri Lanka I think LKT is well known among computer users and
-# adminsitrators.  In my opinion SLT may not be a good choice because the
+# administrators.  In my opinion SLT may not be a good choice because the
 # nation's largest telcom / internet operator Sri Lanka Telcom is well
 # known by that abbreviation - simply as SLT (there IP domains are
 # slt.lk and sltnet.lk).
@@ -2523,13 +2565,13 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
-			5:19:32	-	MMT	1906	# Moratuwa Mean Time
+			5:19:32	-	MMT	1906        # Moratuwa Mean Time
 			5:30	-	IST	1942 Jan  5
 			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16 2:00
-			5:30	-	IST	1996 May 25 0:00
-			6:30	-	LKT	1996 Oct 26 0:30
-			6:00	-	LKT	2006 Apr 15 0:30
+			5:30	1:00	IST	1945 Oct 16  2:00
+			5:30	-	IST	1996 May 25  0:00
+			6:30	-	LKT	1996 Oct 26  0:30
+			6:00	-	LKT	2006 Apr 15  0:30
 			5:30	-	IST
 
 # Syria
@@ -2580,7 +2622,7 @@
 # Today the AP reported "Syria will switch to summertime at midnight Thursday."
 # http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
 Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
-# From Jesper Norgard (2007-10-27):
+# From Jesper Nørgaard (2007-10-27):
 # The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
 # not take place 1st November at 0:00 o'clock but 1st November at 24:00 or
 # rather Midnight between Thursday and Friday. This does make more sense than
@@ -2589,7 +2631,7 @@
 # it is implemented at midnight of the last workday before weekend...
 #
 # From Steffen Thorsen (2007-10-27):
-# Jesper Norgaard Welen wrote:
+# Jesper Nørgaard Welen wrote:
 #
 # > "Winter local time in Syria will be observed at midnight of Thursday 1
 # > November 2007, and the clock will be put back 1 hour."
@@ -2605,8 +2647,7 @@
 
 # From Stephen Colebourne (2008-03-17):
 # For everyone's info, I saw an IATA time zone change for [Syria] for
-# this month (March 2008) in the last day or so...This is the data IATA
-# are now using:
+# this month (March 2008) in the last day or so....
 # Country     Time Standard   --- DST Start ---   --- DST End ---  DST
 # Name        Zone Variation   Time    Date        Time    Date
 # Variation
@@ -2618,16 +2659,15 @@
 # From Arthur David Olson (2008-03-17):
 # Here's a link to English-language coverage by the Syrian Arab News
 # Agency (SANA)...
-# <a href="http://www.sana.sy/eng/21/2008/03/11/165173.htm">
 # http://www.sana.sy/eng/21/2008/03/11/165173.htm
-# </a>...which reads (in part) "The Cabinet approved the suggestion of the
+# ...which reads (in part) "The Cabinet approved the suggestion of the
 # Ministry of Electricity to begin daylight savings time on Friday April
 # 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
 # Since Syria is two hours east of UTC, the 2200 and 2100 transition times
 # shown above match up with midnight in Syria.
 
 # From Arthur David Olson (2008-03-18):
-# My buest guess at a Syrian rule is "the Friday nearest April 1";
+# My best guess at a Syrian rule is "the Friday nearest April 1";
 # coding that involves either using a "Mar Fri>=29" construct that old time zone
 # compilers can't handle  or having multiple Rules (a la Israel).
 # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
@@ -2640,37 +2680,27 @@
 # winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
 # clocks back 60 minutes).
 #
-# <a href="http://sana.sy/ara/2/2008/10/07/195459.htm">
 # http://sana.sy/ara/2/2008/10/07/195459.htm
-# </a>
 
 # From Steffen Thorsen (2009-03-19):
 # Syria will start DST on 2009-03-27 00:00 this year according to many sources,
 # two examples:
 #
-# <a href="http://www.sana.sy/eng/21/2009/03/17/217563.htm">
 # http://www.sana.sy/eng/21/2009/03/17/217563.htm
-# </a>
 # (English, Syrian Arab News # Agency)
-# <a href="http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209">
 # http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
-# </a>
 # (Arabic, gov-site)
 #
 # We have not found any sources saying anything about when DST ends this year.
 #
 # Our summary
-# <a href="http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html">
 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
-# </a>
 
 # From Steffen Thorsen (2009-10-27):
 # The Syrian Arab News Network on 2009-09-29 reported that Syria will
 # revert back to winter (standard) time on midnight between Thursday
 # 2009-10-29 and Friday 2009-10-30:
-# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm">
 # http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
-# </a>
 
 # From Arthur David Olson (2009-10-28):
 # We'll see if future DST switching times turn out to be end of the last
@@ -2681,23 +2711,17 @@
 # The "Syrian News Station" reported on 2010-03-16 that the Council of
 # Ministers has decided that Syria will start DST on midnight Thursday
 # 2010-04-01: (midnight between Thursday and Friday):
-# <a href="http://sns.sy/sns/?path=news/read/11421">
 # http://sns.sy/sns/?path=news/read/11421 (Arabic)
-# </a>
 
 # From Steffen Thorsen (2012-03-26):
 # Today, Syria's government announced that they will start DST early on Friday
 # (00:00). This is a bit earlier than the past two years.
 #
 # From Syrian Arab News Agency, in Arabic:
-# <a href="http://www.sana.sy/ara/2/2012/03/26/408215.htm">
 # http://www.sana.sy/ara/2/2012/03/26/408215.htm
-# </a>
 #
 # Our brief summary:
-# <a href="http://www.timeanddate.com/news/time/syria-dst-2012.html">
 # http://www.timeanddate.com/news/time/syria-dst-2012.html
-# </a>
 
 # From Arthur David Olson (2012-03-27):
 # Assume last Friday in March going forward XXX.
@@ -2710,7 +2734,7 @@
 Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
+Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
 			2:00	Syria	EE%sT
 
 # Tajikistan
@@ -2718,9 +2742,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
 			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
-			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
-			5:00	1:00	DUSST	1991 Sep  9 2:00s
-			5:00	-	TJT		    # Tajikistan Time
+			6:00 RussiaAsia DUS%sT	1991 Mar 31  2:00s
+			5:00	1:00	DUSST	1991 Sep  9  2:00s
+			5:00	-	TJT	# Tajikistan Time
 
 # Thailand
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2733,9 +2757,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
 			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
-			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
+			5:00 RussiaAsia	ASH%sT	1991 Mar 31  2:00
 			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
-			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
+			4:00 RussiaAsia	TM%sT	1992 Jan 19  2:00
 			5:00	-	TMT
 
 # United Arab Emirates
@@ -2744,8 +2768,9 @@
 			4:00	-	GST
 
 # Uzbekistan
+# Byalokoz 1919 says Uzbekistan was 4:27:53.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
+Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
 			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
 			5:00	-	SAMT	1981 Apr  1
 			5:00	1:00	SAMST	1981 Oct  1
@@ -2753,9 +2778,10 @@
 			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
-Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
+# Milne says Tashkent was 4:37:10.8; round to nearest.
+Zone	Asia/Tashkent	4:37:11 -	LMT	1924 May  2
 			5:00	-	TAST	1930 Jun 21 # Tashkent Time
-			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
+			6:00 RussiaAsia	TAS%sT	1991 Mar 31  2:00
 			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
@@ -2769,13 +2795,13 @@
 # and Pottenger.
 
 # From Arthur David Olson (2008-03-18):
-# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
-# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
+# The English-language name of Vietnam's most populous city is "Ho Chi Minh
+# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
 
 # From Shanks & Pottenger:
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
--- a/jdk/test/sun/util/calendar/zi/tzdata/australasia	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/australasia	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -36,13 +35,13 @@
 # Please see the notes below for the controversy about "EST" versus "AEST" etc.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
-Rule	Aus	1917	only	-	Mar	25	2:00	0	-
-Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
-Rule	Aus	1942	only	-	Mar	29	2:00	0	-
-Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
-Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
-Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
+Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	D
+Rule	Aus	1917	only	-	Mar	25	2:00	0	S
+Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	D
+Rule	Aus	1942	only	-	Mar	29	2:00	0	S
+Rule	Aus	1942	only	-	Sep	27	2:00	1:00	D
+Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	S
+Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	D
 # Go with Whitman and the Australian National Standards Commission, which
 # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
 # 1944/1945 was just like 1943/1944.
@@ -50,26 +49,26 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Northern Territory
 Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
-			 9:00	-	CST	1899 May
-			 9:30	Aus	CST
+			 9:00	-	ACST	1899 May
+			 9:30	Aus	AC%sT
 # Western Australia
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
-Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
-Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
-Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
+Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1991	only	-	Nov	17	2:00s	1:00	D
+Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	D
+Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	S
+Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	D
 Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
-			 8:00	Aus	WST	1943 Jul
-			 8:00	AW	WST
+			 8:00	Aus	AW%sT	1943 Jul
+			 8:00	AW	AW%sT
 Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
-			 8:45	Aus	CWST	1943 Jul
-			 8:45	AW	CWST
+			 8:45	Aus	ACW%sT	1943 Jul
+			 8:45	AW	ACW%sT
 
 # Queensland
 #
@@ -85,150 +84,150 @@
 # so use Lindeman.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
-Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
-Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
+Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	S
+Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	D
+Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	S
 Zone Australia/Brisbane	10:12:08 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT
 Zone Australia/Lindeman  9:55:56 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST	1992 Jul
-			10:00	Holiday	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT	1992 Jul
+			10:00	Holiday	AE%sT
 
 # South Australia
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1972	only	-	Feb	27	2:00s	0	-
-Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AS	1991	only	-	Mar	3	2:00s	0	-
-Rule	AS	1992	only	-	Mar	22	2:00s	0	-
-Rule	AS	1993	only	-	Mar	7	2:00s	0	-
-Rule	AS	1994	only	-	Mar	20	2:00s	0	-
-Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2006	only	-	Apr	2	2:00s	0	-
-Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1972	only	-	Feb	27	2:00s	0	S
+Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AS	1991	only	-	Mar	3	2:00s	0	S
+Rule	AS	1992	only	-	Mar	22	2:00s	0	S
+Rule	AS	1993	only	-	Mar	7	2:00s	0	S
+Rule	AS	1994	only	-	Mar	20	2:00s	0	S
+Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2006	only	-	Apr	2	2:00s	0	S
+Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AS	CST
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AS	AC%sT
 
 # Tasmania
 #
 # From Paul Eggert (2005-08-16):
-# <http://www.bom.gov.au/climate/averages/tables/dst_times.shtml>
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
 # says King Island didn't observe DST from WWII until late 1971.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
-Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
-Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
+Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	S
+Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	D
+Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1967
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT
 Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1971 Jul
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1971 Jul
+			10:00	AT	AE%sT
 
 # Victoria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AV	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AV	AE%sT
 
 # New South Wales
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1972	only	-	Feb	27	2:00s	0	-
-Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
-Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1972	only	-	Feb	27	2:00s	0	S
+Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	S
+Rule	AN	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AN	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AN	AE%sT
 Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
-			10:00	-	EST	1896 Aug 23
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AN	CST	2000
-			9:30	AS	CST
+			10:00	-	AEST	1896 Aug 23
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AN	AC%sT	2000
+			9:30	AS	AC%sT
 
 # Lord Howe Island
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
-Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
-Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
-Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
-Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
-Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
-Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
+Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	D
+Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	S
+Rule	LH	1986	only	-	Oct	19	2:00	0:30	D
+Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	S
+Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	D
+Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2007	only	-	Mar	lastSun	2:00	0	S
+Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	D
 Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
-			10:00	-	EST	1981 Mar
-			10:30	LH	LHST
+			10:00	-	AEST	1981 Mar
+			10:30	LH	LH%sT
 
 # Australian miscellany
 #
@@ -244,8 +243,8 @@
 # Permanent occupation (scientific station) 1911-1915 and since 25 March 1948;
 # sealing and penguin oil station operated Nov 1899 to Apr 1919.  See the
 # Tasmania Parks & Wildlife Service history of sealing at Macquarie Island
-# <http://www.parks.tas.gov.au/index.aspx?base=1828>
-# <http://www.parks.tas.gov.au/index.aspx?base=1831>.
+# http://www.parks.tas.gov.au/index.aspx?base=1828
+# http://www.parks.tas.gov.au/index.aspx?base=1831
 # Guess that it was like Australia/Hobart while inhabited before 2010.
 #
 # From Steffen Thorsen (2010-03-10):
@@ -256,16 +255,16 @@
 #
 # From Arthur David Olson (2013-05-23):
 # The 1919 transition is overspecified below so pre-2013 zics
-# will produce a binary file with an EST-type as the first 32-bit type;
+# will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
 Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1919 Apr 1 0:00s
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1919 Apr  1  0:00s
 			0	-	zzz	1948 Mar 25
-			10:00	Aus	EST	1967
-			10:00	AT	EST	2010 Apr 4 3:00
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
 
 # Christmas
@@ -273,24 +272,14 @@
 Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
 			7:00	-	CXT	# Christmas Island Time
 
-# Cook Is
-# From Shanks & Pottenger:
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
-Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
-Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
-			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
-			-10:00	Cook	CK%sT
-
-# Cocos
+# Cocos (Keeling) Is
 # These islands were ruled by the Ross family from about 1830 to 1978.
 # We don't know when standard time was introduced; for now, we guess 1900.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Cocos	6:27:40	-	LMT	1900
 			6:30	-	CCT	# Cocos Islands Time
 
+
 # Fiji
 
 # Milne gives 11:55:44 for Suva.
@@ -300,20 +289,13 @@
 # from November 29th 2009  to April 25th 2010.
 #
 # "Daylight savings to commence this month"
-# <a href="http://www.radiofiji.com.fj/fullstory.php?id=23719">
 # http://www.radiofiji.com.fj/fullstory.php?id=23719
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji01.html">
 # http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
-# </a>
 
 # From Steffen Thorsen (2009-11-10):
 # The Fiji Government has posted some more details about the approved
 # amendments:
-# <a href="http://www.fiji.gov.fj/publish/page_16198.shtml">
 # http://www.fiji.gov.fj/publish/page_16198.shtml
-# </a>
 
 # From Steffen Thorsen (2010-03-03):
 # The Cabinet in Fiji has decided to end DST about a month early, on
@@ -322,35 +304,24 @@
 # 2011 (last Sunday a good guess?).
 #
 # Official source:
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
-# </a>
 #
 # A bit more background info here:
-# <a href="http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html">
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
-# </a>
 
 # From Alexander Krivenyshev (2010-10-24):
 # According to Radio Fiji and Fiji Times online, Fiji will end DST 3
 # weeks earlier than expected - on March 6, 2011, not March 27, 2011...
 # Here is confirmation from Government of the Republic of the Fiji Islands,
 # Ministry of Information (fiji.gov.fj) web site:
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
-# </a>
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
-# </a>
 
 # From Steffen Thorsen (2011-10-03):
 # Now the dates have been confirmed, and at least our start date
 # assumption was correct (end date was one week wrong).
 #
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155">
-# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
-# </a>
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
 # which says
 # Members of the public are reminded to change their time to one hour in
 # advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
@@ -360,9 +331,7 @@
 # Another change to the Fiji DST end date. In the TZ database the end date for
 # Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
 #
-# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155">
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
-# </a>
 # states:
 #
 # The end of daylight saving scheduled initially for the 26th of February 2012
@@ -400,16 +369,16 @@
 Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
 Rule	Fiji	2014	max	-	Jan	Sun>=18	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26	# Suva
+Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
 
 # French Polynesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
+Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
 			 -9:00	-	GAMT	# Gambier Time
 Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
 			 -9:30	-	MART	# Marquesas Time
-Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
+Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct # Papeete
 			-10:00	-	TAHT	# Tahiti Time
 # Clipperton (near North America) is administered from French Polynesia;
 # it is uninhabited.
@@ -417,14 +386,14 @@
 # Guam
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
-			 9:39:00 -	LMT	1901		# Agana
-			10:00	-	GST	2000 Dec 23	# Guam
+			 9:39:00 -	LMT	1901        # Agana
+			10:00	-	GST	2000 Dec 23 # Guam
 			10:00	-	ChST	# Chamorro Standard Time
 
 # Kiribati
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
-			 12:00	-	GILT		 # Gilbert Is Time
+Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
+			 12:00	-	GILT	# Gilbert Is Time
 Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
 			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
 			-11:00	-	PHOT	1995
@@ -438,7 +407,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
 			 9:43:00 -	LMT	1901
-			 9:00	-	MPT	1969 Oct # N Mariana Is Time
+			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
 			10:00	-	MPT	2000 Dec 23
 			10:00	-	ChST	# Chamorro Standard Time
 
@@ -449,24 +418,24 @@
 			12:00	-	MHT
 Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
 			11:00	-	MHT	1969 Oct
-			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
+			-12:00	-	KWAT	1993 Aug 20 # Kwajalein Time
 			12:00	-	MHT
 
 # Micronesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Chuuk	10:07:08 -	LMT	1901
-			10:00	-	CHUT			# Chuuk Time
-Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
-			11:00	-	PONT			# Pohnpei Time
+			10:00	-	CHUT	# Chuuk Time
+Zone Pacific/Pohnpei	10:32:52 -	LMT	1901 # Kolonia
+			11:00	-	PONT	# Pohnpei Time
 Zone Pacific/Kosrae	10:51:56 -	LMT	1901
-			11:00	-	KOST	1969 Oct	# Kosrae Time
+			11:00	-	KOST	1969 Oct # Kosrae Time
 			12:00	-	KOST	1999
 			11:00	-	KOST
 
 # Nauru
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
-			11:30	-	NRT	1942 Mar 15	# Nauru Time
+Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
+			11:30	-	NRT	1942 Mar 15 # Nauru Time
 			9:00	-	JST	1944 Aug 15
 			11:30	-	NRT	1979 May
 			12:00	-	NRT
@@ -479,7 +448,7 @@
 # Shanks & Pottenger say the following was at 2:00; go with IATA.
 Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
+Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
 			11:00	NC	NC%sT
 
 
@@ -496,7 +465,8 @@
 Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
 Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
 # Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
-# convenient notation for this so we must duplicate the Rule lines.
+# convenient single notation for the date and time of this transition
+# so we must duplicate the Rule lines.
 Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
 Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
 Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
@@ -519,13 +489,14 @@
 Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
 			11:30	NZ	NZ%sT	1946 Jan  1
 			12:00	NZ	NZ%sT
-Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
+Zone Pacific/Chatham	12:13:48 -	LMT	1868 Nov  2
+			12:15	-	CHAST	1946 Jan  1
 			12:45	Chatham	CHA%sT
 
 Link Pacific/Auckland Antarctica/McMurdo
 
 # Auckland Is
-# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers,
 # and scientific personnel have wintered
 
 # Campbell I
@@ -534,48 +505,58 @@
 # previously whalers, sealers, pastoralists, and scientific personnel wintered
 # was probably like Pacific/Auckland
 
+# Cook Is
+# From Shanks & Pottenger:
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
+Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
+Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
+			-10:30	-	CKT	1978 Nov 12 # Cook Is Time
+			-10:00	Cook	CK%sT
+
 ###############################################################################
 
 
 # Niue
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
-			-11:20	-	NUT	1951	# Niue Time
-			-11:30	-	NUT	1978 Oct 1
+Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
+			-11:20	-	NUT	1951        # Niue Time
+			-11:30	-	NUT	1978 Oct  1
 			-11:00	-	NUT
 
 # Norfolk
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
-			11:12	-	NMT	1951	# Norfolk Mean Time
-			11:30	-	NFT		# Norfolk Time
+Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
+			11:12	-	NMT	1951 # Norfolk Mean Time
+			11:30	-	NFT	# Norfolk Time
 
 # Palau (Belau)
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
+Zone Pacific/Palau	8:57:56 -	LMT	1901 # Koror
 			9:00	-	PWT	# Palau Time
 
 # Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
-			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
-			10:00	-	PGT		# Papua New Guinea Time
+			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
+			10:00	-	PGT	# Papua New Guinea Time
 
 # Pitcairn
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
-			-8:30	-	PNT	1998 Apr 27 00:00
+Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
+			-8:30	-	PNT	1998 Apr 27  0:00
 			-8:00	-	PST	# Pitcairn Standard Time
 
 # American Samoa
 Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 			-11:22:48 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
-# Samoa
+# Samoa (formerly and also known as Western Samoa)
 
 # From Steffen Thorsen (2009-10-16):
 # We have been in contact with the government of Samoa again, and received
@@ -586,141 +567,80 @@
 # Sunday of April 2011."
 #
 # Background info:
-# <a href="http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html">
 # http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
-# </a>
 #
 # Samoa's Daylight Saving Time Act 2009 is available here, but does not
 # contain any dates:
-# <a href="http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf">
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
-# </a>
 
 # From Laupue Raymond Hughes (2010-10-07):
 # Please see
-# <a href="http://www.mcil.gov.ws">
 # http://www.mcil.gov.ws
-# </a>,
 # the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
 # September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
 # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
 # backwards from 1:00am to 12:00am"
 
 # From Laupue Raymond Hughes (2011-03-07):
-# I believe this will be posted shortly on the website
-# <a href="http://www.mcil.gov.ws">
-# www.mcil.gov.ws
-# </a>
-#
-# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
+# [http://www.mcil.gov.ws/ftcd/daylight_saving_2011.pdf]
 #
-# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
-# businesses and the general public are hereby advised that daylight
-# saving time is on the first Saturday of April 2011 (02/04/11).
-#
-# The public is therefore advised that when the standard time strikes
-# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
-# then all instruments used to measure standard time are to be
-# adjusted/changed to three oclock (3:00am or 0300Hrs).
-#
-# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
-# INDUSTRY AND LABOUR 28th February 2011
+# ... when the standard time strikes the hour of four o'clock (4.00am
+# or 0400 Hours) on the 2nd April 2011, then all instruments used to
+# measure standard time are to be adjusted/changed to three o'clock
+# (3:00am or 0300Hrs).
 
-# From David Zuelke (2011-05-09):
+# From David Zülke (2011-05-09):
 # Subject: Samoa to move timezone from east to west of international date line
 #
-# <a href="http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963">
 # http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
-# </a>
 
-# From Mark Sim-Smith (2011-08-17):
-# I have been in contact with Leilani Tuala Warren from the Samoa Law
-# Reform Commission, and she has sent me a copy of the Bill that she
-# confirmed has been passed...Most of the sections are about maps rather
-# than the time zone change, but I'll paste the relevant bits below. But
-# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
-# changes from UTC-11 to UTC+13:
-#
-# International Date Line Bill 2011
-#
-# AN ACT to provide for the change to standard time in Samoa and to make
-# consequential amendments to the position of the International Date
-# Line, and for related purposes.
-#
-# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
-# assembled as follows:
-#
-# 1. Short title and commencement-(1) This Act may be cited as the
-# International Date Line Act 2011. (2) Except for section 5(3) this Act
-# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
-# Section 5(3) commences on the date of assent by the Head of State.
-#
-# [snip]
-#
-# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
-# other statute of Samoa which refers to 'Samoa standard time' means the
-# time 13 hours in advance of Co-ordinated Universal Time.
-#
-# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
-# standard time shall be set at 13 hours in advance of Co-ordinated
-# Universal Time for the whole of Samoa. (2) All references to Samoa's
-# time zone and to Samoa standard time in Samoa in all legislation and
-# instruments after the commencement of this Act shall be references to
-# Samoa standard time as provided for in this Act. (3) Nothing in this
-# Act affects the provisions of the Daylight Saving Act 2009, except that
-# it defines Samoa standard time....
+# From Paul Eggert (2014-06-27):
+# The International Date Line Act 2011
+# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
+# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# Thursday 29th December 2011".  The International Date Line was adjusted
+# accordingly.
 
 # From Laupue Raymond Hughes (2011-09-02):
-# <a href="http://www.mcil.gov.ws/mcil_publications.html">
 # http://www.mcil.gov.ws/mcil_publications.html
-# </a>
 #
 # here is the official website publication for Samoa DST and dateline change
 #
 # DST
-# Year	End	Time	Start	Time
-# 2011	- - -	- - -	24 September	3:00am to 4:00am
-# 2012	01 April	4:00am to 3:00am	- - -	- - -
+# Year  End      Time              Start        Time
+# 2011  - - -    - - -             24 September 3:00am to 4:00am
+# 2012  01 April 4:00am to 3:00am  - - -        - - -
 #
 # Dateline Change skip Friday 30th Dec 2011
 # Thursday 29th December 2011	23:59:59 Hours
 # Saturday 31st December 2011	00:00:00 Hours
 #
-# Clarification by Tim Parenti (2012-01-03):
-# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
-# seasons, there is not yet any indication that this trend will continue on
-# a regular basis. For now, we have explicitly listed the transitions below.
-#
-# From Nicky (2012-09-10):
+# From Nicholas Pereira (2012-09-10):
 # Daylight Saving Time commences on Sunday 30th September 2012 and
-# ends on Sunday 7th of April 2013.
-#
-# Please find link below for more information.
+# ends on Sunday 7th of April 2013....
 # http://www.mcil.gov.ws/mcil_publications.html
 #
-# That publication also includes dates for Summer of 2013/4 as well
-# which give the impression of a pattern in selecting dates for the
-# future, so for now, we will guess this will continue.
+# From Paul Eggert (2014-07-08):
+# That web page currently lists transitions for 2012/3 and 2013/4.
+# Assume the pattern instituted in 2012 will continue indefinitely.
 
-# Western Samoa
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	WS	2010	only	-	Sep	lastSun	0:00	1	D
+Rule	WS	2011	only	-	Apr	Sat>=1	4:00	0	S
+Rule	WS	2011	only	-	Sep	lastSat	3:00	1	D
+Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	S
 Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
-Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 2 4:00
-			-11:00	-	WST	2011 Sep 24 3:00
-			-11:00	1:00	WSDT	2011 Dec 30
-			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
+			-11:30	-	WSST	1950
+			-11:00	WS	S%sT	2011 Dec 29 24:00 # S=Samoa
 			 13:00	WS	WS%sT
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
+Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
 			11:00	-	SBT	# Solomon Is Time
 
 # Tokelau Is
@@ -744,7 +664,7 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
-			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
+			-11:00	-	TKT	2011 Dec 30 # Tokelau Time
 			13:00	-	TKT
 
 # Tonga
@@ -804,8 +724,8 @@
 # time from Operation Newsreel (Hardtack I/Teak shot, 1958-08-01) to the last
 # Operation Fishbowl shot (Tightrope, 1962-11-04).... [See] Herman Hoerlin,
 # "The United States High-Altitude Test Experience: A Review Emphasizing the
-# Impact on the Environment", Los Alamos LA-6405, Oct 1976
-# <http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf>.
+# Impact on the Environment", Los Alamos LA-6405, Oct 1976.
+# http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf
 # See the table on page 4 where he lists GMT and local times for the tests; a
 # footnote for the JI tests reads that local time is "JI time = Hawaii Time
 # Minus One Hour".
@@ -820,7 +740,7 @@
 # From Mark Brader (2005-01-23):
 # [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
 # published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
-# reproduced a Pan American Airways timeables from 1936, for their weekly
+# reproduced a Pan American Airways timetable from 1936, for their weekly
 # "Orient Express" flights between San Francisco and Manila, and connecting
 # flights to Chicago and the US East Coast.  As it uses some time zone
 # designations that I've never seen before:....
@@ -830,9 +750,9 @@
 Zone Pacific/Midway	-11:49:28 -	LMT	1901
 			-11:00	-	NST	1956 Jun  3
 			-11:00	1:00	NDT	1956 Sep  2
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
 # Palmyra
 # uninhabited since World War II; was probably like Pacific/Kiritimati
@@ -852,7 +772,7 @@
 Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
 Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
+Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
 			11:00	Vanuatu	VU%sT	# Vanuatu Time
 
 # Wallis and Futuna
@@ -864,9 +784,10 @@
 
 # NOTES
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 # A good source for time zone historical data outside the U.S. is
@@ -887,165 +808,188 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
-#		std dst
-#		LMT	Local Mean Time
-#	  8:00	WST WST	Western Australia
-#	  8:45	CWST CWST Central Western Australia*
-#	  9:00	JST	Japan
-#	  9:30	CST CST	Central Australia
-#	 10:00	EST EST	Eastern Australia
-#	 10:00	ChST	Chamorro
-#	 10:30	LHST LHST Lord Howe*
-#	 11:30	NZMT NZST New Zealand through 1945
-#	 12:00	NZST NZDT New Zealand 1946-present
-#	 12:45	CHAST CHADT Chatham*
-#	-11:00	SST	Samoa
-#	-10:00	HST	Hawaii
-#	- 8:00	PST	Pitcairn*
+#		std	dst
+#		LMT		Local Mean Time
+#	  8:00	AWST	AWDT	Western Australia
+#	  8:45	ACWST	ACWDT	Central Western Australia*
+#	  9:00	JST		Japan
+#	  9:30	ACST	ACDT	Central Australia
+#	 10:00	AEST	AEDT	Eastern Australia
+#	 10:00	ChST		Chamorro
+#	 10:30	LHST	LHDT	Lord Howe*
+#	 11:30	NZMT	NZST	New Zealand through 1945
+#	 12:00	NZST	NZDT	New Zealand 1946-present
+#	 12:15	CHAST		Chatham through 1945*
+#	 12:45	CHAST	CHADT	Chatham 1946-present*
+#	 13:00	WSST	WSDT	(western) Samoa 2011-present*
+#	-11:30	WSST		Western Samoa through 1950*
+#	-11:00	SST		Samoa
+#	-10:00	HST		Hawaii
+#	- 8:00	PST		Pitcairn*
 #
-# See the `northamerica' file for Hawaii.
-# See the `southamerica' file for Easter I and the Galapagos Is.
+# See the 'northamerica' file for Hawaii.
+# See the 'southamerica' file for Easter I and the Galápagos Is.
 
 ###############################################################################
 
 # Australia
 
+# From Paul Eggert (2014-06-30):
+# Daylight saving time has long been controversial in Australia, pitting
+# region against region, rural against urban, and local against global.
+# For example, in her review of Graeme Davison's _The Unforgiving
+# Minute: how Australians learned to tell the time_ (1993), Perth native
+# Phillipa J Martyr wrote, "The section entitled 'Saving Daylight' was
+# very informative, but was (as can, sadly, only be expected from a
+# Melbourne-based study) replete with the usual chuckleheaded
+# Queenslanders and straw-chewing yokels from the West prattling fables
+# about fading curtains and crazed farm animals."
+# Electronic Journal of Australian and New Zealand History (1997-03-03)
+# http://www.jcu.edu.au/aff/history/reviews/davison.htm
+
 # From Paul Eggert (2005-12-08):
-# <a href="http://www.bom.gov.au/climate/averages/tables/dst_times.shtml">
 # Implementation Dates of Daylight Saving Time within Australia
-# </a> summarizes daylight saving issues in Australia.
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
+# summarizes daylight saving issues in Australia.
 
 # From Arthur David Olson (2005-12-12):
-# <a href="http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving">
 # Lawlink NSW:Daylight Saving in New South Wales
-# </a> covers New South Wales in particular.
+# http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving
+# covers New South Wales in particular.
 
 # From John Mackin (1991-03-06):
-# We in Australia have _never_ referred to DST as `daylight' time.
-# It is called `summer' time.  Now by a happy coincidence, `summer'
-# and `standard' happen to start with the same letter; hence, the
+# We in Australia have _never_ referred to DST as 'daylight' time.
+# It is called 'summer' time.  Now by a happy coincidence, 'summer'
+# and 'standard' happen to start with the same letter; hence, the
 # abbreviation does _not_ change...
 # The legislation does not actually define abbreviations, at least
 # in this State, but the abbreviation is just commonly taken to be the
 # initials of the phrase, and the legislation here uniformly uses
-# the phrase `summer time' and does not use the phrase `daylight
+# the phrase 'summer time' and does not use the phrase 'daylight
 # time'.
 # Announcers on the Commonwealth radio network, the ABC (for Australian
-# Broadcasting Commission), use the phrases `Eastern Standard Time'
-# or `Eastern Summer Time'.  (Note, though, that as I say in the
+# Broadcasting Commission), use the phrases 'Eastern Standard Time'
+# or 'Eastern Summer Time'.  (Note, though, that as I say in the
 # current australasia file, there is really no such thing.)  Announcers
 # on its overseas service, Radio Australia, use the same phrases
-# prefixed by the word `Australian' when referring to local times;
+# prefixed by the word 'Australian' when referring to local times;
 # time announcements on that service, naturally enough, are made in UTC.
 
-# From Arthur David Olson (1992-03-08):
-# Given the above, what's chosen for year-round use is:
-#	CST	for any place operating at a GMTOFF of 9:30
-#	WST	for any place operating at a GMTOFF of 8:00
-#	EST	for any place operating at a GMTOFF of 10:00
-
-# From Chuck Soper (2006-06-01):
-# I recently found this Australian government web page on time zones:
-# <http://www.australia.gov.au/about-australia-13time>
-# And this government web page lists time zone names and abbreviations:
-# <http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml>
-
-# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
-# versus "AEST" etc.:
+# From Paul Eggert (2014-06-30):
 #
-# I see the following points of dispute:
-#
-# * How important are unique time zone abbreviations?
+# Inspired by Mackin's remarks quoted above, earlier versions of this
+# file used "EST" for both Eastern Standard Time and Eastern Summer
+# Time in Australia, and similarly for "CST", "CWST", and "WST".
+# However, these abbreviations were confusing and were not common
+# practice among Australians, and there were justifiable complaints
+# about them, so I attempted to survey current Australian usage.
+# For the tz database, the full English phrase is not that important;
+# what matters is the abbreviation.  It's difficult to survey the web
+# directly for abbreviation usage, as there are so many false hits for
+# strings like "EST" and "EDT", so I looked for pages that defined an
+# abbreviation for eastern or central DST in Australia, and got the
+# following numbers of unique hits for the listed Google queries:
 #
-#   Here I tend to agree with the point (most recently made by Chris
-#   Newman) that unique abbreviations should not be essential for proper
-#   operation of software.  We have other instances of ambiguity
-#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
-#   Standard Time"), and they are not likely to go away any time soon.
-#   In the old days, some software mistakenly relied on unique
-#   abbreviations, but this is becoming less true with time, and I don't
-#   think it's that important to cater to such software these days.
+#   10 "Eastern Daylight Time AEST" site:au [some are false hits]
+#   10 "Eastern Summer Time AEST" site:au
+#   10 "Summer Time AEDT" site:au
+#   13 "EDST Eastern Daylight Saving Time" site:au
+#   18 "Summer Time ESST" site:au
+#   28 "Eastern Daylight Saving Time EDST" site:au
+#   39 "EDT Eastern Daylight Time" site:au [some are false hits]
+#   53 "Eastern Daylight Time EDT" site:au [some are false hits]
+#   54 "AEDT Australian Eastern Daylight Time" site:au
+#  182 "Eastern Daylight Time AEDT" site:au
+#
+#   17 "Central Daylight Time CDT" site:au [some are false hits]
+#   46 "Central Daylight Time ACDT" site:au
 #
-#   On the other hand, there is another motivation for unambiguous
-#   abbreviations: it cuts down on human confusion.  This is
-#   particularly true for Australia, where "EST" can mean one thing for
-#   time T and a different thing for time T plus 1 second.
+# I tried several other variants (e.g., "Eastern Summer Time EST") but
+# they all returned fewer than 10 unique hits.  I also looked for pages
+# mentioning both "western standard time" and an abbreviation, since
+# there is no WST in the US to generate false hits, and found:
 #
-# * Does the relevant legislation indicate which abbreviations should be used?
+#  156 "western standard time" AWST site:au
+#  226 "western standard time" WST site:au
 #
-#   Here I tend to think that things are a mess, just as they are in
-#   many other countries.  We Americans are currently disagreeing about
-#   which abbreviation to use for the newly legislated Chamorro Standard
-#   Time, for example.
-#
-#   Personally, I would prefer to use common practice; I would like to
-#   refer to legislation only for examples of common practice, or as a
-#   tiebreaker.
+# I then surveyed the top ten newspapers in Australia by circulation as
+# listed in Wikipedia, using Google queries like "AEDT site:heraldsun.com.au"
+# and obtaining estimated counts from the initial page of search results.
+# All ten papers greatly preferred "AEDT" to "EDT".  The papers
+# surveyed were the Herald Sun, The Daily Telegraph, The Courier-Mail,
+# The Sydney Morning Herald, The West Australian, The Age, The Advertiser,
+# The Australian, The Financial Review, and The Herald (Newcastle).
 #
-# * Do Australians more often use "Eastern Daylight Time" or "Eastern
-#   Summer Time"?  Do they typically prefix the time zone names with
-#   the word "Australian"?
-#
-#   My own impression is that both "Daylight Time" and "Summer Time" are
-#   common and are widely understood, but that "Summer Time" is more
-#   popular; and that the leading "A" is also common but is omitted more
-#   often than not.  I just used AltaVista advanced search and got the
-#   following count of page hits:
+# I also searched for historical usage, to see whether abbreviations
+# like "AEDT" are new.  A Trove search <http://trove.nla.gov.au/>
+# found only one newspaper (The Canberra Times) with a house style
+# dating back to the 1970s, I expect because other newspapers weren't
+# fully indexed.  The Canberra Times strongly preferred abbreviations
+# like "AEDT".  The first occurrence of "AEDT" was a World Weather
+# column (1971-11-17, page 24), and of "ACDT" was a Scoreboard column
+# (1993-01-24, p 16).  The style was the typical usage but was not
+# strictly enforced; for example, "Welcome to the twilight zones ..."
+# (1994-10-29, p 1) uses the abbreviations AEST/AEDT, CST/CDT, and
+# WST, and goes on to say, "The confusion and frustration some feel
+# about the lack of uniformity among Australia's six states and two
+# territories has prompted one group to form its very own political
+# party -- the Sydney-based Daylight Saving Extension Party."
 #
-#     1,103 "Eastern Summer Time" AND domain:au
-#       971 "Australian Eastern Summer Time" AND domain:au
-#       613 "Eastern Daylight Time" AND domain:au
-#       127 "Australian Eastern Daylight Time" AND domain:au
+# I also surveyed federal government sources.  They did not agree:
 #
-#   Here "Summer" seems quite a bit more popular than "Daylight",
-#   particularly when we know the time zone is Australian and not US,
-#   say.  The "Australian" prefix seems to be popular for Eastern Summer
-#   Time, but unpopular for Eastern Daylight Time.
+#   The Australian Government (2014-03-26)
+#   http://australia.gov.au/about-australia/our-country/time
+#   (This document was produced by the Department of Finance.)
+#   AEST ACST AWST AEDT ACDT
+#
+#   Bureau of Meteorology (2012-11-08)
+#   http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml
+#   EST CST WST EDT CDT
 #
-#   For abbreviations, tools like AltaVista are less useful because of
-#   ambiguity.  Many hits are not really time zones, unfortunately, and
-#   many hits denote US time zones and not Australian ones.  But here
-#   are the hit counts anyway:
+#   Civil Aviation Safety Authority (undated)
+#   http://services.casa.gov.au/outnback/inc/pages/episode3/episode-3_time_zones.shtml
+#   EST CST WST (no abbreviations given for DST)
 #
-#     161,304 "EST" and domain:au
-#      25,156 "EDT" and domain:au
-#      18,263 "AEST" and domain:au
-#      10,416 "AEDT" and domain:au
+#   Geoscience Australia (2011-11-24)
+#   http://www.ga.gov.au/geodesy/astro/sunrise.jsp
+#   AEST ACST AWST AEDT ACDT
+#
+#   Parliamentary Library (2008-11-10)
+#   http://www.aph.gov.au/binaries/library/pubs/rp/2008-09/09rp14.pdf
+#   EST CST WST preferred for standard time; AEST AEDT ACST ACDT also used
 #
-#      14,538 "CST" and domain:au
-#       5,728 "CDT" and domain:au
-#         176 "ACST" and domain:au
-#          29 "ACDT" and domain:au
-#
-#       7,539 "WST" and domain:au
-#          68 "AWST" and domain:au
+#   The Transport Safety Bureau has an extensive series of accident reports,
+#   and investigators seem to use whatever abbreviation they like.
+#   Googling site:atsb.gov.au found the following number of unique hits:
+#   311 "ESuT", 195 "EDT", 26 "AEDT", 83 "CSuT", 46 "CDT".
+#   "_SuT" tended to appear in older reports, and "A_DT" tended to
+#   appear in reports of events with international implications.
 #
-#   This data suggest that Australians tend to omit the "A" prefix in
-#   practice.  The situation for "ST" versus "DT" is less clear, given
-#   the ambiguities involved.
-#
-# * How do Australians feel about the abbreviations in the tz database?
-#
-#   If you just count Australians on this list, I count 2 in favor and 3
-#   against.  One of the "against" votes (David Keegel) counseled delay,
-#   saying that both AEST/AEDT and EST/EST are widely used and
-#   understood in Australia.
+# From the above it appears that there is a working consensus in
+# Australia to use trailing "DT" for daylight saving time; although
+# some sources use trailing "SST" or "ST" or "SuT" they are by far in
+# the minority.  The case for leading "A" is weaker, but since it
+# seems to be preferred in the overall web and is preferred in all
+# the leading newspaper websites and in many government departments,
+# it has a stronger case than omitting the leading "A".  The current
+# version of the database therefore uses abbreviations like "AEST" and
+# "AEDT" for Australian time zones.
 
 # From Paul Eggert (1995-12-19):
 # Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
 # Mark Prior writes that his newspaper
 # reports that NSW's fall 1995 change will occur at 2:00,
 # but Robert Elz says it's been 3:00 in Victoria since 1970
-# and perhaps the newspaper's `2:00' is referring to standard time.
+# and perhaps the newspaper's '2:00' is referring to standard time.
 # For now we'll continue to assume 2:00s for changes since 1960.
 
 # From Eric Ulevik (1998-01-05):
@@ -1055,17 +999,14 @@
 # relevant entries in this database.
 #
 # NSW (including LHI and Broken Hill):
-# <a href="http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html">
 # Standard Time Act 1987 (updated 1995-04-04)
-# </a>
+# http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html
 # ACT
-# <a href="http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html">
 # Standard Time and Summer Time Act 1972
-# </a>
+# http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html
 # SA
-# <a href="http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html">
 # Standard Time Act, 1898
-# </a>
+# http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html
 
 # From David Grosz (2005-06-13):
 # It was announced last week that Daylight Saving would be extended by
@@ -1083,7 +1024,7 @@
 # Victoria: I wasn't able to find anything separate, but the other articles
 # allude to it.
 # But not Queensland
-# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
+# http://www.news.com.au/story/0,10117,15564030-1248,00.html
 
 # Northern Territory
 
@@ -1130,9 +1071,9 @@
 # The 1992 ending date used in the rules is a best guess;
 # it matches what was used in the past.
 
-# <a href="http://www.bom.gov.au/faq/faqgen.htm">
 # The Australian Bureau of Meteorology FAQ
-# </a> (1999-09-27) writes that Giles Meteorological Station uses
+# http://www.bom.gov.au/faq/faqgen.htm
+# (1999-09-27) writes that Giles Meteorological Station uses
 # South Australian time even though it's located in Western Australia.
 
 # Queensland
@@ -1173,9 +1114,9 @@
 # The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
 
 # From Christopher Hunt (2006-11-21), after an advance warning
-# from Jesper Norgaard Welen (2006-11-01):
+# from Jesper Nørgaard Welen (2006-11-01):
 # WA are trialing DST for three years.
-# <http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf>
+# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf
 
 # From Rives McDow (2002-04-09):
 # The most interesting region I have found consists of three towns on the
@@ -1189,7 +1130,7 @@
 # From Paul Eggert (2002-04-09):
 # This is confirmed by the section entitled
 # "What's the deal with time zones???" in
-# <http://www.earthsci.unimelb.edu.au/~awatkins/null.html>.
+# http://www.earthsci.unimelb.edu.au/~awatkins/null.html
 #
 # From Alex Livingston (2006-12-07):
 # ... it was just on four years ago that I drove along the Eyre Highway,
@@ -1337,7 +1278,7 @@
 # Based on law library research by John Mackin,
 # who notes:
 #	In Australia, time is not legislated federally, but rather by the
-#	individual states.  Thus, while such terms as ``Eastern Standard Time''
+#	individual states.  Thus, while such terms as "Eastern Standard Time"
 #	[I mean, of course, Australian EST, not any other kind] are in common
 #	use, _they have NO REAL MEANING_, as they are not defined in the
 #	legislation.  This is very important to understand.
@@ -1345,48 +1286,42 @@
 
 # From Eric Ulevik (1999-05-26):
 # DST will start in NSW on the last Sunday of August, rather than the usual
-# October in 2000.  [See: Matthew Moore,
-# <a href="http://www.smh.com.au/news/9905/26/pageone/pageone4.html">
-# Two months more daylight saving
-# </a>
-# Sydney Morning Herald (1999-05-26).]
+# October in 2000.  See: Matthew Moore,
+# Two months more daylight saving, Sydney Morning Herald (1999-05-26).
+# http://www.smh.com.au/news/9905/26/pageone/pageone4.html
 
 # From Paul Eggert (1999-09-27):
 # See the following official NSW source:
-# <a href="http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ">
 # Daylight Saving in New South Wales.
-# </a>
+# http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ
 #
 # Narrabri Shire (NSW) council has announced it will ignore the extension of
 # daylight saving next year.  See:
-# <a href="http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm">
 # Narrabri Council to ignore daylight saving
-# </a> (1999-07-22).  For now, we'll wait to see if this really happens.
+# http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm
+# (1999-07-22).  For now, we'll wait to see if this really happens.
 #
 # Victoria will following NSW.  See:
-# <a href="http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm">
-# Vic to extend daylight saving
-# </a> (1999-07-28).
+# Vic to extend daylight saving (1999-07-28)
+# http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm
 #
 # However, South Australia rejected the DST request.  See:
-# <a href="http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm">
-# South Australia rejects Olympics daylight savings request
-# </a> (1999-07-19).
+# South Australia rejects Olympics daylight savings request (1999-07-19)
+# http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm
 #
 # Queensland also will not observe DST for the Olympics.  See:
-# <a href="http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm">
 # Qld says no to daylight savings for Olympics
-# </a> (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
-# ``Look you've got to remember in my family when this came up last time
+# http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm
+# (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# "Look you've got to remember in my family when this came up last time
 # I voted for it, my wife voted against it and she said to me it's all very
 # well for you, you don't have to worry about getting the children out of
 # bed, getting them to school, getting them to sleep at night.
-# I've been through all this argument domestically...my wife rules.''
+# I've been through all this argument domestically...my wife rules."
 #
 # Broken Hill will stick with South Australian time in 2000.  See:
-# <a href="http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm">
-# Broken Hill to be behind the times
-# </a> (1999-07-21).
+# Broken Hill to be behind the times (1999-07-21)
+# http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm
 
 # IATA SSIM (1998-09) says that the spring 2000 change for Australian
 # Capital Territory, New South Wales except Lord Howe Island and Broken
@@ -1402,7 +1337,7 @@
 # Yancowinna
 
 # From John Mackin (1989-01-04):
-# `Broken Hill' means the County of Yancowinna.
+# 'Broken Hill' means the County of Yancowinna.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
@@ -1459,9 +1394,7 @@
 # summer (southern hemisphere).
 #
 # From
-# <a href="http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf">
 # http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
-# </a>
 # The extended daylight saving period that South Australia has been trialling
 # for over the last year is now set to be ongoing.
 # Daylight saving will continue to start on the first Sunday in October each
@@ -1471,9 +1404,7 @@
 # the ACT for all 52 weeks of the year...
 #
 # We have a wrap-up here:
-# <a href="http://www.timeanddate.com/news/time/south-australia-extends-dst.html">
 # http://www.timeanddate.com/news/time/south-australia-extends-dst.html
-# </a>
 ###############################################################################
 
 # New Zealand
@@ -1482,7 +1413,7 @@
 # the 1989/90 year was a trial of an extended "daylight saving" period.
 # This trial was deemed successful and the extended period adopted for
 # subsequent years (with the addition of a further week at the start).
-# source -- phone call to Ministry of Internal Affairs Head Office.
+# source - phone call to Ministry of Internal Affairs Head Office.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # The Country of New Zealand   (Australia's east island -) Gee they hate that!
@@ -1524,6 +1455,19 @@
 # that DST will begin on 2007-09-30 2008-04-06.
 # http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
 
+# From Paul Eggert (2014-07-14):
+# Chatham Island time was formally standardized on 1957-01-01 by
+# New Zealand's Standard Time Amendment Act 1956 (1956-10-26).
+# http://www.austlii.edu.au/nz/legis/hist_act/staa19561956n100244.pdf
+# According to Google Books snippet view, a speaker in the New Zealand
+# parliamentary debates in 1956 said "Clause 78 makes provision for standard
+# time in the Chatham Islands.  The time there is 45 minutes in advance of New
+# Zealand time.  I understand that is the time they keep locally, anyhow."
+# For now, assume this practice goes back to the introduction of standard time
+# in New Zealand, as this would make Chatham Islands time almost exactly match
+# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# not observe New Zealand's prewar DST.
+
 ###############################################################################
 
 
@@ -1543,7 +1487,7 @@
 
 # From the BBC World Service in
 # http://news.bbc.co.uk/2/hi/asia-pacific/205226.stm (1998-10-31 16:03 UTC):
-# The Fijiian government says the main reasons for the time change is to
+# The Fijian government says the main reasons for the time change is to
 # improve productivity and reduce road accidents.... [T]he move is also
 # intended to boost Fiji's ability to attract tourists to witness the dawning
 # of the new millennium.
@@ -1551,16 +1495,12 @@
 # http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
 # reports that Fiji has discontinued DST.
 
-# Johnston
-
-# Johnston data is from usno1995.
-
 
 # Kiribati
 
 # From Paul Eggert (1996-01-22):
 # Today's _Wall Street Journal_ (page 1) reports that Kiribati
-# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
+# "declared it the same day [throughout] the country as of Jan. 1, 1995"
 # as part of the competition to be first into the 21st century.
 
 
@@ -1575,8 +1515,8 @@
 
 # N Mariana Is, Guam
 
-# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
-# Philippines and the Ladrones from America,'' and implies that the Ladrones
+# Howse writes (p 153) "The Spaniards, on the other hand, reached the
+# Philippines and the Ladrones from America," and implies that the Ladrones
 # (now called the Marianas) kept American date for quite some time.
 # For now, we assume the Ladrones switched at the same time as the Philippines;
 # see Asia/Manila.
@@ -1590,17 +1530,16 @@
 # Micronesia
 
 # Alan Eugene Davis writes (1996-03-16),
-# ``I am certain, having lived there for the past decade, that "Truk"
-# (now properly known as Chuuk) ... is in the time zone GMT+10.''
+# "I am certain, having lived there for the past decade, that 'Truk'
+# (now properly known as Chuuk) ... is in the time zone GMT+10."
 #
 # Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
 # on 1978-10-01; ignore this for now.
 
 # From Paul Eggert (1999-10-29):
 # The Federated States of Micronesia Visitors Board writes in
-# <a href="http://www.fsmgov.org/info/clocks.html">
-# The Federated States of Micronesia - Visitor Information
-# </a> (1999-01-26)
+# The Federated States of Micronesia - Visitor Information (1999-01-26)
+# http://www.fsmgov.org/info/clocks.html
 # that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
 # We don't know when Kosrae switched from UTC+12; assume January 1 for now.
 
@@ -1646,27 +1585,34 @@
 # Sacramento but it was changed a couple of years ago.
 
 
-# Samoa
+# (Western) Samoa and American Samoa
 
 # Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
 # that in 1879 the King of Samoa decided to change
-# ``the date in his kingdom from the Antipodean to the American system,
-# ordaining -- by a masterpiece of diplomatic flattery -- that
-# the Fourth of July should be celebrated twice in that year.''
+# "the date in his kingdom from the Antipodean to the American system,
+# ordaining - by a masterpiece of diplomatic flattery - that
+# the Fourth of July should be celebrated twice in that year."
 
+# Although Shanks & Pottenger says they both switched to UTC-11:30
+# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# for American Samoa, e.g., the US National Bureau of Standards
+# circular "Standard Time Throughout the World", 1932.
+# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# and that after 1950 they agreed until (western) Samoa skipped a
+# day in 2011.  Assume also that the Samoas follow the US and New
+# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
 
 # Tonga
 
 # From Paul Eggert (1996-01-22):
-# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
-# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
+# Today's _Wall Street Journal_ (p 1) reports that "Tonga has been plotting
+# to sneak ahead of [New Zealanders] by introducing daylight-saving time."
 # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
 
 # Don Mundell writes in the 1997-02-20 Tonga Chronicle
-# <a href="http://www.tongatapu.net.to/tonga/homeland/timebegins.htm">
-# How Tonga became `The Land where Time Begins'
-# </a>:
-
+# How Tonga became 'The Land where Time Begins':
+# http://www.tongatapu.net.to/tonga/homeland/timebegins.htm
+#
 # Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
 # 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
 # standard time in 1940s, Tonga had the choice of subtracting from its
@@ -1674,8 +1620,8 @@
 # advancing its time to maintain the differential of 13 degrees
 # (approximately 50 minutes ahead of New Zealand time).
 #
-# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
-# Tungi, preferred to ensure Tonga's title as the land where time
+# Because His Majesty King Tāufaʻāhau Tupou IV, then Crown Prince
+# Tungī, preferred to ensure Tonga's title as the land where time
 # begins, the Legislative Assembly approved the latter change.
 #
 # But some of the older, more conservative members from the outer
@@ -1701,9 +1647,7 @@
 # * Tonga will introduce DST in November
 #
 # I was given this link by John Letts:
-# <a href="http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm">
 # http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
-# </a>
 #
 # I have not been able to find exact dates for the transition in November
 # yet. By reading this article it seems like Fiji will be 14 hours ahead
@@ -1711,9 +1655,7 @@
 # (12 + 1 hour DST).
 
 # From Arthur David Olson (1999-09-20):
-# According to <a href="http://www.tongaonline.com/news/sept1799.html">
-# http://www.tongaonline.com/news/sept1799.html
-# </a>:
+# According to <http://www.tongaonline.com/news/sept1799.html>:
 # "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
 # and annually thereafter from the first Saturday in October through the
 # third Saturday of April.  Under the system approved by Privy Council on
@@ -1731,7 +1673,7 @@
 # instead of the original reported date April 16. Unfortunately, the article
 # is no longer available on the site, and I did not make a copy of the
 # text, and I have forgotten to report it here.
-# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+# (Original URL was <http://www.tongaonline.com/news/march162000.htm>)
 
 # From Rives McDow (2000-12-01):
 # Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
@@ -1751,7 +1693,7 @@
 # From Vernice Anderson, Personal Secretary to Philip Jessup,
 # US Ambassador At Large (oral history interview, 1971-02-02):
 #
-# Saturday, the 14th [of October, 1950] -- ...  The time was all the
+# Saturday, the 14th [of October, 1950] - ...  The time was all the
 # more confusing at that point, because we had crossed the
 # International Date Line, thus getting two Sundays.  Furthermore, we
 # discovered that Wake Island had two hours of daylight saving time
@@ -1796,7 +1738,7 @@
 # on the high seas.  Whenever a ship was within the territorial waters of any
 # nation it would use that nation's standard time.  The captain was permitted
 # to change his ship's clocks at a time of his choice following his ship's
-# entry into another zone time--he often chose midnight.  These zones were
+# entry into another zone time - he often chose midnight.  These zones were
 # adopted by all major fleets between 1920 and 1925 but not by many
 # independent merchant ships until World War II.
 
@@ -1804,6 +1746,6 @@
 # (2005-03-20):
 #
 # The American Practical Navigator (2002)
-# <http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187>
+# http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187
 # talks only about the 180-degree meridian with respect to ships in
 # international waters; it ignores the international date line.
--- a/jdk/test/sun/util/calendar/zi/tzdata/backward	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/backward	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
 
+# Link	TARGET			LINK-NAME
 Link	Africa/Asmara		Africa/Asmera
-Link	Africa/Bamako		Africa/Timbuktu
+Link	Africa/Abidjan		Africa/Timbuktu
 Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
 Link	America/Adak		America/Atka
 Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
@@ -50,8 +50,11 @@
 Link	Pacific/Auckland	Antarctica/South_Pole
 Link	Asia/Ashgabat		Asia/Ashkhabad
 Link	Asia/Kolkata		Asia/Calcutta
-Link	Asia/Chongqing		Asia/Chungking
+Link	Asia/Shanghai		Asia/Chongqing
+Link	Asia/Shanghai		Asia/Chungking
 Link	Asia/Dhaka		Asia/Dacca
+Link	Asia/Shanghai		Asia/Harbin
+Link	Asia/Urumqi		Asia/Kashgar
 Link	Asia/Kathmandu		Asia/Katmandu
 Link	Asia/Macau		Asia/Macao
 Link	Asia/Ho_Chi_Minh	Asia/Saigon
--- a/jdk/test/sun/util/calendar/zi/tzdata/etcetera	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/etcetera	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -37,7 +36,7 @@
 Zone	Etc/UCT		0	-	UCT
 
 # The following link uses older naming conventions,
-# but it belongs here, not in the file `backward',
+# but it belongs here, not in the file 'backward',
 # as functions like gmtime load the "GMT" file to handle leap seconds properly.
 # We want this to work even on installations that omit the other older names.
 Link	Etc/GMT				GMT
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2014-05-31):
 # A good source for time zone historical data outside the U.S. is
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
 # San Diego: ACS Publications, Inc. (2003).
@@ -40,6 +40,9 @@
 # published semiannually.  Law sent in several helpful summaries
 # of the IATA's data after 1990.
 #
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
 # Except where otherwise noted, Shanks & Pottenger is the source for
 # entries through 1991, and IATA SSIM is the source for entries afterwards.
 #
@@ -49,9 +52,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	<a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
 #	William Willett, The Waste of Daylight, 19th edition
-#	</a> (1914-03)
+#	<http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	<http://www.jstor.org/stable/1774359>.  He writes:
@@ -59,10 +62,20 @@
 #	may be sent to Mr. John Milne, Royal Geographical Society,
 #	Savile Row, London."  Nowadays please email them to tz@iana.org.
 #
-#	Brazil's Departamento Servico da Hora (DSH),
-#	<a href="http://pcdsh01.on.br/HISTHV.htm">
+#	Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+#	This Russian-language source was consulted by Vladimir Karpinsky; see
+#	http://mm.icann.org/pipermail/tz/2014-August/021320.html
+#	The full Russian citation is:
+#	Бялокоз, Евгений Людвигович. Новый счет времени в течении суток
+#	введенный декретом Совета народных комиссаров для всей России с 1-го
+#	июля 1919 г. / Изд. 2-е Междуведомственной комиссии. - Петроград:
+#	Десятая гос. тип., 1919.
+#	http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf
+#
+#	Brazil's Divisão Serviço da Hora (DSHO),
 #	History of Summer Time
-#	</a> (1998-09-21, in Portuguese)
+#	<http://pcdsh01.on.br/HISTHV.htm>
+#	(1998-09-21, in Portuguese)
 
 #
 # I invented the abbreviations marked '*' in the following table;
@@ -81,10 +94,8 @@
 #        1:00       CET CEST CEMT Central Europe
 #        1:00:14    SET           Swedish (1879-1899)*
 #        2:00       EET EEST      Eastern Europe
-#        3:00       MSK MSD       Moscow
-#
-# A reliable and entertaining source about time zones, especially in Britain,
-# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#        3:00       FET           Further-eastern Europe*
+#        3:00       MSK MSD  MSM* Moscow
 
 # From Peter Ilieve (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -128,7 +139,7 @@
 # along the towpath within a few yards of it.'
 #
 # I have a one inch to one mile map of London and my estimate of the stone's
-# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# position is 51 degrees 28' 30" N, 0 degrees 18' 45" W. The longitude should
 # be within about +-2". The Ordnance Survey grid reference is TQ172761.
 #
 # [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
@@ -160,8 +171,22 @@
 # transition date for London, namely 1847-12-01.  We don't know as much
 # about Dublin, so we use 1880-08-02, the legal transition time.
 
-# From Paul Eggert (2003-09-27):
-# Summer Time was first seriously proposed by William Willett (1857-1915),
+# From Paul Eggert (2014-07-19):
+# The ancients had no need for daylight saving, as they kept time
+# informally or via hours whose length depended on the time of year.
+# Daylight saving time in its modern sense was invented by the
+# New Zealand entomologist George Vernon Hudson (1867-1946),
+# whose day job as a postal clerk led him to value
+# after-hours daylight in which to pursue his research.
+# In 1895 he presented a paper to the Wellington Philosophical Society
+# that proposed a two-hour daylight-saving shift.  See:
+# Hudson GV. On seasonal time-adjustment in countries south of lat. 30 deg.
+# Transactions and Proceedings of the New Zealand Institute. 1895;28:734
+# http://rsnz.natlib.govt.nz/volume/rsnz_28/rsnz_28_00_006110.html
+# Although some interest was expressed in New Zealand, his proposal
+# did not find its way into law and eventually it was almost forgotten.
+#
+# In England, DST was independently reinvented by William Willett (1857-1915),
 # a London builder and member of the Royal Astronomical Society
 # who circulated a pamphlet "The Waste of Daylight" (1907)
 # that proposed advancing clocks 20 minutes on each of four Sundays in April,
@@ -174,7 +199,7 @@
 # A monument to Willett was unveiled on 1927-05-21, in an open space in
 # a 45-acre wood near Chislehurst, Kent that was purchased by popular
 # subscription and open to the public.  On the south face of the monolith,
-# designed by G. W. Miller, is the...William Willett Memorial Sundial,
+# designed by G. W. Miller, is the William Willett Memorial Sundial,
 # which is permanently set to Summer Time.
 
 # From Winston Churchill (1934-04-28):
@@ -183,9 +208,9 @@
 # between 160 and 170 hours more daylight leisure, to a war which
 # plunged Europe into darkness for four years, and shook the
 # foundations of civilization throughout the world.
-#	-- <a href="http://www.winstonchurchill.org/fh114willett.htm">
-#	"A Silent Toast to William Willett", Pictorial Weekly
-#	</a>
+#	-- "A Silent Toast to William Willett", Pictorial Weekly;
+#	republished in Finest Hour (Spring 2002) 1(114):26
+#	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
 
 # From Paul Eggert (1996-09-03):
 # The OED Supplement says that the English originally said "Daylight Saving"
@@ -194,7 +219,6 @@
 # proponents (who eventually won the argument) are quoted as using "Summer".
 
 # From Arthur David Olson (1989-01-19):
-#
 # A source at the British Information Office in New York avers that it's
 # known as "British" Summer Time in all parts of the United Kingdom.
 
@@ -221,8 +245,8 @@
 # official designation; the reply of the 21st was that there wasn't
 # but he couldn't think of anything better than the "Double British
 # Summer Time" that the BBC had been using informally.
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+# http://www.polyomino.org.uk/british-time/bbc-19410418.png
+# http://www.polyomino.org.uk/british-time/ho-19410421.png
 
 # From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
 # [N]o official designation has as far as I know been adopted for the time
@@ -239,23 +263,14 @@
 # the history of summer time legislation in the United Kingdom.
 # Since 1998 Joseph S. Myers has been updating
 # and extending this list, which can be found in
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/
-# <a href="http://www.polyomino.org.uk/british-time/">
-# History of legal time in Britain
-# </a>
-# Rob Crowther (2012-01-04) reports that that URL no longer
-# exists, and the article can now be found at:
-# <a href="http://www.polyomino.org.uk/british-time/">
 # http://www.polyomino.org.uk/british-time/
-# </a>
 
 # From Joseph S. Myers (1998-01-06):
 #
 # The legal time in the UK outside of summer time is definitely GMT, not UTC;
 # see Lord Tanlaw's speech
-# <a href="http://www.parliament.the-stationery-office.co.uk/pa/ld199697/ldhansrd/pdvn/lds97/text/70611-20.htm#70611-20_head0">
-# (Lords Hansard 11 June 1997 columns 964 to 976)
-# </a>.
+# http://www.publications.parliament.uk/pa/ld199798/ldhansrd/vo970611/text/70611-10.htm#70611-10_head0
+# (Lords Hansard 11 June 1997 columns 964 to 976).
 
 # From Paul Eggert (2006-03-22):
 #
@@ -295,8 +310,8 @@
 #   -- James Joyce, Ulysses
 
 # From Joseph S. Myers (2005-01-26):
-# Irish laws are available online at www.irishstatutebook.ie.  These include
-# various relating to legal time, for example:
+# Irish laws are available online at <http://www.irishstatutebook.ie>.
+# These include various relating to legal time, for example:
 #
 # ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
 #
@@ -458,25 +473,27 @@
 # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
+Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
 			 0:00	GB-Eire	%s	1968 Oct 27
-			 1:00	-	BST	1971 Oct 31 2:00u
+			 1:00	-	BST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	%s	1996
 			 0:00	EU	GMT/BST
 Link	Europe/London	Europe/Jersey
 Link	Europe/London	Europe/Guernsey
 Link	Europe/London	Europe/Isle_of_Man
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
-			-0:25:21 -	DMT	1916 May 21 2:00
-			-0:25:21 1:00	IST	1916 Oct  1 2:00s
+			-0:25:21 -	DMT	1916 May 21  2:00
+			-0:25:21 1:00	IST	1916 Oct  1  2:00s
 			 0:00	GB-Eire	%s	1921 Dec  6 # independence
-			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
-			 0:00	1:00	IST	1946 Oct  6 2:00
-			 0:00	-	GMT	1947 Mar 16 2:00
-			 0:00	1:00	IST	1947 Nov  2 2:00
-			 0:00	-	GMT	1948 Apr 18 2:00
+			 0:00	GB-Eire	GMT/IST	1940 Feb 25  2:00
+			 0:00	1:00	IST	1946 Oct  6  2:00
+			 0:00	-	GMT	1947 Mar 16  2:00
+			 0:00	1:00	IST	1947 Nov  2  2:00
+			 0:00	-	GMT	1948 Apr 18  2:00
 			 0:00	GB-Eire	GMT/IST	1968 Oct 27
-			 1:00	-	IST	1971 Oct 31 2:00u
+			 1:00	-	IST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	GMT/IST	1996
 			 0:00	EU	GMT/IST
 
@@ -495,10 +512,9 @@
 Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
 # The most recent directive covers the years starting in 2002.  See:
-# <a="http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT">
 # Directive 2000/84/EC of the European Parliament and of the Council
 # of 19 January 2001 on summer-time arrangements.
-# </a>
+# http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT
 
 # W-Eur differs from EU only in that W-Eur uses standard time.
 Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
@@ -521,18 +537,18 @@
 Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
 # Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
 Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
-# From Jesper Norgaard Welen (2008-07-13):
+# From Jesper Nørgaard Welen (2008-07-13):
 #
 # I found what is probably a typo of 2:00 which should perhaps be 2:00s
 # in the C-Eur rule from tz database version 2008d (this part was
-# corrected in version 2008d). The circumstancial evidence is simply the
+# corrected in version 2008d). The circumstantial evidence is simply the
 # tz database itself, as seen below:
 #
 # Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
 #    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
-#    0:00 France WE%sT 1945 Sep 16 3:00
+#    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Belgrade 1:22:00 - LMT 1884
 #    1:00 1:00 CEST 1945 Sep 16  2:00s
@@ -576,16 +592,16 @@
 Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
-Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
-Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
+Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST  # Moscow Summer Time
+Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT  # Moscow Mean Time
+Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST # Moscow Double Summer Time
 Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
 Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
-Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
-Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
-Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
-Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
-Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
+Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	MSD
+Rule	Russia	1919	only	-	Aug	16	 0:00	0	MSK
+Rule	Russia	1921	only	-	Feb	14	23:00	1:00	MSD
+Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
+Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
 Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
 # Act No.925 of the Council of Ministers of the USSR (1980-10-24):
 Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
@@ -607,14 +623,10 @@
 # According to the law Russia is abolishing daylight saving time.
 #
 # Medvedev signed a law "On the Calculation of Time" (in russian):
-# <a href="http://bmockbe.ru/events/?ID=7583">
 # http://bmockbe.ru/events/?ID=7583
-# </a>
 #
 # Medvedev signed a law on the calculation of the time (in russian):
-# <a href="http://www.regnum.ru/news/polit/1413906.html">
 # http://www.regnum.ru/news/polit/1413906.html
-# </a>
 
 # From Arthur David Olson (2011-06-15):
 # Take "abolishing daylight saving time" to mean that time is now considered
@@ -634,10 +646,10 @@
 # From Markus Kuhn (1996-07-12):
 # The official German names ... are
 #
-#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
-#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
+#	Mitteleuropäische Zeit (MEZ)         = UTC+01:00
+#	Mitteleuropäische Sommerzeit (MESZ)  = UTC+02:00
 #
-# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# as defined in the German Time Act (Gesetz über die Zeitbestimmung (ZeitG),
 # 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
 # I wrote ... to the German Federal Physical-Technical Institution
 #
@@ -692,7 +704,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Andorra	0:06:04 -	LMT	1901
 			0:00	-	WET	1946 Sep 30
-			1:00	-	CET	1985 Mar 31 2:00
+			1:00	-	CET	1985 Mar 31  2:00
 			1:00	EU	CE%sT
 
 # Austria
@@ -718,9 +730,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1920
-			1:00	Austria	CE%sT	1940 Apr  1 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
-			1:00	1:00	CEST	1945 Apr 12 2:00s
+			1:00	Austria	CE%sT	1940 Apr  1  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
+			1:00	1:00	CEST	1945 Apr 12  2:00s
 			1:00	-	CET	1946
 			1:00	Austria	CE%sT	1981
 			1:00	EU	CE%sT
@@ -731,38 +743,29 @@
 # GMT+3 without DST (was GMT+2 with DST).
 #
 # Sources (Russian language):
-# 1.
-# <a href="http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html">
 # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
-# </a>
-# 2.
-# <a href="http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/">
 # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
-# </a>
-# 3.
-# <a href="http://news.tut.by/society/250578.html">
 # http://news.tut.by/society/250578.html
-# </a>
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
-			1:50	-	MMT	1924 May 2 # Minsk Mean Time
+			1:50	-	MMT	1924 May  2 # Minsk Mean Time
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Jun 28
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
-			2:00	-	EET	1992 Mar 29 0:00s
-			2:00	1:00	EEST	1992 Sep 27 0:00s
-			2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			3:00	-	FET # Further-eastern European Time
+			3:00	-	MSK	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
+			2:00	-	EET	1992 Mar 29  0:00s
+			2:00	1:00	EEST	1992 Sep 27  0:00s
+			2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			3:00	-	FET
 
 # Belgium
 #
 # From Paul Eggert (1997-07-02):
 # Entries from 1918 through 1991 are taken from:
 #	Annuaire de L'Observatoire Royal de Belgique,
-#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
 #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
 #	pp 8-9.
 # LMT before 1892 was 0:17:30, according to the official journal of Belgium:
@@ -812,7 +815,7 @@
 Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Brussels	0:17:30 -	LMT	1880
-			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
+			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
 			0:00	-	WET	1914 Nov  8
 			1:00	-	CET	1916 May  1  0:00
 			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
@@ -828,8 +831,8 @@
 #
 # From Plamen Simenov via Steffen Thorsen (1999-09-09):
 # A document of Government of Bulgaria (No.94/1997) says:
-# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
-# EETDST --> EET is in 04:00 Local time in last Sunday of October
+# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST -> EET is in 04:00 Local time in last Sunday of October
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
@@ -842,7 +845,7 @@
 			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
 			2:00	-	EET	1942 Nov  2  3:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 Apr 2 3:00
+			1:00	-	CET	1945 Apr  2  3:00
 			2:00	-	EET	1979 Mar 31 23:00
 			2:00	Bulg	EE%sT	1982 Sep 26  2:00
 			2:00	C-Eur	EE%sT	1991
@@ -866,15 +869,15 @@
 Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Prague	0:57:44 -	LMT	1850
-			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
-			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
+			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
+			1:00	C-Eur	CE%sT	1944 Sep 17  2:00s
 			1:00	Czech	CE%sT	1979
 			1:00	EU	CE%sT
 # Use Europe/Prague also for Slovakia.
 
 # Denmark, Faroe Islands, and Greenland
 
-# From Jesper Norgaard Welen (2005-04-26):
+# From Jesper Nørgaard Welen (2005-04-26):
 # http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
 # [introducing standard time] was in effect from 1894-01-01....
 # The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
@@ -884,7 +887,7 @@
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
 #
 # This provoked a new law from 1974 to make possible summer time changes
-# in subsequenet decrees with the law
+# in subsequent decrees with the law
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
 #
 # It seems however that no decree was set forward until 1980.  I have
@@ -899,7 +902,7 @@
 # was suspended on that night):
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
 
-# From Jesper Norgaard Welen (2005-06-11):
+# From Jesper Nørgaard Welen (2005-06-11):
 # The Herning Folkeblad (1980-09-26) reported that the night between
 # Saturday and Sunday the clock is set back from three to two.
 
@@ -923,11 +926,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
 			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
-			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
-			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
+			 1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			 1:00	Denmark	CE%sT	1980
 			 1:00	EU	CE%sT
-Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
+Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11 # Tórshavn
 			 0:00	-	WET	1981
 			 0:00	EU	WE%sT
 #
@@ -939,11 +942,11 @@
 # From Paul Eggert (2006-03-22):
 # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
 # and left the EU on 1985-02-01.  It therefore should have been using EU
-# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
+# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthåb
 # used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
 # rules since at least 1991.  Assume EU rules since 1980.
 
-# From Gwillin Law (2001-06-06), citing
+# From Gwillim Law (2001-06-06), citing
 # <http://www.statkart.no/efs/efshefter/2001/efs5-2001.pdf> (2001-03-15),
 # and with translations corrected by Steffen Thorsen:
 #
@@ -978,16 +981,16 @@
 # DPC research station at Zackenberg.
 #
 # Scoresbysund and two small villages nearby keep time UTC-1 and use
-# the same daylight savings time period as in West Greenland (Godthab).
+# the same daylight savings time period as in West Greenland (Godthåb).
 #
-# The rest of Greenland, including Godthab (this area, although it
+# The rest of Greenland, including Godthåb (this area, although it
 # includes central Greenland, is known as west Greenland), keeps time
 # UTC-3, with daylight savings methods according to European rules.
 #
 # It is common procedure to use UTC 0 in the wilderness of East and
 # North Greenland, because it is mainly Icelandic aircraft operators
 # maintaining traffic in these areas.  However, the official status of
-# this area is that it sticks with Godthab time.  This area might be
+# this area is that it sticks with Godthåb time.  This area might be
 # considered a dual time zone in some respects because of this.
 
 # From Rives McDow (2001-11-19):
@@ -996,8 +999,8 @@
 
 # From Paul Eggert (2006-03-22):
 # From 1997 on the CIA map shows Danmarkshavn on GMT;
-# the 1995 map as like Godthab.
-# For lack of better info, assume they were like Godthab before 1996.
+# the 1995 map as like Godthåb.
+# For lack of better info, assume they were like Godthåb before 1996.
 # startkart.no says Thule does not observe DST, but this is clearly an error,
 # so go with Shanks & Pottenger for Thule transitions until this year.
 # For 2007 on assume Thule will stay in sync with US DST rules.
@@ -1012,15 +1015,15 @@
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT	1996
 			0:00	-	GMT
 Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
-			-2:00	-	CGT	1980 Apr  6 2:00
+			-2:00	-	CGT	1980 Apr  6  2:00
 			-2:00	C-Eur	CG%sT	1981 Mar 29
 			-1:00	EU	EG%sT
 Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT
 Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 			-4:00	Thule	A%sT
@@ -1042,17 +1045,16 @@
 # summer time next spring."
 
 # From Peter Ilieve (1998-11-04), heavily edited:
-# <a href="http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390">
 # The 1998-09-22 Estonian time law
-# </a>
+# http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390
 # refers to the Eighth Directive and cites the association agreement between
-# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22-27, 120).
 #
 # I also asked [my relative] whether they use any standard abbreviation
 # for their standard and summer times. He says no, they use "suveaeg"
 # (summer time) and "talveaeg" (winter time).
 
-# From <a href="http://www.baltictimes.com/">The Baltic Times</a> (1999-09-09)
+# From The Baltic Times <http://www.baltictimes.com/> (1999-09-09)
 # via Steffen Thorsen:
 # This year will mark the last time Estonia shifts to summer time,
 # a council of the ruling coalition announced Sept. 6....
@@ -1070,19 +1072,19 @@
 # The Estonian government has changed once again timezone politics.
 # Now we are using again EU rules.
 #
-# From Urmet Jaanes (2002-03-28):
+# From Urmet Jänes (2002-03-28):
 # The legislative reference is Government decree No. 84 on 2002-02-21.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tallinn	1:39:00	-	LMT	1880
-			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
+			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
 			1:00	C-Eur	CE%sT	1919 Jul
 			1:39:00	-	TMT	1921 May
 			2:00	-	EET	1940 Aug  6
 			3:00	-	MSK	1941 Sep 15
 			1:00	C-Eur	CE%sT	1944 Sep 22
-			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
-			2:00	1:00	EEST	1989 Sep 24 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
+			2:00	1:00	EEST	1989 Sep 24  2:00s
 			2:00	C-Eur	EE%sT	1998 Sep 22
 			2:00	EU	EE%sT	1999 Nov  1
 			2:00	-	EET	2002 Feb 21
@@ -1104,35 +1106,45 @@
 # This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
 # Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
 # Finnish) at
-#
-# <a href="http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf">
 # http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
-# </a>
 #
 # Page 105 (56 in PDF version) has a handy table of all past daylight savings
 # transitions. It is easy enough to interpret without Finnish skills.
 #
 # This is also confirmed by Finnish Broadcasting Company's archive at:
-#
-# <a href="http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401">
 # http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
-# </a>
 #
 # The news clip from 1981 says that "the time between 2 and 3 o'clock does not
 # exist tonight."
 
+# From Konstantin Hyppönen (2014-06-13):
+# [Heikki Oja's book Aikakirja 2013]
+# http://almanakka.helsinki.fi/images/aikakirja/Aikakirja2013kokonaan.pdf
+# pages 104-105, including a scan from a newspaper published on Apr 2 1942
+# say that ... [o]n Apr 2 1942, 24 o'clock (which means Apr 3 1942,
+# 00:00), clocks were moved one hour forward. The newspaper
+# mentions "on the night from Thursday to Friday"....
+# On Oct 4 1942, clocks were moved at 1:00 one hour backwards.
+#
+# From Paul Eggert (2014-06-14):
+# Go with Oja over Shanks.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
-Rule	Finland	1942	only	-	Oct	3	0:00	0	-
+Rule	Finland	1942	only	-	Apr	2	24:00	1:00	S
+Rule	Finland	1942	only	-	Oct	4	1:00	0	-
 Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
 Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
+
+# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
+# round to nearest.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
-			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
+Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
+			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
 			2:00	Finland	EE%sT	1983
 			2:00	EU	EE%sT
 
-# Aaland Is
+# Åland Is
 Link	Europe/Helsinki	Europe/Mariehamn
 
 
@@ -1140,14 +1152,14 @@
 
 # From Ciro Discepolo (2000-12-20):
 #
-# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Henri Le Corre, Régimes horaires pour le monde entier, Éditions
 # Traditionnelles - Paris 2 books, 1993
 #
-# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Gabriel, Traité de l'heure dans le monde, Guy Trédaniel,
 # Paris, 1991
 #
-# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
-# Guy tredaniel, Paris 1987
+# Françoise Gauquelin, Problèmes de l'heure résolus en astrologie,
+# Guy Trédaniel, Paris 1987
 
 
 #
@@ -1188,16 +1200,16 @@
 Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
 # The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
 # write that they were used in Monaco and in many French locations.
-# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
-# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
-# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
+# Le Corre writes that the upper limit of the free zone was Arnéguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamothe-Montravel, Marœuil, La
+# Rochefoucauld, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
 # Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
-# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Paray-le-Monial, Montceau-les-Mines, Chalon-sur-Saône, Arbois,
 # Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
 Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
 # Shanks & Pottenger say this transition occurred at Oct 6 1:00,
 # but go with Denis Excoffier (1997-12-12),
-# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# who quotes the Ephémérides astronomiques for 1998 from Bureau des Longitudes
 # as saying 5/10/41 22hUT.
 Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
 Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
@@ -1218,7 +1230,7 @@
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
-			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
+			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
 # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
 			0:00	France	WE%sT	1940 Jun 14 23:00
 # Le Corre says Paris stuck with occupied-France time after the liberation;
@@ -1235,15 +1247,13 @@
 # Bundesanstalt contains DST information back to 1916.
 # [See tz-link.htm for the URL.]
 
-# From Joerg Schilling (2002-10-23):
+# From Jörg Schilling (2002-10-23):
 # In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
-# <a href="http://www.dhm.de/lemo/html/biografien/BersarinNikolai/">
-# General [Nikolai] Bersarin</a>.
+# http://www.dhm.de/lemo/html/biografien/BersarinNikolai/
+# General [Nikolai] Bersarin.
 
 # From Paul Eggert (2003-03-08):
-# <a href="http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf">
 # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
-# </a>
 # says that Bersarin issued an order to use Moscow time on May 20.
 # However, Moscow did not observe daylight saving in 1945, so
 # this was equivalent to CEMT (GMT+3), not GMT+4.
@@ -1268,23 +1278,23 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
-			1:00	C-Eur	CE%sT	1945 May 24 2:00
+			1:00	C-Eur	CE%sT	1945 May 24  2:00
 			1:00 SovietZone	CE%sT	1946
 			1:00	Germany	CE%sT	1980
 			1:00	EU	CE%sT
 
 # From Tobias Conradi (2011-09-12):
-# Busingen <http://www.buesingen.de>, surrounded by the Swiss canton
+# Büsingen <http://www.buesingen.de>, surrounded by the Swiss canton
 # Schaffhausen, did not start observing DST in 1980 as the rest of DE
 # (West Germany at that time) and DD (East Germany at that time) did.
 # DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
 # which in turn is covered by the zone Europe/Berlin.
 #
-# Source for the time in Busingen 1980:
+# Source for the time in Büsingen 1980:
 # http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
 
 # From Arthur David Olson (2012-03-03):
-# Busingen and Zurich have shared clocks since 1970.
+# Büsingen and Zurich have shared clocks since 1970.
 
 Link	Europe/Zurich	Europe/Busingen
 
@@ -1295,8 +1305,8 @@
 
 # Gibraltar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
-			0:00	GB-Eire	%s	1957 Apr 14 2:00
+Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
+			0:00	GB-Eire	%s	1957 Apr 14  2:00
 			1:00	-	CET	1982
 			1:00	EU	CE%sT
 
@@ -1327,7 +1337,7 @@
 Rule	Greece	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
-			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
+			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
 			2:00	Greece	EE%sT	1941 Apr 30
 			1:00	Greece	CE%sT	1944 Apr  4
 			2:00	Greece	EE%sT	1981
@@ -1336,15 +1346,20 @@
 			2:00	EU	EE%sT
 
 # Hungary
+# From Paul Eggert (2014-07-15):
+# Dates for 1916-1945 are taken from:
+# Oross A. Jelen a múlt jövője: a nyári időszámítás Magyarországon 1916-1945.
+# National Archives of Hungary (2012-10-29).
+# http://mnl.gov.hu/a_het_dokumentuma/a_nyari_idoszamitas_magyarorszagon_19161945.html
+# This source does not always give times, which are taken from Shanks
+# & Pottenger (which disagree about the dates).
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
-Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
+Rule	Hungary	1918	only	-	Sep	16	 3:00	0	-
 Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
-Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
-Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
-Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
+Rule	Hungary	1919	only	-	Nov	24	 3:00	0	-
 Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
-Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
+Rule	Hungary	1945	only	-	Nov	 1	 0:00	0	-
 Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
 Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
 Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
@@ -1360,7 +1375,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
 			1:00	C-Eur	CE%sT	1918
-			1:00	Hungary	CE%sT	1941 Apr  6  2:00
+			1:00	Hungary	CE%sT	1941 Apr  8
 			1:00	C-Eur	CE%sT	1945
 			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
 			1:00	EU	CE%sT
@@ -1423,7 +1438,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
-			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
+			-1:00	Iceland	IS%sT	1968 Apr  7  1:00s
 			 0:00	-	GMT
 
 # Italy
@@ -1438,9 +1453,8 @@
 # From Paul Eggert (2006-03-22):
 # For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
 # F. Pollastri
-# <a href="http://toi.iriti.cnr.it/uk/ienitlt.html">
 # Day-light Saving Time in Italy (2006-02-03)
-# </a>
+# http://toi.iriti.cnr.it/uk/ienitlt.html
 # ('FP' below), taken from an Italian National Electrotechnical Institute
 # publication. When the three sources disagree, guess who's right, as follows:
 #
@@ -1500,8 +1514,8 @@
 Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
-			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
+			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
 			1:00	C-Eur	CE%sT	1944 Jul
 			1:00	Italy	CE%sT	1980
 			1:00	EU	CE%sT
@@ -1548,18 +1562,18 @@
 
 # From Andrei Ivanov (2000-03-06):
 # This year Latvia will not switch to Daylight Savings Time (as specified in
-# <a href="http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm">
 # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79)</a>, in Latvian for subscribers only).
+# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
+# in Latvian for subscribers only).
 
-# <a href="http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html">
-# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
-# </a>
+# From RFE/RL Newsline
+# http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html
+# (2001-01-03), noted after a heads-up by Rives McDow:
 # The Latvian government on 2 January decided that the country will
 # institute daylight-saving time this spring, LETA reported.
 # Last February the three Baltic states decided not to turn back their
 # clocks one hour in the spring....
-# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# Minister of Economy Aigars Kalvītis noted that Latvia had too few
 # daylight hours and thus decided to comply with a draft European
 # Commission directive that provides for instituting daylight-saving
 # time in EU countries between 2002 and 2006. The Latvian government
@@ -1569,18 +1583,23 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
+
+# Milne 1899 says Riga was 1:36:28 (Polytechnique House time).
+# Byalokoz 1919 says Latvia was 1:36:34.
+# Go with Byalokoz.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Riga	1:36:24	-	LMT	1880
-			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
-			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
-			1:36:24	-	RMT	1919 Apr  1 2:00
-			1:36:24	1:00	LST	1919 May 22 3:00
-			1:36:24	-	RMT	1926 May 11
+Zone	Europe/Riga	1:36:34	-	LMT	1880
+			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
+			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
+			1:36:34	-	RMT	1919 Apr  1  2:00
+			1:36:34	1:00	LST	1919 May 22  3:00
+			1:36:34	-	RMT	1926 May 11
 			2:00	-	EET	1940 Aug  5
 			3:00	-	MSK	1941 Jul
 			1:00	C-Eur	CE%sT	1944 Oct 13
-			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
-			2:00	1:00	EEST	1989 Sep lastSun 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar lastSun  2:00s
+			2:00	1:00	EEST	1989 Sep lastSun  2:00s
 			2:00	Latvia	EE%sT	1997 Jan 21
 			2:00	EU	EE%sT	2000 Feb 29
 			2:00	-	EET	2001 Jan  2
@@ -1614,7 +1633,7 @@
 # I would like to inform that in this year Lithuanian time zone
 # (Europe/Vilnius) was changed.
 
-# From <a href="http://www.elta.lt/">ELTA</a> No. 972 (2582) (1999-09-29),
+# From ELTA No. 972 (2582) (1999-09-29) <http://www.elta.lt/>,
 # via Steffen Thorsen:
 # Lithuania has shifted back to the second time zone (GMT plus two hours)
 # to be valid here starting from October 31,
@@ -1623,9 +1642,9 @@
 # motion to give up shifting to summer time in spring, as it was
 # already done by Estonia.
 
-# From the <a href="http://www.tourism.lt/informa/ff.htm">
-# Fact File, Lithuanian State Department of Tourism
-# </a> (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+# From the Fact File, Lithuanian State Department of Tourism
+# <http://www.tourism.lt/informa/ff.htm> (2000-03-27):
+# Local time is GMT+2 hours ..., no daylight saving.
 
 # From a user via Klaus Marten (2003-02-07):
 # As a candidate for membership of the European Union, Lithuania will
@@ -1638,18 +1657,18 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vilnius	1:41:16	-	LMT	1880
-			1:24:00	-	WMT	1917	    # Warsaw Mean Time
+			1:24:00	-	WMT	1917        # Warsaw Mean Time
 			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
 			1:00	-	CET	1920 Jul 12
 			2:00	-	EET	1920 Oct  9
 			1:00	-	CET	1940 Aug  3
 			3:00	-	MSK	1941 Jun 24
 			1:00	C-Eur	CE%sT	1944 Aug
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
 			2:00	C-Eur	EE%sT	1998
-			2:00	-	EET	1998 Mar 29 1:00u
-			1:00	EU	CE%sT	1999 Oct 31 1:00u
+			2:00	-	EET	1998 Mar 29  1:00u
+			1:00	EU	CE%sT	1999 Oct 31  1:00u
 			2:00	-	EET	2003 Jan  1
 			2:00	EU	EE%sT
 
@@ -1683,9 +1702,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 			1:00	Lux	CE%sT	1918 Nov 25
-			0:00	Lux	WE%sT	1929 Oct  6 2:00s
-			0:00	Belgium	WE%sT	1940 May 14 3:00
-			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
+			0:00	Lux	WE%sT	1929 Oct  6  2:00s
+			0:00	Belgium	WE%sT	1940 May 14  3:00
+			1:00	C-Eur	WE%sT	1944 Sep 18  3:00
 			1:00	Belgium	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1702,9 +1721,9 @@
 Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
+Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
 			1:00	EU	CE%sT
@@ -1719,7 +1738,7 @@
 # In early 1992 there was large-scale interethnic violence in the area
 # and it's possible that some Russophones continued to observe Moscow time.
 # But [two people] separately reported via
-# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# Jesper Nørgaard that as of 2001-01-24 Tiraspol was like Chisinau.
 # The Tiraspol entry has therefore been removed for now.
 #
 # From Alexander Krivenyshev (2011-10-17):
@@ -1728,13 +1747,8 @@
 # to the Winter Time).
 #
 # News (in Russian):
-# <a href="http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html">
 # http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
-# </a>
-#
-# <a href="http://www.allmoldova.com/moldova-news/1249064116.html">
 # http://www.allmoldova.com/moldova-news/1249064116.html
-# </a>
 #
 # The substance of this change (reinstatement of the Tiraspol entry)
 # is from a patch from Petr Machata (2011-10-17)
@@ -1752,9 +1766,7 @@
 # Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
 # Tiraspol will go back to winter time on October 30, 2011.
 # News from Moldova (in russian):
-# <a href="http://ru.publika.md/link_317061.html">
 # http://ru.publika.md/link_317061.html
-# </a>
 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1777,8 +1789,8 @@
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	France	WE%sT	1945 Sep 16 3:00
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	France	WE%sT	1945 Sep 16  3:00
 			1:00	France	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1822,8 +1834,8 @@
 # was not until 1866 when they were all required by law to observe
 # Amsterdam mean time.
 
-# The data before 1945 are taken from
-# <http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm>.
+# The data entries before 1945 are taken from
+# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -1854,8 +1866,8 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Amsterdam	0:19:32 -	LMT	1835
 			0:19:32	Neth	%s	1937 Jul  1
-			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			0:20	Neth	NE%sT	1940 May 16  0:00 # Dutch Time
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			1:00	Neth	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1885,14 +1897,14 @@
 # time they were declared as parts of Norway.  Svalbard was declared
 # as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
 # Mayen by law of 1930-02-27 no 2, section 2. (From
-# http://www.lovdata.no/all/nl-19250717-011.html and
-# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
+# <http://www.lovdata.no/all/nl-19250717-011.html> and
+# <http://www.lovdata.no/all/nl-19300227-002.html>).  The law/regulation
 # for normal/standard time in Norway is from 1894-06-29 no 1 (came
 # into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
 # part of this law since 1925/1930. (From
-# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
+# <http://www.lovdata.no/all/nl-18940629-001.html>) I have not been
 # able to find if Jan Mayen used a different time zone (e.g. -0100)
-# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
+# before 1930. Jan Mayen has only been "inhabited" since 1921 by
 # Norwegian meteorologists and maybe used the same time as Norway ever
 # since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
 # before 1895, and therefore probably changed the local time somewhere
@@ -1907,7 +1919,7 @@
 # <http://home.no.net/janmayen/history.htm> says that the meteorologists
 # burned down their station in 1940 and left the island, but returned in
 # 1941 with a small Norwegian garrison and continued operations despite
-# frequent air ttacks from Germans.  In 1943 the Americans established a
+# frequent air attacks from Germans.  In 1943 the Americans established a
 # radiolocating station on the island, called "Atlantic City".  Possibly
 # the UT offset changed during the war, but I think it unlikely that
 # Jan Mayen used German daylight-saving rules.
@@ -1918,7 +1930,7 @@
 # <http://www.svalbard.com/SvalbardFAQ.html> says that the Germans were
 # expelled on 1942-05-14.  However, small parties of Germans did return,
 # and according to Wilhelm Dege's book "War North of 80" (1954)
-# <http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html>
+# http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html
 # the German armed forces at the Svalbard weather station code-named
 # Haudegen did not surrender to the Allies until September 1945.
 #
@@ -1927,6 +1939,10 @@
 Link	Europe/Oslo	Arctic/Longyearbyen
 
 # Poland
+
+# The 1919 dates and times can be found in Tygodnik Urzędowy nr 1 (1919-03-20),
+# <http://www.wbc.poznan.pl/publication/32156> pp 1-2.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
 Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
@@ -1937,9 +1953,9 @@
 Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
 Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
 # For 1946 on the source is Kazimierz Borkowski,
-# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
-# <http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1>
-# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
+# Toruń Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
+# http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1
+# Thanks to Przemysław Augustyniak (2005-05-28) for this reference.
 # He also gives these further references:
 # Mon Pol nr 13, poz 162 (1995) <http://www.abc.com.pl/serwis/mp/1995/0162.htm>
 # Druk nr 2180 (2003) <http://www.senat.gov.pl/k5/dok/sejm/053/2180.pdf>
@@ -1959,10 +1975,10 @@
 Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Warsaw	1:24:00 -	LMT	1880
-			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
-			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
+			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
+			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
 			2:00	Poland	EE%sT	1922 Jun
-			1:00	Poland	CE%sT	1940 Jun 23 2:00
+			1:00	Poland	CE%sT	1940 Jun 23  2:00
 			1:00	C-Eur	CE%sT	1944 Oct
 			1:00	Poland	CE%sT	1977
 			1:00	W-Eur	CE%sT	1988
@@ -1970,6 +1986,14 @@
 
 # Portugal
 #
+# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
+# According to a Portuguese decree (1911-05-26)
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00.
+# Round the old offset to -0:36:45.  This agrees with Willett but disagrees
+# with Shanks, who says the transition occurred on 1911-05-24 at 00:00 for
+# Europe/Lisbon, Atlantic/Azores, and Atlantic/Madeira.
+#
 # From Rui Pedro Salgueiro (1992-11-12):
 # Portugal has recently (September, 27) changed timezone
 # (from WET to MET or CET) to harmonize with EEC.
@@ -2049,35 +2073,34 @@
 Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
 Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
-# Willett says 1912-01-01.  Go with Willett.
-Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
-			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
-			 0:00	Port	WE%sT	1966 Apr  3 2:00
-			 1:00	-	CET	1976 Sep 26 1:00
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
-			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
-			 1:00	EU	CE%sT	1996 Mar 31 1:00u
+Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
+			-0:36:45 -	LMT	1912 Jan  1 # Lisbon Mean Time
+			 0:00	Port	WE%sT	1966 Apr  3  2:00
+			 1:00	-	CET	1976 Sep 26  1:00
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
+			 0:00	W-Eur	WE%sT	1992 Sep 27  1:00s
+			 1:00	EU	CE%sT	1996 Mar 31  1:00u
 			 0:00	EU	WE%sT
-Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
-			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
-			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
-			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
-			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
-			 0:00	EU	WE%sT	1993 Mar 28 1:00u
+Zone Atlantic/Azores	-1:42:40 -	LMT	1884        # Ponta Delgada
+			-1:54:32 -	HMT	1912 Jan  1 # Horta Mean Time
+			-2:00	Port	AZO%sT	1966 Apr  3  2:00  # Azores Time
+			-1:00	Port	AZO%sT	1983 Sep 25  1:00s
+			-1:00	W-Eur	AZO%sT	1992 Sep 27  1:00s
+			 0:00	EU	WE%sT	1993 Mar 28  1:00u
 			-1:00	EU	AZO%sT
-Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
-			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
-			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
+Zone Atlantic/Madeira	-1:07:36 -	LMT	1884        # Funchal
+			-1:07:36 -	FMT	1912 Jan  1 # Funchal Mean Time
+			-1:00	Port	MAD%sT	1966 Apr  3  2:00 # Madeira Time
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
 			 0:00	EU	WE%sT
 
 # Romania
 #
 # From Paul Eggert (1999-10-07):
-# <a href="http://www.nineoclock.ro/POL/1778pol.html">
-# Nine O'clock</a> (1998-10-23) reports that the switch occurred at
+# Nine O'clock <http://www.nineoclock.ro/POL/1778pol.html>
+# (1998-10-23) reports that the switch occurred at
 # 04:00 local time in fall 1998.  For lack of better info,
 # assume that Romania and Moldova switched to EU rules in 1997,
 # the same year as Bulgaria.
@@ -2094,32 +2117,28 @@
 Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
-			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
-			2:00	Romania	EE%sT	1981 Mar 29 2:00s
+			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
+			2:00	Romania	EE%sT	1981 Mar 29  2:00s
 			2:00	C-Eur	EE%sT	1991
 			2:00	Romania	EE%sT	1994
 			2:00	E-Eur	EE%sT	1997
 			2:00	EU	EE%sT
 
+
 # Russia
 
 # From Alexander Krivenyshev (2011-09-15):
 # Based on last Russian Government Decree # 725 on August 31, 2011
 # (Government document
-# <a href="http://www.government.ru/gov/results/16355/print/">
 # http://www.government.ru/gov/results/16355/print/
-# </a>
 # in Russian)
 # there are few corrections have to be made for some Russian time zones...
 # All updated Russian Time Zones were placed in table and translated to English
 # by WorldTimeZone.com at the link below:
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia36.htm">
 # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
-# </a>
 
 # From Sanjeev Gupta (2011-09-27):
 # Scans of [Decree #23 of January 8, 1992] are available at:
-# <a href="http://government.consultant.ru/page.aspx?1223966">
 # http://government.consultant.ru/page.aspx?1223966
 # They are in Cyrillic letters (presumably Russian).
 
@@ -2128,16 +2147,12 @@
 # changed in September 2011:
 #
 # One source is
-# < a href="http://government.ru/gov/results/16355/>
 # http://government.ru/gov/results/16355/
-# </a>
 # which, according to translate.google.com, begins "Decree of August 31,
 # 2011 No 725" and contains no other dates or "effective date" information.
 #
 # Another source is
-# <a href="http://www.rg.ru/2011/09/06/chas-zona-dok.html">
 # http://www.rg.ru/2011/09/06/chas-zona-dok.html
-# </a>
 # which, according to translate.google.com, begins "Resolution of the
 # Government of the Russian Federation on August 31, 2011 N 725" and also
 # contains "Date first official publication: September 6, 2011 Posted on:
@@ -2145,28 +2160,45 @@
 # does not contain any "effective date" information.
 #
 # Another source is
-# <a href="http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7">
 # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# </a>
 # which, in note 8, contains "Resolution #725 of August 31, 2011...
 # Effective as of after 7 days following the day of the official publication"
 # but which does not contain any reference to September 6, 2011.
 #
 # The Wikipedia article refers to
-# <a href="http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896">
 # http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896
-# </a>
 # which seems to copy the text of the government.ru page.
 #
 # Tobias Conradi combines Wikipedia's
 # "as of after 7 days following the day of the official publication"
-# with www.rg.ru's "Date of first official publication: September 6, 2011" to get
-# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes).
+# with www.rg.ru's "Date of first official publication: September 6, 2011" to
+# get September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias
+# Conradi notes).
 #
 # None of the sources indicates a time of day for changing clocks.
 #
 # Go with 2011-09-13 0:00s.
 
+# From Alexander Krivenyshev (2014-07-01):
+# According to the Russian news (ITAR-TASS News Agency)
+# http://en.itar-tass.com/russia/738562
+# the State Duma has approved ... the draft bill on returning to
+# winter time standard and return Russia 11 time zones.  The new
+# regulations will come into effect on October 26, 2014 at 02:00 ...
+# http://asozd2.duma.gov.ru/main.nsf/%28Spravka%29?OpenAgent&RN=431985-6&02
+# Here is a link where we put together table (based on approved Bill N
+# 431985-6) with proposed 11 Russian time zones and corresponding
+# areas/cities/administrative centers in the Russian Federation (in English):
+# http://www.worldtimezone.com/dst_news/dst_news_russia65.html
+#
+# From Alexander Krivenyshev (2014-07-22):
+# Putin signed the Federal Law 431985-6 ... (in Russian)
+# http://itar-tass.com/obschestvo/1333711
+# http://www.pravo.gov.ru:8080/page.aspx?111660
+# http://www.kremlin.ru/acts/46279
+# From October 26, 2014 the new Russian time zone map will looks like this:
+# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
+
 # From Paul Eggert (2006-03-22):
 # Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
 # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
@@ -2193,9 +2225,9 @@
 #
 # For Grozny, Chechnya, we have the following story from
 # John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
-# News--often false--is spread by word of mouth.  A rumor that it was
+# News - often false - is spread by word of mouth.  A rumor that it was
 # time to move the clocks back put this whole city out of sync with
-# the rest of Russia for two weeks--even soldiers stationed here began
+# the rest of Russia for two weeks - even soldiers stationed here began
 # enforcing curfew at the wrong time.
 #
 # From Gwillim Law (2001-06-05):
@@ -2206,107 +2238,265 @@
 # since September 1997....  Although the Kuril Islands are
 # administratively part of Sakhalin oblast', they appear to have
 # remained on UTC+11 along with Magadan.
-#
+
+# From Tim Parenti (2014-07-06):
+# The comments detailing the coverage of each Russian zone are meant to assist
+# with maintenance only and represent our best guesses as to which regions
+# are covered by each zone.  They are not meant to be taken as an authoritative
+# listing.  The region codes listed come from
+# http://en.wikipedia.org/w/?title=Federal_subjects_of_Russia&oldid=611810498
+# and are used for convenience only; no guarantees are made regarding their
+# future stability.  ISO 3166-2:RU codes are also listed for first-level
+# divisions where available.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-#
-# Kaliningradskaya oblast'.
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Kaliningrad covers...
+# 39	RU-KGD	Kaliningrad Oblast
+
 Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
 			 1:00	C-Eur	CE%sT	1945
 			 2:00	Poland	CE%sT	1946
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			 3:00	-	FET # Further-eastern European Time
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			 3:00	-	FET	2014 Oct 26  2:00s
+			 2:00	-	EET
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Moscow covers...
+# 01	RU-AD	Adygea, Republic of
+# 05	RU-DA	Dagestan, Republic of
+# 06	RU-IN	Ingushetia, Republic of
+# 07	RU-KB	Kabardino-Balkar Republic
+# 08	RU-KL	Kalmykia, Republic of
+# 09	RU-KC	Karachay-Cherkess Republic
+# 10	RU-KR	Karelia, Republic of
+# 11	RU-KO	Komi Republic
+# 12	RU-ME	Mari El Republic
+# 13	RU-MO	Mordovia, Republic of
+# 15	RU-SE	North Ossetia-Alania, Republic of
+# 16	RU-TA	Tatarstan, Republic of
+# 20	RU-CE	Chechen Republic
+# 21	RU-CU	Chuvash Republic
+# 23	RU-KDA	Krasnodar Krai
+# 26	RU-STA	Stavropol Krai
+# 29	RU-ARK	Arkhangelsk Oblast
+# 31	RU-BEL	Belgorod Oblast
+# 32	RU-BRY	Bryansk Oblast
+# 33	RU-VLA	Vladimir Oblast
+# 35	RU-VLG	Vologda Oblast
+# 36	RU-VOR	Voronezh Oblast
+# 37	RU-IVA	Ivanovo Oblast
+# 40	RU-KLU	Kaluga Oblast
+# 44	RU-KOS	Kostroma Oblast
+# 46	RU-KRS	Kursk Oblast
+# 47	RU-LEN	Leningrad Oblast
+# 48	RU-LIP	Lipetsk Oblast
+# 50	RU-MOS	Moscow Oblast
+# 51	RU-MUR	Murmansk Oblast
+# 52	RU-NIZ	Nizhny Novgorod Oblast
+# 53	RU-NGR	Novgorod Oblast
+# 57	RU-ORL	Oryol Oblast
+# 58	RU-PNZ	Penza Oblast
+# 60	RU-PSK	Pskov Oblast
+# 61	RU-ROS	Rostov Oblast
+# 62	RU-RYA	Ryazan Oblast
+# 67	RU-SMO	Smolensk Oblast
+# 68	RU-TAM	Tambov Oblast
+# 69	RU-TVE	Tver Oblast
+# 71	RU-TUL	Tula Oblast
+# 73	RU-ULY	Ulyanovsk Oblast
+# 76	RU-YAR	Yaroslavl Oblast
+# 77	RU-MOW	Moscow
+# 78	RU-SPE	Saint Petersburg
+# 83	RU-NEN	Nenets Autonomous Okrug
+
+# From Vladimir Karpinsky (2014-07-08):
+# LMT in Moscow (before Jul 3, 1916) is 2:30:17, that was defined by Moscow
+# Observatory (coordinates: 55 deg. 45'29.70", 37 deg. 34'05.30")....
+# LMT in Moscow since Jul 3, 1916 is 2:31:01 as a result of new standard.
+# (The info is from the book by Byalokoz ... p. 18.)
+# The time in St. Petersburg as capital of Russia was defined by
+# Pulkov observatory, near St. Petersburg.  In 1916 LMT Moscow
+# was synchronized with LMT St. Petersburg (+30 minutes), (Pulkov observatory
+# coordinates: 59 deg. 46'18.70", 30 deg. 19'40.70") so 30 deg. 19'40.70" >
+# 2h01m18.7s = 2:01:19.  LMT Moscow = LMT St.Petersburg + 30m 2:01:19 + 0:30 =
+# 2:31:19 ...
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Adygeya, Arkhangel'skaya oblast',
-# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
-# Vologodskaya oblast', Voronezhskaya oblast',
-# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
-# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
-# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
-# Respublika Kareliya, Respublika Komi,
-# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
-# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
-# Respublika Mordoviya, Moskva, Moskovskaya oblast',
-# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
-# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
-# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
-# Ryazanskaya oblast', Sankt-Peterburg,
-# Respublika Severnaya Osetiya, Smolenskaya oblast',
-# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
-# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
-# Chechenskaya Respublika, Chuvashskaya oblast',
-# Yaroslavskaya oblast'
-Zone Europe/Moscow	 2:30:20 -	LMT	1880
-			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
-			 2:30:48 Russia	%s	1919 Jul  1 2:00
+# From Paul Eggert (2014-07-08):
+# Milne does not list Moscow, but suggests that its time might be listed in
+# Résumés mensuels et annuels des observations météorologiques (1895).
+# Presumably this is OCLC 85825704, a journal published with parallel text in
+# Russian and French.  This source has not been located; go with Karpinsky.
+
+Zone Europe/Moscow	 2:30:17 -	LMT	1880
+			 2:30:17 -	MMT	1916 Jul  3 # Moscow Mean Time
+			 2:31:19 Russia	%s	1919 Jul  1  2:00
+			 3:00	Russia	%s	1921 Oct
 			 3:00	Russia	MSK/MSD	1922 Oct
 			 2:00	-	EET	1930 Jun 21
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
-			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
-			 4:00	-	MSK
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1992 Jan 19  2:00s
+			 3:00	Russia	MSK/MSD	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Simferopol covers...
+# **	****	Crimea, Republic of
+# **	****	Sevastopol
+
+Zone Europe/Simferopol	 2:16:24 -	LMT	1880
+			 2:16	-	SMT	1924 May  2 # Simferopol Mean T
+			 2:00	-	EET	1930 Jun 21
+			 3:00	-	MSK	1941 Nov
+			 1:00	C-Eur	CE%sT	1944 Apr 13
+			 3:00	Russia	MSK/MSD	1990
+			 3:00	-	MSK	1990 Jul  1  2:00
+			 2:00	-	EET	1992
+# Central Crimea used Moscow time 1994/1997.
 #
-# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
-# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
-# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
-# others?  But we have no data.
+# From Paul Eggert (2006-03-22):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
+# from Kiev to Moscow time sometime after the January 1994 elections.
+# Shanks (1999) says "date of change uncertain", but implies that it happened
+# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
+# 1994-09-25 03:00, but that can't be right.  For now, guess it
+# changed in May.
+			 2:00	E-Eur	EE%sT	1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
+			 3:00	1:00	MSD	1996 Oct 27  3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+			 3:00	Russia	MSK/MSD	1997
+			 3:00	-	MSK	1997 Mar lastSun  1:00u
+# From Alexander Krivenyshev (2014-03-17):
+# time change at 2:00 (2am) on March 30, 2014
+# http://vz.ru/news/2014/3/17/677464.html
+# From Paul Eggert (2014-03-30):
+# Simferopol and Sevastopol reportedly changed their central town clocks
+# late the previous day, but this appears to have been ceremonial
+# and the discrepancies are small enough to not worry about.
+			 2:00	EU	EE%sT	2014 Mar 30  2:00
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Volgograd covers...
+# 30	RU-AST	Astrakhan Oblast
+# 34	RU-VGG	Volgograd Oblast
+# 43	RU-KIR	Kirov Oblast
+# 64	RU-SAR	Saratov Oblast
+
+# From Paul Eggert (2006-05-09):
+# Shanks & Pottenger say Kirov is still at +0400 but Wikipedia says +0300.
+# Perhaps it switched after the others?  But we have no data.
+
 Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
 			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
 			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
 			 4:00	-	STAT	1961 Nov 11
-			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
-			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
-			 4:00	-	VOLT	1992 Mar 29 2:00s
-			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
-			 4:00	-	VOLT
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Samarskaya oblast', Udmyrtskaya respublika
-Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
+			 4:00	Russia	VOL%sT	1989 Mar 26  2:00s # Volgograd T
+			 3:00	Russia	VOL%sT	1991 Mar 31  2:00s
+			 4:00	-	VOLT	1992 Mar 29  2:00s
+			 3:00	Russia	MSK	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Samara covers...
+# 18	RU-UD	Udmurt Republic
+# 63	RU-SAM	Samara Oblast
+
+# Byalokoz 1919 says Samara was 3:20:20.
+
+Zone Europe/Samara	 3:20:20 -	LMT	1919 Jul  1  2:00
 			 3:00	-	SAMT	1930 Jun 21
 			 4:00	-	SAMT	1935 Jan 27
-			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
-			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
-			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
-			 3:00	-	KUYT	1991 Oct 20 3:00
-			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
-			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
+			 4:00	Russia	KUY%sT	1989 Mar 26  2:00s # Kuybyshev
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1991 Sep 29  2:00s
+			 3:00	-	KUYT	1991 Oct 20  3:00
+			 4:00	Russia	SAM%sT	2010 Mar 28  2:00s # Samara Time
+			 3:00	Russia	SAM%sT	2011 Mar 27  2:00s
 			 4:00	-	SAMT
 
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Yekaterinburg covers...
+# 02	RU-BA	Bashkortostan, Republic of
+# 90	RU-PER	Perm Krai
+# 45	RU-KGN	Kurgan Oblast
+# 56	RU-ORE	Orenburg Oblast
+# 66	RU-SVE	Sverdlovsk Oblast
+# 72	RU-TYU	Tyumen Oblast
+# 74	RU-CHE	Chelyabinsk Oblast
+# 86	RU-KHM	Khanty-Mansi Autonomous Okrug - Yugra
+# 89	RU-YAN	Yamalo-Nenets Autonomous Okrug
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
-# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
-# Sverdlovskaya oblast', Tyumenskaya oblast',
-# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
-# Yamalo-Nenetskij avtonomnyj okrug.
-Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
+# Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak
+# Autonomous Okrug merged to form (90, RU-PER) Perm Krai.
+
+# Milne says Yekaterinburg was 4:02:32.9; round to nearest.
+# Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05.
+# Assume it switched on 1916-07-03, the time of the new standard.
+# The 1919 and 1930 transitions are from Shanks.
+
+Zone Asia/Yekaterinburg	 4:02:33 -	LMT	1916 Jul  3
+			 3:45:05 -	PMT	1919 Jul 15  4:00
 			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
-			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
-			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
-			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
-			 6:00	-	YEKT	# Yekaterinburg Time
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
-Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
-			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
-			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
-			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
-			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
-			 7:00	-	OMST
-#
+			 5:00	Russia	SVE%sT	1991 Mar 31  2:00s
+			 4:00	Russia	SVE%sT	1992 Jan 19  2:00s
+			 5:00	Russia	YEK%sT	2011 Mar 27  2:00s
+			 6:00	-	YEKT	2014 Oct 26  2:00s
+			 5:00	-	YEKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Omsk covers...
+# 04	RU-AL	Altai Republic
+# 22	RU-ALT	Altai Krai
+# 55	RU-OMS	Omsk Oblast
+
+# Byalokoz 1919 says Omsk was 4:53:30.
+
+Zone Asia/Omsk		 4:53:30 -	LMT	1919 Nov 14
+			 5:00	-	OMST	1930 Jun 21 # Omsk Time
+			 6:00	Russia	OMS%sT	1991 Mar 31  2:00s
+			 5:00	Russia	OMS%sT	1992 Jan 19  2:00s
+			 6:00	Russia	OMS%sT	2011 Mar 27  2:00s
+			 7:00	-	OMST	2014 Oct 26  2:00s
+			 6:00	-	OMST
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novosibirsk covers...
+# 54	RU-NVS	Novosibirsk Oblast
+# 70	RU-TOM	Tomsk Oblast
+
 # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
 # not clear when it switched from +7 to +6.
-# Novosibirskaya oblast', Tomskaya oblast'.
-Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
+
+Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
 			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
+			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
+			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 6:00	-	NOVT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novokuznetsk covers...
+# 42	RU-KEM	Kemerovo Oblast
 
 # From Alexander Krivenyshev (2009-10-13):
 # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
@@ -2319,14 +2509,10 @@
 # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
 #
 # Russian Government web site (Russian language)
-# <a href="http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archiv">
 # http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
-# </a>
 # or Russian-English translation by WorldTimeZone.com with reference
 # map to local region and new Russia Time Zone map after March 28, 2010
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_russia03.html
-# </a>
 #
 # Thus, when Russia will switch to DST on the night of March 28, 2010
 # Kemerovo region (Kemerovo oblast') will not change the clock.
@@ -2334,152 +2520,319 @@
 # As a result, Kemerovo oblast' will be in the same time zone as
 # Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
 
+# From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
+# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
+# realigning itself with KRAT.
+
 Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 7:00	-	KRAT	# Krasnoyarsk Time
+
 
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Krasnoyarsk covers...
+# 17	RU-TY	Tuva Republic
+# 19	RU-KK	Khakassia, Republic of
+# 24	RU-KYA	Krasnoyarsk Krai
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Krasnoyarskij kraj,
-# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
-# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
-Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
+# Note: Effective 2007-01-01, (88) Evenk Autonomous Okrug and (84) Taymyr
+# Autonomous Okrug were merged into (24, RU-KYA) Krasnoyarsk Krai.
+
+# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
+
+Zone Asia/Krasnoyarsk	 6:11:26 -	LMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
-			 8:00	-	KRAT
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2011 Mar 27  2:00s
+			 8:00	-	KRAT	2014 Oct 26  2:00s
+			 7:00	-	KRAT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Irkutsk covers...
+# 03	RU-BU	Buryatia, Republic of
+# 38	RU-IRK	Irkutsk Oblast
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Buryatiya, Irkutskaya oblast',
-# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
-Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
-			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
+# Note: Effective 2008-01-01, (85) Ust-Orda Buryat Autonomous Okrug was
+# merged into (38, RU-IRK) Irkutsk Oblast.
+
+# Milne 1899 says Irkutsk was 6:57:15.
+# Byalokoz 1919 says Irkutsk was 6:57:05.
+# Go with Byalokoz.
+
+Zone Asia/Irkutsk	 6:57:05 -	LMT	1880
+			 6:57:05 -	IMT	1920 Jan 25 # Irkutsk Mean Time
 			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
-			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
-			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
-			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
-			 9:00	-	IRKT
+			 8:00	Russia	IRK%sT	1991 Mar 31  2:00s
+			 7:00	Russia	IRK%sT	1992 Jan 19  2:00s
+			 8:00	Russia	IRK%sT	2011 Mar 27  2:00s
+			 9:00	-	IRKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Chita covers...
+# 92	RU-ZAB	Zabaykalsky Krai
 #
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
-# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
+# Note: Effective 2008-03-01, (75) Chita Oblast and (80) Agin-Buryat
+# Autonomous Okrug merged to form (92, RU-ZAB) Zabaykalsky Krai.
+
+Zone Asia/Chita	 7:33:52 -	LMT	1919 Dec 15
+			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
 
-# From Oscar van Vlijmen (2009-11-29):
-# ...some regions of [Russia] were merged with others since 2005...
-# Some names were changed, no big deal, except for one instance: a new name.
-# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Yakutsk covers...
+# 28	RU-AMU	Amur Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-02	****	Aldansky District
+# 14-04	****	Amginsky District
+# 14-05	****	Anabarsky District
+# 14-06	****	Bulunsky District
+# 14-07	****	Verkhnevilyuysky District
+# 14-10	****	Vilyuysky District
+# 14-11	****	Gorny District
+# 14-12	****	Zhigansky District
+# 14-13	****	Kobyaysky District
+# 14-14	****	Lensky District
+# 14-15	****	Megino-Kangalassky District
+# 14-16	****	Mirninsky District
+# 14-18	****	Namsky District
+# 14-19	****	Neryungrinsky District
+# 14-21	****	Nyurbinsky District
+# 14-23	****	Olenyoksky District
+# 14-24	****	Olyokminsky District
+# 14-26	****	Suntarsky District
+# 14-27	****	Tattinsky District
+# 14-29	****	Ust-Aldansky District
+# 14-32	****	Khangalassky District
+# 14-33	****	Churapchinsky District
+# 14-34	****	Eveno-Bytantaysky National District
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
-# Verkhnevilyujskij, Vilyujskij, Gornyj,
-# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
-# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
-# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
-# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
+# From Tim Parenti (2014-07-03):
+# Our commentary seems to have lost mention of (14-19) Neryungrinsky District.
+# Since the surrounding districts of Sakha are all YAKT, assume this is, too.
+# Also assume its history has been the same as the rest of Asia/Yakutsk.
 
-Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
+# Byalokoz 1919 says Yakutsk was 8:38:58.
+
+Zone Asia/Yakutsk	 8:38:58 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
-			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
-			 10:00	-	YAKT
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Vladivostok covers...
+# 25	RU-PRI	Primorsky Krai
+# 27	RU-KHA	Khabarovsk Krai
+# 79	RU-YEV	Jewish Autonomous Oblast
 #
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
-# [parts of] Respublika Sakha (Yakutiya).
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-09	****	Verkhoyansky District
+# 14-31	****	Ust-Yansky District
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
-Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
+# Milne 1899 says Vladivostok was 8:47:33.5.
+# Byalokoz 1919 says Vladivostok was 8:47:31.
+# Go with Byalokoz.
+
+Zone Asia/Vladivostok	 8:47:31 -	LMT	1922 Nov 15
 			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
-			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
-			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT
+			10:00	Russia	VLA%sT	1991 Mar 31  2:00s
+			 9:00	Russia	VLA%sT	1992 Jan 19  2:00s
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Khandyga covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-28	****	Tomponsky District
+# 14-30	****	Ust-Maysky District
 
 # From Arthur David Olson (2012-05-09):
 # Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time
 # in 2011.
-#
+
 # From Paul Eggert (2012-11-25):
 # Shanks and Pottenger (2003) has Khandyga on Yakutsk time.
 # Make a wild guess that it switched to Vladivostok time in 2004.
 # This transition is no doubt wrong, but we have no better info.
-#
+
 Zone Asia/Khandyga	 9:02:13 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
 			 9:00	Russia	YAK%sT	2004
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT	2011 Sep 13 0:00s # Decree 725?
-			10:00	-	YAKT
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2011 Sep 13  0:00s # Decree 725?
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
 
-#
-# Sakhalinskaya oblast'.
-# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
+# From Tim Parenti (2014-07-03):
+# Asia/Sakhalin covers...
+# 65	RU-SAK	Sakhalin Oblast
+# ...with the exception of:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
 Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
-			 9:00	-	CJT	1938
+			 9:00	-	JCST	1937 Oct  1
 			 9:00	-	JST	1945 Aug 25
-			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
-			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
-			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
-			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
-			11:00	-	SAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Magadanskaya oblast', Respublika Sakha (Yakutiya).
-# Probably also: Kuril Islands.
+			11:00	Russia	SAK%sT	1991 Mar 31  2:00s # Sakhalin T
+			10:00	Russia	SAK%sT	1992 Jan 19  2:00s
+			11:00	Russia	SAK%sT	1997 Mar lastSun  2:00s
+			10:00	Russia	SAK%sT	2011 Mar 27  2:00s
+			11:00	-	SAKT	2014 Oct 26  2:00s
+			10:00	-	SAKT
+
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, ... Srednekolymskij.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Magadan covers...
+# 49	RU-MAG	Magadan Oblast
+
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# Magadan Oblast is moving from UTC+12 to UTC+10 on 2014-10-26; however,
+# several districts of Sakha Republic as well as Severo-Kurilsky District of
+# the Sakhalin Oblast (also known as the North Kuril Islands), represented
+# until now by Asia/Magadan, will instead move to UTC+11.  These regions will
+# need their own zone.
+
 Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
 			10:00	-	MAGT	1930 Jun 21 # Magadan Time
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			10:00	-	MAGT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Srednekolymsk covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-01	****	Abyysky District
+# 14-03	****	Allaikhovsky District
+# 14-08	****	Verkhnekolymsky District
+# 14-17	****	Momsky District
+# 14-20	****	Nizhnekolymsky District
+# 14-25	****	Srednekolymsky District
+#
+# ...and parts of (65, RU-SAK) Sakhalin Oblast:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# From Tim Parenti (2014-07-02):
+# Oymyakonsky District of Sakha Republic (represented by Ust-Nera), along with
+# most of Sakhalin Oblast (represented by Sakhalin) will be moving to UTC+10 on
+# 2014-10-26 to stay aligned with VLAT/SAKT; however, Severo-Kurilsky District
+# of the Sakhalin Oblast (also known as the North Kuril Islands, represented by
+# Severo-Kurilsk) will remain on UTC+11.
+
+# From Tim Parenti (2014-07-06):
+# Assume North Kuril Islands have history like Magadan before 2011-03-27.
+# There is a decent chance this is wrong, in which case a new zone
+# Asia/Severo-Kurilsk would become necessary.
+#
+# Srednekolymsk and Zyryanka are the most populous places amongst these
+# districts, but have very similar populations.  In fact, Wikipedia currently
+# lists them both as having 3528 people, exactly 1668 males and 1860 females
+# each!  (Yikes!)
+# http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
+# http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
+# Assume this is a mistake, albeit an amusing one.
+#
+# Looking at censuses, the populations of the two municipalities seem to have
+# fluctuated recently.  Zyryanka was more populous than Srednekolymsk in the
+# 1989 and 2002 censuses, but Srednekolymsk was more populous in the most
+# recent (2010) census, 3525 to 3170.  (See pages 195 and 197 of
+# http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf
+# in Russian.)  In addition, Srednekolymsk appears to be a much older
+# settlement and the population of Zyryanka seems to be declining.
+# Go with Srednekolymsk.
+#
+# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
+# as the abbreviation.  Use SRET instead.
+
+Zone Asia/Srednekolymsk	10:14:52 -	LMT	1924 May  2
+			10:00	-	MAGT	1930 Jun 21 # Magadan Time
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			11:00	-	SRET	# Srednekolymsk Time
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-22	****	Oymyakonsky District
 
 # From Arthur David Olson (2012-05-09):
-# Ojmyakonskij and the Kuril Islands switched from
+# Ojmyakonskij [and the Kuril Islands] switched from
 # Magadan time to Vladivostok time in 2011.
+#
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# It's unlikely that any of the Kuril Islands were involved in such a switch,
+# as the South and Middle Kurils have been on UTC+11 (SAKT) with the rest of
+# Sakhalin Oblast since at least 2011-09, and the North Kurils have been on
+# UTC+12 since at least then, too.
+
 Zone Asia/Ust-Nera	 9:32:54 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
 			 9:00	Russia	YAKT	1981 Apr  1
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT	2011 Sep 13 0:00s # Decree 725?
-			11:00	-	VLAT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2011 Sep 13  0:00s # Decree 725?
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
 
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Kamchatka covers...
+# 91	RU-KAM	Kamchatka Krai
 #
-# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
+# Note: Effective 2007-07-01, (41) Kamchatka Oblast and (82) Koryak
+# Autonomous Okrug merged to form (91, RU-KAM) Kamchatka Krai.
+
+# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
+# Asia/Petropavlovsk-Kamchatsky, but these are too long.
 Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
 			11:00	-	PETT	1930 Jun 21 # P-K Time
-			12:00	Russia	PET%sT	1991 Mar 31 2:00s
-			11:00	Russia	PET%sT	1992 Jan 19 2:00s
-			12:00	Russia	PET%sT	2010 Mar 28 2:00s
-			11:00	Russia	PET%sT	2011 Mar 27 2:00s
+			12:00	Russia	PET%sT	1991 Mar 31  2:00s
+			11:00	Russia	PET%sT	1992 Jan 19  2:00s
+			12:00	Russia	PET%sT	2010 Mar 28  2:00s
+			11:00	Russia	PET%sT	2011 Mar 27  2:00s
 			12:00	-	PETT
-#
-# Chukotskij avtonomnyj okrug
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Anadyr covers...
+# 87	RU-CHU	Chukotka Autonomous Okrug
+
 Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
-			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
-			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
-			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
-			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
-			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
+			13:00	Russia	ANA%sT	1982 Apr  1  0:00s
+			12:00	Russia	ANA%sT	1991 Mar 31  2:00s
+			11:00	Russia	ANA%sT	1992 Jan 19  2:00s
+			12:00	Russia	ANA%sT	2010 Mar 28  2:00s
+			11:00	Russia	ANA%sT	2011 Mar 27  2:00s
 			12:00	-	ANAT
 
+
 # San Marino
 # See Europe/Rome.
 
@@ -2488,11 +2841,11 @@
 Zone	Europe/Belgrade	1:22:00	-	LMT	1884
 			1:00	-	CET	1941 Apr 18 23:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 May 8 2:00s
+			1:00	-	CET	1945 May  8  2:00s
 			1:00	1:00	CEST	1945 Sep 16  2:00s
-# Metod Kozelj reports that the legal date of
+# Metod Koželj reports that the legal date of
 # transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
-# Shanks & Pottenger don't give as much detail, so go with Kozelj.
+# Shanks & Pottenger don't give as much detail, so go with Koželj.
 			1:00	-	CET	1982 Nov 27
 			1:00	EU	CE%sT
 Link Europe/Belgrade Europe/Ljubljana	# Slovenia
@@ -2568,13 +2921,13 @@
 			 0:00	1:00	WEST	1918 Oct  7 23:00
 			 0:00	-	WET	1924
 			 0:00	Spain	WE%sT	1929
-			 0:00 SpainAfrica WE%sT 1984 Mar 16
+			 0:00 SpainAfrica WE%sT	1984 Mar 16
 			 1:00	-	CET	1986
 			 1:00	EU	CE%sT
 Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
-			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
-			 0:00	-	WET	1980 Apr  6 0:00s
-			 0:00	1:00	WEST	1980 Sep 28 0:00s
+			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
+			 0:00	-	WET	1980 Apr  6  0:00s
+			 0:00	1:00	WEST	1980 Sep 28  0:00s
 			 0:00	EU	WE%sT
 # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
 # Ignore this for now, as the Canaries are part of the EU.
@@ -2583,7 +2936,7 @@
 
 # From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
 #
-# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
+# The law "Svensk författningssamling 1878, no 14" about standard time in 1879:
 # From the beginning of 1879 (that is 01-01 00:00) the time for all
 # places in the country is "the mean solar time for the meridian at
 # three degrees, or twelve minutes of time, to the west of the
@@ -2594,7 +2947,7 @@
 # national standard time as 01:00:14 ahead of GMT....
 #
 # About the beginning of CET in Sweden. The lawtext ("Svensk
-# forfattningssamling 1899, no 44") states, that "from the beginning
+# författningssamling 1899, no 44") states, that "from the beginning
 # of 1900... ... the same as the mean solar time for the meridian at
 # the distance of one hour of time from the meridian of the English
 # observatory at Greenwich, or at 12 minutes 14 seconds to the west
@@ -2602,7 +2955,7 @@
 # 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
 # in Sweden is 01:00:00 ahead of GMT.
 #
-# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
+# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states
 # that "1916-05-15 is considered to begin one hour earlier". It is
 # pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
 # Further the law says, that "1916-09-30 is considered to end one hour later".
@@ -2612,7 +2965,7 @@
 # not available on the site (to my knowledge they are only available
 # in Swedish): <http://www.riksdagen.se/english/work/sfst.asp> (type
 # "sommartid" without the quotes in the field "Fritext" and then click
-# the Sok-button).
+# the Sök-button).
 #
 # (2001-05-13):
 #
@@ -2627,9 +2980,9 @@
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
-			1:00:14	-	SET	1900 Jan  1	# Swedish Time
+			1:00:14	-	SET	1900 Jan  1 # Swedish Time
 			1:00	-	CET	1916 May 14 23:00
-			1:00	1:00	CEST	1916 Oct  1 01:00
+			1:00	1:00	CEST	1916 Oct  1  1:00
 			1:00	-	CET	1980
 			1:00	EU	CE%sT
 
@@ -2637,7 +2990,7 @@
 # From Howse:
 # By the end of the 18th century clocks and watches became commonplace
 # and their performance improved enormously.  Communities began to keep
-# mean time in preference to apparent time -- Geneva from 1780 ....
+# mean time in preference to apparent time - Geneva from 1780 ....
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 # From Whitman (who writes "Midnight?"):
 # Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
@@ -2653,7 +3006,7 @@
 # to be wrong. This is now verified.
 #
 # I have found copies of the original ruling by the Swiss Federal
-# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
+# government, in 'Eidgenössische Gesetzessammlung 1941 and 1942' (Swiss
 # federal law collection)...
 #
 # DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
@@ -2672,7 +3025,7 @@
 # night as an absolute novelty, because this was the first time that such
 # a thing had happened in Switzerland.
 #
-# I have also checked 1916, because one book source (Gabriel, Traite de
+# I have also checked 1916, because one book source (Gabriel, Traité de
 # l'heure dans le monde) claims that Switzerland had DST in 1916. This is
 # false, no official document could be found. Probably Gabriel got misled
 # by references to Germany, which introduced DST in 1916 for the first time.
@@ -2686,19 +3039,19 @@
 # One further detail for Switzerland, which is probably out of scope for
 # most users of tzdata: The [Europe/Zurich zone] ...
 # describes all of Switzerland correctly, with the exception of
-# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
+# the Canton de Genève (Geneva, Genf). Between 1848 and 1894 Geneva did not
 # follow Bern Mean Time but kept its own local mean time.
 # To represent this, an extra zone would be needed.
 #
 # From Alois Treindl (2013-09-11):
 # The Federal regulations say
 # http://www.admin.ch/opc/de/classified-compilation/20071096/index.html
-# ... the meridian for Bern mean time ... is 7 degrees 26'22.50".
+# ... the meridian for Bern mean time ... is 7 degrees 26' 22.50".
 # Expressed in time, it is 0h29m45.5s.
 
 # From Pierre-Yves Berger (2013-09-11):
-# the "Circulaire du conseil federal" (December 11 1893)
-# <http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353> ...
+# the "Circulaire du conseil fédéral" (December 11 1893)
+# http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353
 # clearly states that the [1894-06-01] change should be done at midnight
 # but if no one is present after 11 at night, could be postponed until one
 # hour before the beginning of service.
@@ -2709,14 +3062,14 @@
 # We can find no reliable source for Shanks's assertion that all of Switzerland
 # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12.  This book:
 #
-#	Jakob Messerli. Gleichmassig, punktlich, schnell: Zeiteinteilung und
+#	Jakob Messerli. Gleichmässig, pünktlich, schnell. Zeiteinteilung und
 #	Zeitgebrauch in der Schweiz im 19. Jahrhundert. Chronos, Zurich 1995,
 #	ISBN 3-905311-68-2, OCLC 717570797.
 #
 # suggests that the transition was more gradual, and that the Swiss did not
 # agree about civil time during the transition.  The timekeeping it gives the
 # most detail for is postal and telegraph time: here, federal legislation (the
-# "Bundesgesetz uber die Erstellung von elektrischen Telegraphen") passed on
+# "Bundesgesetz über die Erstellung von elektrischen Telegraphen") passed on
 # 1851-11-23, and an official implementation notice was published 1853-07-16
 # (Bundesblatt 1853, Bd. II, S. 859).  On p 72 Messerli writes that in
 # practice since July 1853 Bernese time was used in "all postal and telegraph
@@ -2730,7 +3083,7 @@
 Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
-			0:29:46	-	BMT	1894 Jun # Bern Mean Time
+			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
 			1:00	Swiss	CE%sT	1981
 			1:00	EU	CE%sT
 
@@ -2738,7 +3091,7 @@
 
 # From Amar Devegowda (2007-01-03):
 # The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at -
+# ... The latest rules are available at:
 # http://www.timeanddate.com/worldclock/timezone.html?n=107
 # From Steffen Thorsen (2007-01-03):
 # I have been able to find press records back to 1996 which all say that
@@ -2763,8 +3116,7 @@
 # (on a non-government server though) describing dates between 2002 and 2006:
 # http://www.alomaliye.com/bkk_2002_3769.htm
 
-# From G&ouml;kdeniz Karada&#x011f; (2011-03-10):
-#
+# From Gökdeniz Karadağ (2011-03-10):
 # According to the articles linked below, Turkey will change into summer
 # time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
 # This change is due to a nationwide exam on 27th.
@@ -2777,9 +3129,16 @@
 # Turkish Local election....
 # http://www.sabah.com.tr/Ekonomi/2014/02/12/yaz-saatinde-onemli-degisiklik
 # ... so Turkey will move clocks forward one hour on March 31 at 3:00 a.m.
-# From Paul Eggert (2014-02-17):
-# Here is an English-language source:
-# http://www.worldbulletin.net/turkey/129016/turkey-switches-to-daylight-saving-time-march-31
+# From Randal L. Schwartz (2014-04-15):
+# Having landed on a flight from the states to Istanbul (via AMS) on March 31,
+# I can tell you that NOBODY (even the airlines) respected this timezone DST
+# change delay.  Maybe the word just didn't get out in time.
+# From Paul Eggert (2014-06-15):
+# The press reported massive confusion, as election officials obeyed the rule
+# change but cell phones (and airline baggage systems) did not.  See:
+# Kostidis M. Eventful elections in Turkey. Balkan News Agency
+# http://www.balkaneu.com/eventful-elections-turkey/ 2014-03-30.
+# I guess the best we can do is document the official time.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
@@ -2846,10 +3205,10 @@
 			2:00	Turkey	EE%sT	1978 Oct 15
 			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
 			2:00	Turkey	EE%sT	2007
-			2:00	EU	EE%sT	2011 Mar 27 1:00u
-			2:00	-	EET	2011 Mar 28 1:00u
-			2:00	EU	EE%sT	2014 Mar 30 1:00u
-			2:00	-	EET	2014 Mar 31 1:00u
+			2:00	EU	EE%sT	2011 Mar 27  1:00u
+			2:00	-	EET	2011 Mar 28  1:00u
+			2:00	EU	EE%sT	2014 Mar 30  1:00u
+			2:00	-	EET	2014 Mar 31  1:00u
 			2:00	EU	EE%sT
 Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 
@@ -2870,7 +3229,7 @@
 # Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
 # approval from 266 deputies.
 #
-# Ukraine abolishes transter back to the winter time (in Russian)
+# Ukraine abolishes transfer back to the winter time (in Russian)
 # http://news.mail.ru/politics/6861560/
 #
 # The Ukrainians will no longer change the clock (in Russian)
@@ -2931,12 +3290,12 @@
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Sep 20
 			1:00	C-Eur	CE%sT	1943 Nov  6
-			3:00	Russia	MSK/MSD	1990 Jul  1 2:00
-			2:00	1:00	EEST	1991 Sep 29 3:00
+			3:00	Russia	MSK/MSD	1990 Jul  1  2:00
+			2:00	1:00	EEST	1991 Sep 29  3:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
 # Ruthenia used CET 1990/1991.
-# "Uzhhorod" is the transliteration of the Ukrainian name, but
+# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
 # "Uzhgorod" is more common in English.
 Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	-	CET	1940
@@ -2944,8 +3303,8 @@
 			1:00	1:00	CEST	1944 Oct 26
 			1:00	-	CET	1945 Jun 29
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			1:00	-	CET	1991 Mar 31 3:00
+			3:00	-	MSK	1990 Jul  1  2:00
+			1:00	-	CET	1991 Mar 31  3:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
@@ -2959,42 +3318,9 @@
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Aug 25
 			1:00	C-Eur	CE%sT	1943 Oct 25
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
-# Central Crimea used Moscow time 1994/1997.
-Zone Europe/Simferopol	2:16:24 -	LMT	1880
-			2:16	-	SMT	1924 May  2 # Simferopol Mean T
-			2:00	-	EET	1930 Jun 21
-			3:00	-	MSK	1941 Nov
-			1:00	C-Eur	CE%sT	1944 Apr 13
-			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			2:00	-	EET	1992
-# From Paul Eggert (2006-03-22):
-# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
-# from Kiev to Moscow time sometime after the January 1994 elections.
-# Shanks (1999) says "date of change uncertain", but implies that it happened
-# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
-# 1994-09-25 03:00, but that can't be right.  For now, guess it
-# changed in May.
-			2:00	E-Eur	EE%sT	1994 May
-# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
-			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
-			3:00	1:00	MSD	1996 Oct 27 3:00s
-# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
-# Assume it happened in March by not changing the clocks.
-			3:00	Russia	MSK/MSD	1997
-			3:00	-	MSK	1997 Mar lastSun 1:00u
-# From Alexander Krivenyshev (2014-03-17):
-# time change at 2:00 (2am) on March 30, 2014
-# http://vz.ru/news/2014/3/17/677464.html
-# From Paul Eggert (2014-03-30):
-# Simferopol and Sevastopol reportedly changed their central town clocks
-# late the previous day, but this appears to have been ceremonial
-# and the discrepancies are small enough to not worry about.
-			2:00	EU	EE%sT	2014 Mar 30 2:00
-			4:00	-	MSK
 
 # Vatican City
 # See Europe/Rome.
@@ -3018,7 +3344,7 @@
 # ...
 #
 # ...the European time rules are...standardized since 1981, when
-# most European coun[tr]ies started DST.  Before that year, only
+# most European countries started DST.  Before that year, only
 # a few countries (UK, France, Italy) had DST, each according
 # to own national rules.  In 1981, however, DST started on
 # 'Apr firstSun', and not on 'Mar lastSun' as in the following
@@ -3026,7 +3352,7 @@
 # But also since 1981 there are some more national exceptions
 # than listed in 'europe': Switzerland, for example, joined DST
 # one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
-# lastSun' in 1981---I don't know how they handle now.
+# lastSun' in 1981 - I don't know how they handle now.
 #
 # Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
 # Soviet Union (as far as I know).
--- a/jdk/test/sun/util/calendar/zi/tzdata/factory	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/factory	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/test/sun/util/calendar/zi/tzdata/iso3166.tab	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/iso3166.tab	Wed Jul 05 20:00:59 2017 +0200
@@ -26,21 +26,21 @@
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-05-27):
+# From Paul Eggert (2014-07-18):
+# This file contains a table of two-letter country codes.  Columns are
+# separated by a single tab.  Lines beginning with '#' are comments.
+# Although all text currently uses ASCII encoding, this is planned to
+# change to UTF-8 soon.  The columns of the table are as follows:
 #
-# This file contains a table with the following columns:
 # 1.  ISO 3166-1 alpha-2 country code, current as of
-#     ISO 3166-1 Newsletter VI-15 (2013-05-10).  See: Updates on ISO 3166
+#     ISO 3166-1 Newsletter VI-16 (2013-07-11).  See: Updates on ISO 3166
 #   http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
 #
-# Columns are separated by a single tab.
 # The table is sorted by country code.
 #
-# Lines beginning with `#' are comments.
-#
 # This table is intended as an aid for users, to help them select time
 # zone data appropriate for their practical needs.  It is not intended
 # to take or endorse any position on legal or territorial claims.
--- a/jdk/test/sun/util/calendar/zi/tzdata/leapseconds	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,7 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# Allowance for leapseconds added to each timezone file.
+# Allowance for leap seconds added to each time zone file.
 
 # This file is in the public domain.
 
@@ -31,7 +31,7 @@
 # you should be able to pick up leap-seconds.list from a secondary NIST server.
 # For more about leap-seconds.list, please see
 # The NTP Timescale and Leap Seconds
-# <http://www.eecis.udel.edu/~mills/leap.html>.
+# http://www.eecis.udel.edu/~mills/leap.html
 
 # The International Earth Rotation Service periodically uses leap seconds
 # to keep UTC to within 0.9 s of UT1
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # also includes Central America and the Caribbean
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (1999-03-22):
 # A reliable and entertaining source about time zones is
@@ -78,13 +78,13 @@
 #	to push people into bed earlier, and get them up earlier, to make
 #	them healthy, wealthy and wise in spite of themselves.
 #
-#	-- Robertson Davies, The diary of Samuel Marchbanks,
+#	 -- Robertson Davies, The diary of Samuel Marchbanks,
 #	   Clarke, Irwin (1947), XIX, Sunday
 #
 # For more about the first ten years of DST in the United States, see
-# Robert Garland's <a href="http://www.clpgh.org/exhibit/dst.html">
-# Ten years of daylight saving from the Pittsburgh standpoint
-# (Carnegie Library of Pittsburgh, 1927)</a>.
+# Robert Garland, Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927).
+# http://www.clpgh.org/exhibit/dst.html
 #
 # Shanks says that DST was called "War Time" in the US in 1918 and 1919.
 # However, DST was imposed by the Standard Time Act of 1918, which
@@ -103,11 +103,11 @@
 # From Arthur David Olson (2000-09-25):
 # Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
 # In the introduction, Oboler spoke of "Eastern Peace Time."
-# An AltaVista search turned up
-# <a href="http://rowayton.org/rhs/hstaug45.html">:
+# An AltaVista search turned up:
+# http://rowayton.org/rhs/hstaug45.html
 # "When the time is announced over the radio now, it is 'Eastern Peace
 # Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
-# </a> (August 1945) by way of confirmation.
+# (August 1945) by way of confirmation.
 
 # From Joseph Gallant citing
 # George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
@@ -205,7 +205,7 @@
 # USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
 # USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
 # USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
-# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
+# USA    "           9 H  BEHIND UTC    APR 3 - OCT 30
 # USA  HAWAII       10 H  BEHIND UTC
 # USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
 
@@ -258,19 +258,19 @@
 # The following was signed into law on 2005-08-08.
 #
 # H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
-#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
+#   (a) Amendment.--Section 3(a) of the Uniform Time Act of 1966 (15
 #   U.S.C. 260a(a)) is amended--
-#     (1) by striking 'first Sunday of April' and inserting 'second
-#     Sunday of March'; and
-#     (2) by striking 'last Sunday of October' and inserting 'first
+#     (1) by striking "first Sunday of April" and inserting "second
+#     Sunday of March"; and
+#     (2) by striking "last Sunday of October" and inserting "first
 #     Sunday of November'.
-#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
+#   (b) Effective Date.--Subsection (a) shall take effect 1 year after the
 #   date of enactment of this Act or March 1, 2007, whichever is later.
-#   (c) Report to Congress- Not later than 9 months after the effective
+#   (c) Report to Congress.--Not later than 9 months after the effective
 #   date stated in subsection (b), the Secretary shall report to Congress
 #   on the impact of this section on energy consumption in the United
 #   States.
-#   (d) Right to Revert- Congress retains the right to revert the
+#   (d) Right to Revert.--Congress retains the right to revert the
 #   Daylight Saving Time back to the 2005 time schedules once the
 #   Department study is complete.
 
@@ -292,7 +292,7 @@
 
 # From Paul Eggert (2005-08-26):
 # According to today's Huntsville Times
-# <http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1>
+# http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1
 # a few towns on Alabama's "eastern border with Georgia, such as Phenix City
 # in Russell County, Lanett in Chambers County and some towns in Lee County,
 # set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
@@ -347,15 +347,15 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
 			-6:00	US	C%sT	1920
-			-6:00	Chicago	C%sT	1936 Mar  1 2:00
-			-5:00	-	EST	1936 Nov 15 2:00
+			-6:00	Chicago	C%sT	1936 Mar  1  2:00
+			-5:00	-	EST	1936 Nov 15  2:00
 			-6:00	Chicago	C%sT	1942
 			-6:00	US	C%sT	1946
 			-6:00	Chicago	C%sT	1967
 			-6:00	US	C%sT
 # Oliver County, ND switched from mountain to central time on 1992-10-25.
 Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
-			-7:00	US	M%sT	1992 Oct 25 02:00
+			-7:00	US	M%sT	1992 Oct 25  2:00
 			-6:00	US	C%sT
 # Morton County, ND, switched from mountain to central time on
 # 2003-10-26, except for the area around Mandan which was already central time.
@@ -364,29 +364,26 @@
 # Jones, Mellette, and Todd Counties in South Dakota;
 # but in practice these other counties were already observing central time.
 # See <http://www.epa.gov/fedrgstr/EPA-IMPACT/2003/October/Day-28/i27056.htm>.
-Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
-			-7:00	US	M%sT	2003 Oct 26 02:00
+Zone America/North_Dakota/New_Salem -6:45:39 - LMT	1883 Nov 18 12:14:21
+			-7:00	US	M%sT	2003 Oct 26  2:00
 			-6:00	US	C%sT
 
 # From Josh Findley (2011-01-21):
 # ...it appears that Mercer County, North Dakota, changed from the
 # mountain time zone to the central time zone at the last transition from
 # daylight-saving to standard time (on Nov. 7, 2010):
-# <a href="http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm">
 # http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
-# </a>
-# <a href="http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html">
 # http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
-# </a>
 
 # From Andy Lipscomb (2011-01-24):
 # ...according to the Census Bureau, the largest city is Beulah (although
 # it's commonly referred to as Beulah-Hazen, with Hazen being the next
 # largest city in Mercer County).  Google Maps places Beulah's city hall
-# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
+# at 47 degrees 15' 51" N, 101 degrees 46' 40" W, which yields an offset
+# of 6h47'07".
 
-Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
-			-7:00	US	M%sT	2010 Nov  7 2:00
+Zone America/North_Dakota/Beulah -6:47:07 - LMT	1883 Nov 18 12:12:53
+			-7:00	US	M%sT	2010 Nov  7  2:00
 			-6:00	US	C%sT
 
 # US mountain time, represented by Denver
@@ -448,15 +445,18 @@
 # was destroyed in 1805 by a Yakutat-kon war party.)  However, there
 # were nearby inhabitants in some cases and for our purposes perhaps
 # it's best to simply use the official transition.
+
+# From Paul Eggert (2014-07-18):
+# One opinion of the early-1980s turmoil in Alaska over time zones and
+# daylight saving time appeared as graffiti on a Juneau airport wall:
+# "Welcome to Juneau.  Please turn your watch back to the 19th century."
+# See: Turner W. Alaska's four time zones now two. NY Times 1983-11-01.
+# http://www.nytimes.com/1983/11/01/us/alaska-s-four-time-zones-now-two.html
 #
-
-# From Steve Ferguson (2011-01-31):
-# The author lives in Alaska and many of the references listed are only
-# available to Alaskan residents.
-#
-# <a href="http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98">
-# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
-# </a>
+# Steve Ferguson (2011-01-31) referred to the following source:
+# Norris F. Keeping time in Alaska: national directives, local response.
+# Alaska History 2001;16(1-2).
+# http://alaskahistoricalsociety.org/discover-alaska/glimpses-of-the-past/keeping-time-in-alaska/
 
 # From Arthur David Olson (2011-02-01):
 # Here's database-relevant material from the 2001 "Alaska History" article:
@@ -482,12 +482,10 @@
 # From Arthur David Olson (2011-02-09):
 # I just spoke by phone with a staff member at the Metlakatla Indian
 # Community office (using contact information available at
-# <a href="http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla">
 # http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
-# </a>).
 # It's shortly after 1:00 here on the east coast of the United States;
 # the staffer said it was shortly after 10:00 there. When I asked whether
-# that meant they were on Pacific time, they said no--they were on their
+# that meant they were on Pacific time, they said no - they were on their
 # own time. I asked about daylight saving; they said it wasn't used. I
 # did not inquire about practices in the past.
 
@@ -501,9 +499,9 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1980 Apr 27 2:00
-			 -9:00	US	Y%sT	1980 Oct 26 2:00
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1980 Apr 27  2:00
+			 -9:00	US	Y%sT	1980 Oct 26  2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
@@ -511,7 +509,7 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
@@ -519,8 +517,8 @@
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
-			 -8:00	-	MeST
+			 -8:00	US	P%sT	1983 Oct 30  2:00
+			 -8:00	-	PST
 Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
 			 -9:18:55 -	LMT	1900 Aug 20 12:00
 			 -9:00	-	YST	1942
@@ -535,7 +533,7 @@
 			-10:00	US	CAT/CAPT 1946 # Peace
 			-10:00	-	CAT	1967 Apr
 			-10:00	-	AHST	1969
-			-10:00	US	AH%sT	1983 Oct 30 2:00
+			-10:00	US	AH%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
@@ -544,7 +542,7 @@
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
@@ -553,7 +551,7 @@
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			-10:00	US	AH%sT	1983 Nov 30
 			-10:00	US	HA%sT
 # The following switches don't quite make our 1970 cutoff.
@@ -571,7 +569,7 @@
 #  Minutes of the Unalaska City Council Meeting, January 10, 1967:
 #  "Except for St. Paul and Akutan, Unalaska is the only important
 #  location not on Alaska Standard Time.  The following resolution was
-#  made by William Robinson and seconded by Henry Swanson:  Be it
+#  made by William Robinson and seconded by Henry Swanson: Be it
 #  resolved that the City of Unalaska hereby goes to Alaska Standard
 #  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
 #  January 14, Alaska Standard Time.)  This resolution was passed with
@@ -583,9 +581,7 @@
 # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
 # of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
 # the article is available at
-# <a href="http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf">
 # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
-# </a>
 # and indicates that standard time was adopted effective noon, January
 # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
 # saving for the period between the last Sunday of each April and the
@@ -606,7 +602,7 @@
 # year, the standard time of this Territory shall be advanced one
 # hour...This Act shall take effect upon its approval. Approved this 26th
 # day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
-# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
+# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is
 # hereby repealed...This Act shall take effect upon its approval, upon
 # which date the standard time of this Territory shall be restored to
 # that existing immediately prior to the taking effect of said Act 90.
@@ -616,14 +612,14 @@
 # Note that 1933-05-21 was a Sunday.
 # We're left to guess the time of day when Act 163 was approved; guess noon.
 
-Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
-			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
-			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
-			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
-			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
-			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
+			-10:30	-	HST	1933 Apr 30  2:00
+			-10:30	1:00	HDT	1933 May 21 12:00
+			-10:30	-	HST	1942 Feb  9  2:00
+			-10:30	1:00	HDT	1945 Sep 30  2:00
+			-10:30	-	HST	1947 Jun  8  2:00
 			-10:00	-	HST
-
 Link Pacific/Honolulu Pacific/Johnston
 
 # Now we turn to US areas that have diverged from the consensus since 1970.
@@ -633,9 +629,9 @@
 # From Paul Eggert (2002-10-20):
 #
 # The information in the rest of this paragraph is derived from the
-# <a href="http://www.dlapr.lib.az.us/links/daylight.htm">
-# Daylight Saving Time web page (2002-01-23)</a> maintained by the
-# Arizona State Library, Archives and Public Records.
+# Daylight Saving Time web page
+# <http://www.dlapr.lib.az.us/links/daylight.htm> (2002-01-23)
+# maintained by the Arizona State Library, Archives and Public Records.
 # Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
 # time, but by federal law railroads, airlines, bus lines, military
 # personnel, and some engaged in interstate commerce continued to
@@ -649,10 +645,11 @@
 # Shanks says the 1944 experiment came to an end on 1944-03-17.
 # Go with the Arizona State Library instead.
 
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
-			-7:00	US	M%sT	1944 Jan  1 00:01
-			-7:00	-	MST	1944 Apr  1 00:01
-			-7:00	US	M%sT	1944 Oct  1 00:01
+			-7:00	US	M%sT	1944 Jan  1  0:01
+			-7:00	-	MST	1944 Apr  1  0:01
+			-7:00	US	M%sT	1944 Oct  1  0:01
 			-7:00	-	MST	1967
 			-7:00	US	M%sT	1968 Mar 21
 			-7:00	-	MST
@@ -676,24 +673,22 @@
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
-			-8:00	US	P%sT	1923 May 13 2:00
+			-8:00	US	P%sT	1923 May 13  2:00
 			-7:00	US	M%sT	1974
-			-7:00	-	MST	1974 Feb  3 2:00
+			-7:00	-	MST	1974 Feb  3  2:00
 			-7:00	US	M%sT
 
 # Indiana
 #
 # For a map of Indiana's time zone regions, see:
-# <a href="http://www.mccsc.edu/time.html">
-# What time is it in Indiana?
-# </a> (2006-03-01)
+# http://en.wikipedia.org/wiki/Time_in_Indiana
 #
 # From Paul Eggert (2007-08-17):
 # Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
 # with the following exceptions:
 #
 # - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
-#   Vandenburgh, and Warrick counties have been like America/Chicago.
+#   Vanderburgh, and Warrick counties have been like America/Chicago.
 #
 # - Dearborn and Ohio counties have been like America/New_York.
 #
@@ -712,22 +707,16 @@
 # that they would be ambiguous if we left them at the 'America' level.
 # So we reluctantly put them all in a subdirectory 'America/Indiana'.
 
-# From Paul Eggert (2005-08-16):
-# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
-
-# From Nathan Stratton Treadway (2006-03-30):
-# http://www.dot.gov/affairs/dot0406.htm [3705 B]
-# From Deborah Goldsmith (2006-01-18):
-# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
-# From Paul Eggert (2006-01-20):
-# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
+# From Paul Eggert (2014-06-26):
+# https://www.federalregister.gov/articles/2006/01/20/06-563/standard-time-zone-boundary-in-the-state-of-indiana
+# says "DOT is relocating the time zone boundary in Indiana to move Starke,
 # Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
 # Eastern Time Zone to the Central Time Zone.... The effective date of
-# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
+# this rule is 2 a.m. EST Sunday, April 2, 2006, which is the
 # changeover date from standard time to Daylight Saving Time."
-# Strictly speaking, this means the affected counties will change their
-# clocks twice that night, but this obviously is in error.  The intent
-# is that 01:59:59 EST be followed by 02:00:00 CDT.
+# Strictly speaking, this meant the affected counties changed their
+# clocks twice that night, but this obviously was in error.  The intent
+# was that 01:59:59 EST be followed by 02:00:00 CDT.
 
 # From Gwillim Law (2007-02-10):
 # The Associated Press has been reporting that Pulaski County, Indiana is
@@ -739,13 +728,13 @@
 Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
 Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
+Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
 			-6:00	US	C%sT	1920
 			-6:00 Indianapolis C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
-			-5:00	-	EST	1957 Sep 29 2:00
-			-6:00	-	CST	1958 Apr 27 2:00
+			-6:00 Indianapolis C%sT	1955 Apr 24  2:00
+			-5:00	-	EST	1957 Sep 29  2:00
+			-6:00	-	CST	1958 Apr 27  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
 			-5:00	-	EST	2006
@@ -761,10 +750,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
 			-6:00	US	C%sT	1951
-			-6:00	Marengo	C%sT	1961 Apr 30 2:00
+			-6:00	Marengo	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT	1976
 			-5:00	-	EST	2006
 			-5:00	US	E%sT
@@ -785,11 +774,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
 			-6:00	US	C%sT	1946
-			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
+			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Perry County, Indiana, switched from eastern to central time in April 2006.
@@ -806,10 +795,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
 			-6:00	US	C%sT	1946
-			-6:00 Perry	C%sT	1964 Apr 26 2:00
+			-6:00 Perry	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pike County, Indiana moved from central to eastern time in 1977,
@@ -822,11 +811,11 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
 			-6:00	US	C%sT	1955
-			-6:00	Pike	C%sT	1965 Apr 25 2:00
-			-5:00	-	EST	1966 Oct 30 2:00
-			-6:00	US	C%sT	1977 Oct 30 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-6:00	Pike	C%sT	1965 Apr 25  2:00
+			-5:00	-	EST	1966 Oct 30  2:00
+			-6:00	US	C%sT	1977 Oct 30  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Starke County, Indiana moved from central to eastern time in 1991,
@@ -844,10 +833,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
 			-6:00	US	C%sT	1947
-			-6:00	Starke	C%sT	1962 Apr 29 2:00
-			-5:00	-	EST	1963 Oct 27 2:00
-			-6:00	US	C%sT	1991 Oct 27 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
+			-6:00	Starke	C%sT	1962 Apr 29  2:00
+			-5:00	-	EST	1963 Oct 27  2:00
+			-6:00	US	C%sT	1991 Oct 27  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pulaski County, Indiana, switched from eastern to central time in
@@ -860,17 +849,17 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
 			-6:00	US	C%sT	1946
-			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
+			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Mar 11 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Mar 11  2:00
 			-5:00	US	E%sT
 #
 # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
-			-6:00	US	C%sT	1954 Apr 25 2:00
+			-6:00	US	C%sT	1954 Apr 25  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1973
 			-5:00	-	EST	2006
@@ -891,18 +880,17 @@
 			-6:00	US	C%sT	1921
 			-6:00 Louisville C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Louisville C%sT	1961 Jul 23 2:00
+			-6:00 Louisville C%sT	1961 Jul 23  2:00
 			-5:00	-	EST	1968
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT
 #
 # Wayne County, Kentucky
 #
-# From
-# <a href="http://www.lake-cumberland.com/life/archive/news990129time.shtml">
-# Lake Cumberland LIFE
-# </a> (1999-01-29) via WKYM-101.7:
+# From Lake Cumberland LIFE
+# http://www.lake-cumberland.com/life/archive/news990129time.shtml
+# (1999-01-29) via WKYM-101.7:
 # Clinton County has joined Wayne County in asking the DoT to change from
 # the Central to the Eastern time zone....  The Wayne County government made
 # the same request in December.  And while Russell County officials have not
@@ -919,9 +907,8 @@
 #
 # From Paul Eggert (2001-07-16):
 # The final rule was published in the
-# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22">
-# Federal Register 65, 160 (2000-08-17), page 50154-50158.
-# </a>
+# Federal Register 65, 160 (2000-08-17), pp 50154-50158.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22
 #
 Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 			-6:00	US	C%sT	1946
@@ -946,9 +933,8 @@
 # See America/North_Dakota/Center for the Oliver County, ND change.
 # West Wendover, NV officially switched from Pacific to mountain time on
 # 1999-10-31.  See the
-# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15">
-# Federal Register 64, 203 (1999-10-21), page 56705-56707.
-# </a>
+# Federal Register 64, 203 (1999-10-21), pp 56705-56707.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15
 # However, the Federal Register says that West Wendover already operated
 # on mountain time, and the rule merely made this official;
 # hence a separate tz entry is not needed.
@@ -986,12 +972,12 @@
 Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Detroit	-5:32:11 -	LMT	1905
-			-6:00	-	CST	1915 May 15 2:00
+			-6:00	-	CST	1915 May 15  2:00
 			-5:00	-	EST	1942
 			-5:00	US	E%sT	1946
 			-5:00	Detroit	E%sT	1973
 			-5:00	US	E%sT	1975
-			-5:00	-	EST	1975 Apr 27 2:00
+			-5:00	-	EST	1975 Apr 27  2:00
 			-5:00	US	E%sT
 #
 # Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
@@ -1004,8 +990,8 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 			-6:00	US	C%sT	1946
-			-6:00 Menominee	C%sT	1969 Apr 27 2:00
-			-5:00	-	EST	1973 Apr 29 2:00
+			-6:00 Menominee	C%sT	1969 Apr 27  2:00
+			-5:00	-	EST	1973 Apr 29  2:00
 			-6:00	US	C%sT
 
 # Navassa
@@ -1042,9 +1028,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	<a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
 #	William Willett, The Waste of Daylight, 19th edition
-#	</a> (1914-03)
+#	<http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	<http://www.jstor.org/stable/1774359>.
@@ -1053,11 +1039,11 @@
 
 # Canada
 
-# From Alain LaBont<e'> (1994-11-14):
+# From Alain LaBonté (1994-11-14):
 # I post here the time zone abbreviations standardized in Canada
 # for both English and French in the CAN/CSA-Z234.4-89 standard....
 #
-#	UTC	Standard time	Daylight savings time
+#	UTC	Standard time	Daylight saving time
 #	offset	French	English	French	English
 #	-2:30	-	-	HAT	NDT
 #	-3	-	-	HAA	ADT
@@ -1070,7 +1056,7 @@
 #	-9	HNY	YST	-	-
 #
 #	HN: Heure Normale	ST: Standard Time
-#	HA: Heure Avanc<e'>e	DT: Daylight saving Time
+#	HA: Heure Avancée	DT: Daylight saving Time
 #
 #	A: de l'Atlantique	Atlantic
 #	C: du Centre		Central
@@ -1085,7 +1071,7 @@
 # From Paul Eggert (1994-11-22):
 # Alas, this sort of thing must be handled by localization software.
 
-# Unless otherwise specified, the data for Canada are all from Shanks
+# Unless otherwise specified, the data entries for Canada are all from Shanks
 # & Pottenger.
 
 # From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
@@ -1134,15 +1120,15 @@
 
 # From Paul Eggert (2006-04-25):
 # H. David Matthews and Mary Vincent's map
-# <a href="http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp">
 # "It's about TIME", _Canadian Geographic_ (September-October 1998)
-# </a> contains detailed boundaries for regions observing nonstandard
+# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# contains detailed boundaries for regions observing nonstandard
 # time and daylight saving time arrangements in Canada circa 1998.
 #
-# INMS, the Institute for National Measurement Standards in Ottawa, has <a
-# href="http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php">
+# INMS, the Institute for National Measurement Standards in Ottawa, has
 # information about standard and daylight saving time zones in Canada.
-# </a> (updated periodically).
+# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
+# (updated periodically).
 # Its unofficial information is often taken from Matthews and Vincent.
 
 # From Paul Eggert (2006-06-27):
@@ -1151,9 +1137,7 @@
 
 # From Chris Walton (2011-12-01)
 # In the first of Tammy Hardwick's articles
-# <a href="http://www.ilovecreston.com/?p=articles&t=spec&ar=260">
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# </a>
 # she quotes the Friday November 1/1918 edition of the Creston Review.
 # The quote includes these two statements:
 # 'Sunday the CPR went back to the old system of time...'
@@ -1221,9 +1205,7 @@
 # Time to Standard Time and from Standard Time to Daylight Savings Time
 # now occurs at 2:00AM.
 # ...
-# <a href="http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm">
 # http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
-# </a>
 # ...
 # MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
 # Office of the Chief Information Officer
@@ -1259,7 +1241,7 @@
 			-3:30	-	NST	1936
 			-3:30	StJohns	N%sT	1942 May 11
 			-3:30	Canada	N%sT	1946
-			-3:30	StJohns	N%sT	1966 Mar 15 2:00
+			-3:30	StJohns	N%sT	1966 Mar 15  2:00
 			-4:00	StJohns	A%sT	2011 Nov
 			-4:00	Canada	A%sT
 
@@ -1320,7 +1302,7 @@
 Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
 			-4:00	Halifax	A%sT	1918
 			-4:00	Canada	A%sT	1919
-			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
+			-4:00	Halifax	A%sT	1942 Feb  9  2:00s
 			-4:00	Canada	A%sT	1946
 			-4:00	Halifax	A%sT	1974
 			-4:00	Canada	A%sT
@@ -1379,7 +1361,7 @@
 # meridian is supposed to observe AST, but residents as far east as
 # Natashquan use EST/EDT, and residents east of Natashquan use AST.
 # The Quebec department of justice writes in
-# "The situation in Minganie and Basse-Cote-Nord"
+# "The situation in Minganie and Basse-Côte-Nord"
 # http://www.justice.gouv.qc.ca/english/publications/generale/temps-minganie-a.htm
 # that the coastal strip from just east of Natashquan to Blanc-Sablon
 # observes Atlantic standard time all year round.
@@ -1387,7 +1369,6 @@
 # says this common practice was codified into law as of 2007.
 # For lack of better info, guess this practice began around 1970, contra to
 # Shanks & Pottenger who have this region observing AST/ADT.
-# for post-1970 data America/Puerto_Rico.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
@@ -1401,18 +1382,10 @@
 Rule	Mont	1924	only	-	May	17	2:00	1:00	D
 Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
 Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
-# The 1927-to-1937 rules can be expressed more simply as
-# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
-# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
-# The rules below avoid use of 24:00
-# (which pre-1998 versions of zic cannot handle).
-Rule	Mont	1927	only	-	May	1	0:00	1:00	D
-Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
-Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1932	only	-	May	1	0:00	1:00	D
-Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1933	only	-	Oct	1	0:00	0	S
-Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
+Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
+Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
+Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
+Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
 Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
 Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
@@ -1426,7 +1399,7 @@
 Zone America/Montreal	-4:54:16 -	LMT	1884
 			-5:00	Mont	E%sT	1918
 			-5:00	Canada	E%sT	1919
-			-5:00	Mont	E%sT	1942 Feb  9 2:00s
+			-5:00	Mont	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Mont	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1448,7 +1421,7 @@
 # have already done so.  In Orillia DST was to run until Saturday,
 # 1912-08-31 (no time mentioned), but it was met with considerable
 # hostility from certain segments of the public, and was revoked after
-# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
+# only two weeks - I copied it as Saturday, 1912-07-07, 22:00, but
 # presumably that should be -07-06.  (1912-06-19, -07-12; also letters
 # earlier in June).
 #
@@ -1458,10 +1431,8 @@
 # Mark Brader writes that an article in the 1997-10-14 Toronto Star
 # says that Atikokan, Ontario currently does not observe DST,
 # but will vote on 11-10 whether to use EST/EDT.
-# He also writes that the
-# <a href="http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html">
-# Ontario Time Act (1990, Chapter T.9)
-# </a>
+# He also writes that the Ontario Time Act (1990, Chapter T.9)
+# http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html
 # says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
 # Officially Atikokan is therefore on CST/CDT, and most likely this report
 # concerns a non-official time observed as a matter of local practice.
@@ -1540,9 +1511,7 @@
 # The Journal of The Royal Astronomical Society of Canada,
 # volume 26, number 2 (February 1932) and, as of 2010-07-17,
 # was available at
-# <a href="http://adsabs.harvard.edu/full/1932JRASC..26...49S">
 # http://adsabs.harvard.edu/full/1932JRASC..26...49S
-# </a>
 #
 # It includes the text below (starting on page 57):
 #
@@ -1553,26 +1522,26 @@
 # ing in 1930. The information for the province of Quebec is definite,
 # for the other provinces only approximate:
 #
-# 	Province	Daylight saving time used
+#	Province	Daylight saving time used
 # Prince Edward Island	Not used.
 # Nova Scotia		In Halifax only.
 # New Brunswick		In St. John only.
 # Quebec		In the following places:
-# 			Montreal	Lachine
-# 			Quebec		Mont-Royal
-# 			Levis		Iberville
-# 			St. Lambert	Cap de la Madeleine
-# 			Verdun		Loretteville
-# 			Westmount	Richmond
-# 			Outremont	St. Jerome
-# 			Longueuil	Greenfield Park
-# 			Arvida		Waterloo
-# 			Chambly-Canton	Beaulieu
-# 			Melbourne	La Tuque
-# 			St. Theophile	Buckingham
+#			Montreal	Lachine
+#			Quebec		Mont-Royal
+#			Lévis		Iberville
+#			St. Lambert	Cap de la Madelèine
+#			Verdun		Loretteville
+#			Westmount	Richmond
+#			Outremont	St. Jérôme
+#			Longueuil	Greenfield Park
+#			Arvida		Waterloo
+#			Chambly-Canton	Beaulieu
+#			Melbourne	La Tuque
+#			St. Théophile	Buckingham
 # Ontario		Used generally in the cities and towns along
-# 			the southerly part of the province. Not
-# 			used in the northwesterlhy part.
+#			the southerly part of the province. Not
+#			used in the northwesterly part.
 # Manitoba		Not used.
 # Saskatchewan		In Regina only.
 # Alberta		Not used.
@@ -1641,7 +1610,7 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Toronto	-5:17:32 -	LMT	1895
 			-5:00	Canada	E%sT	1919
-			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
+			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Toronto	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1654,16 +1623,16 @@
 			-5:00	Canada	E%sT
 Zone America/Nipigon	-5:53:04 -	LMT	1895
 			-5:00	Canada	E%sT	1940 Sep 29
-			-5:00	1:00	EDT	1942 Feb  9 2:00s
+			-5:00	1:00	EDT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT
 Zone America/Rainy_River -6:18:16 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
 			-6:00	Canada	C%sT
 Zone America/Atikokan	-6:06:28 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
-			-6:00	Canada	C%sT	1945 Sep 30 2:00
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
+			-6:00	Canada	C%sT	1945 Sep 30  2:00
 			-5:00	-	EST
 
 
@@ -1676,7 +1645,7 @@
 # the first Sunday of April of each year and two o'clock Central
 # Standard Time in the morning of the last Sunday of October next
 # following, one hour in advance of Central Standard Time."...
-# I believe that the English legislation [of the old time act] had =
+# I believe that the English legislation [of the old time act] had
 # been assented to (March 22, 1967)....
 # Also, as far as I can tell, there was no order-in-council varying
 # the time of Daylight Saving Time for 2005 and so the provisions of
@@ -1799,12 +1768,12 @@
 Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Regina	-6:58:36 -	LMT	1905 Sep
-			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
+			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
 			-6:00	-	CST
 Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
-			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
+			-7:00	Canada	M%sT	1946 Apr lastSun  2:00
 			-7:00	Regina	M%sT	1950
-			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
+			-7:00	Swift	M%sT	1972 Apr lastSun  2:00
 			-6:00	-	CST
 
 
@@ -1854,9 +1823,7 @@
 # Earlier this year I stumbled across a detailed article about the time
 # keeping history of Creston; it was written by Tammy Hardwick who is the
 # manager of the Creston & District Museum. The article was written in May 2009.
-# <a href="http://www.ilovecreston.com/?p=articles&t=spec&ar=260">
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# </a>
 # According to the article, Creston has not changed its clocks since June 1918.
 # i.e. Creston has been stuck on UTC-7 for 93 years.
 # Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
@@ -1864,18 +1831,16 @@
 # Unfortunately the exact date for the time change in June 1918 remains
 # unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
 # ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
-# as plausible as any other date (in June).  She also said that after writing the
-# article she had discovered another time change in 1916; this is the subject
-# of another article which she wrote in October 2010.
-# <a href="http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56">
+# as plausible as any other date (in June).  She also said that after writing
+# the article she had discovered another time change in 1916; this is the
+# subject of another article which she wrote in October 2010.
 # http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
-# </a>
 
 # Here is a summary of the three clock change events in Creston's history:
 # 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
 # Exact date unknown
 # 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
-# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
+# Exact date in October unknown; Sunday October 1 is a reasonable guess.
 # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
 # Exact date in June unknown; Sunday June 2 is a reasonable guess.
 # note#1:
@@ -1888,9 +1853,7 @@
 # There is no guarantee that Creston will remain on Mountain Standard Time
 # (UTC-7) forever.
 # The subject was debated at least once this year by the town Council.
-# <a href="http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html">
 # http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
-# </a>
 
 # During a period WWII, summer time (Daylight saying) was mandatory in Canada.
 # In Creston, that was handled by shifting the area to PST (-8:00) then applying
@@ -1917,7 +1880,7 @@
 			-8:00	Canada	P%sT
 Zone America/Dawson_Creek -8:00:56 -	LMT	1884
 			-8:00	Canada	P%sT	1947
-			-8:00	Vanc	P%sT	1972 Aug 30 2:00
+			-8:00	Vanc	P%sT	1972 Aug 30  2:00
 			-7:00	-	MST
 Zone America/Creston	-7:46:04 -	LMT	1884
 			-7:00	-	MST	1916 Oct 1
@@ -1944,18 +1907,17 @@
 
 # From Rives McDow (1999-09-04):
 # Nunavut ... moved ... to incorporate the whole territory into one time zone.
-# <a href="http://www.nunatsiaq.com/nunavut/nvt90903_13.html">
 # Nunavut moves to single time zone Oct. 31
-# </a>
+# http://www.nunatsiaq.com/nunavut/nvt90903_13.html
 #
 # From Antoine Leca (1999-09-06):
 # We then need to create a new timezone for the Kitikmeot region of Nunavut
 # to differentiate it from the Yellowknife region.
 
 # From Paul Eggert (1999-09-20):
-# <a href="http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html">
 # Basic Facts: The New Territory
-# </a> (1999) reports that Pangnirtung operates on eastern time,
+# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
+# (1999) reports that Pangnirtung operates on eastern time,
 # and that Coral Harbour does not observe DST.  We don't know when
 # Pangnirtung switched to eastern time; we'll guess 1995.
 
@@ -1983,8 +1945,8 @@
 # the current state of affairs.
 
 # From Michaela Rodrigue, writing in the
-# <a href="http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html">
-# Nunatsiaq News (1999-11-19)</a>:
+# Nunatsiaq News (1999-11-19):
+# http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html
 # Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
 # central - or Nunavut time - for government offices, and eastern time
 # for municipal offices and schools....  Igloolik [was similar but then]
@@ -2002,10 +1964,8 @@
 # Central Time and Southampton Island [in the Central zone] is not
 # required to use daylight savings.
 
-# From
-# <a href="http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html">
-# Nunavut now has two time zones
-# </a> (2000-11-10):
+# From <http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html>
+# Nunavut now has two time zones (2000-11-10):
 # The Nunavut government would allow its employees in Kugluktuk and
 # Cambridge Bay to operate on central time year-round, putting them
 # one hour behind the rest of Nunavut for six months during the winter.
@@ -2096,9 +2056,7 @@
 # used to be the mayor of Resolute Bay and he apparently owns half the
 # businesses including "South Camp Inn." This website has some info on
 # Aziz:
-# <a href="http://www.uphere.ca/node/493">
 # http://www.uphere.ca/node/493
-# </a>
 #
 # I sent Aziz an e-mail asking when Resolute Bay had stopped using
 # Eastern Standard Time.
@@ -2136,47 +2094,47 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
 Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
-			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
-			-5:00	Canada	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
+			-5:00	Canada	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
 Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
-			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
 Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
-			-6:00	Canada	C%sT	2006 Oct 29 2:00
-			-5:00	-	EST	2007 Mar 11 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
+			-6:00	Canada	C%sT	2006 Oct 29  2:00
+			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
 Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
 Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
-			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2000 Nov  5 0:00
-			-6:00	-	CST	2001 Apr  1 3:00
+			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2000 Nov  5  0:00
+			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
 Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
-			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
+			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
+			-9:00	NT_YK	Y%sT	1966 Jul  1  2:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
+			-9:00	NT_YK	Y%sT	1973 Oct 28  0:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 
@@ -2188,9 +2146,8 @@
 # From Paul Eggert (2001-03-05):
 # The Investigation and Analysis Service of the
 # Mexican Library of Congress (MLoC) has published a
-# <a href="http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/">
 # history of Mexican local time (in Spanish)
-# </a>.
+# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
 #
 # Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
 # (In all cases we go with the MLoC.)
@@ -2235,9 +2192,8 @@
 # -------------- End Forwarded Message --------------
 # From Paul Eggert (1996-06-12):
 # For an English translation of the decree, see
-# <a href="http://mexico-travel.com/extra/timezone_eng.html">
 # "Diario Oficial: Time Zone Changeover" (1996-01-04).
-# </a>
+# http://mexico-travel.com/extra/timezone_eng.html
 
 # From Rives McDow (1998-10-08):
 # The State of Quintana Roo has reverted back to central STD and DST times
@@ -2249,7 +2205,7 @@
 # savings time so as to stay on the same time zone as the southern part of
 # Arizona year round.
 
-# From Jesper Norgaard, translating
+# From Jesper Nørgaard, translating
 # <http://www.reforma.com/nacional/articulo/064327/> (2001-01-17):
 # In Oaxaca, the 55.000 teachers from the Section 22 of the National
 # Syndicate of Education Workers, refuse to apply daylight saving each
@@ -2262,7 +2218,7 @@
 # January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
 # that Summer Time will be reduced from seven to five months, starting
 # this year....
-# <http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001>
+# http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001
 # [translated], says "summer time will ... take effect on the first Sunday
 # in May, and end on the last Sunday of September.
 
@@ -2270,23 +2226,22 @@
 # The 2001-01-24 traditional Washington Post contained the page one
 # story "Timely Issue Divides Mexicans."...
 # http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
-# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# ... Mexico City Mayor López Obrador "...is threatening to keep
 # Mexico City and its 20 million residents on a different time than
-# the rest of the country..." In particular, Lopez Obrador would abolish
+# the rest of the country..." In particular, López Obrador would abolish
 # observation of Daylight Saving Time.
 
-# <a href="http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre">
 # Official statute published by the Energy Department
-# </a> (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
-# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
+# http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre
+# (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST.  This was reported by Jesper Nørgaard (2001-02-03).
 
 # From Paul Eggert (2001-03-03):
 #
-# <a href="http://www.latimes.com/news/nation/20010303/t000018766.html">
+# http://www.latimes.com/news/nation/20010303/t000018766.html
 # James F. Smith writes in today's LA Times
-# </a>
 # * Sonora will continue to observe standard time.
-# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
 #   the Federal District will not adopt DST.
 # * 4 of 16 district leaders announced they'll ignore the decree.
 # * The decree does not affect federal-controlled facilities including
@@ -2294,7 +2249,7 @@
 #
 # For now we'll assume that the Federal District will bow to federal rules.
 
-# From Jesper Norgaard (2001-04-01):
+# From Jesper Nørgaard (2001-04-01):
 # I found some references to the Mexican application of daylight
 # saving, which modifies what I had already sent you, stating earlier
 # that a number of northern Mexican states would go on daylight
@@ -2303,7 +2258,7 @@
 # saving all year) will follow the original decree of president
 # Vicente Fox, starting daylight saving May 6, 2001 and ending
 # September 30, 2001.
-# References: "Diario de Monterrey" <www.diariodemonterrey.com/index.asp>
+# References: "Diario de Monterrey" <http://www.diariodemonterrey.com/index.asp>
 # Palabra <http://palabra.infosel.com/010331/primera/ppri3101.pdf> (2001-03-31)
 
 # From Reuters (2001-09-04):
@@ -2315,7 +2270,7 @@
 # standard time. "This is so residents of the Federal District are not
 # subject to unexpected time changes," a statement from the court said.
 
-# From Jesper Norgaard Welen (2002-03-12):
+# From Jesper Nørgaard Welen (2002-03-12):
 # ... consulting my local grocery store(!) and my coworkers, they all insisted
 # that a new decision had been made to reinstate US style DST in Mexico....
 # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
@@ -2329,48 +2284,36 @@
 # > the United States.
 # Now this has passed both the Congress and the Senate, so starting from
 # 2010, some border regions will be the same:
-# <a href="http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/">
 # http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
-# </a>
-# <a href="http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939">
 # http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
-# </a>
 # (Spanish)
 #
 # Could not find the new law text, but the proposed law text changes are here:
-# <a href="http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf">
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
-# </a>
 # (Gaceta Parlamentaria)
 #
 # There is also a list of the votes here:
-# <a href="http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html">
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
-# </a>
 #
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/north-mexico-dst-change.html">
 # http://www.timeanddate.com/news/time/north-mexico-dst-change.html
-# </a>
 
 # From Arthur David Olson (2010-01-20):
 # The page
-# <a href="http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010">
 # http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
-# </a>
 # includes this text:
 # En los municipios fronterizos de Tijuana y Mexicali en Baja California;
-# Ju&aacute;rez y Ojinaga en Chihuahua; Acu&ntilde;a y Piedras Negras en Coahuila;
-# An&aacute;huac en Nuevo Le&oacute;n; y Nuevo Laredo, Reynosa y Matamoros en
-# Tamaulipas, la aplicaci&oacute;n de este horario estacional surtir&aacute; efecto
-# desde las dos horas del segundo domingo de marzo y concluir&aacute; a las dos
+# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
+# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
+# Tamaulipas, la aplicación de este horario estacional surtirá efecto
+# desde las dos horas del segundo domingo de marzo y concluirá a las dos
 # horas del primer domingo de noviembre.
 # En los municipios fronterizos que se encuentren ubicados en la franja
-# fronteriza norte en el territorio comprendido entre la l&iacute;nea
-# internacional y la l&iacute;nea paralela ubicada a una distancia de veinte
-# kil&oacute;metros, as&iacute; como la Ciudad de Ensenada, Baja California, hacia el
-# interior del pa&iacute;s, la aplicaci&oacute;n de este horario estacional surtir&aacute;
-# efecto desde las dos horas del segundo domingo de marzo y concluir&aacute; a
+# fronteriza norte en el territorio comprendido entre la línea
+# internacional y la línea paralela ubicada a una distancia de veinte
+# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
+# interior del país, la aplicación de este horario estacional surtirá
+# efecto desde las dos horas del segundo domingo de marzo y concluirá a
 # las dos horas del primer domingo de noviembre.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -2389,39 +2332,39 @@
 Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
 Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Quintana Roo
+# Quintana Roo; represented by Cancún
 Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
 			-6:00	-	CST	1981 Dec 23
 			-5:00	Mexico	E%sT	1998 Aug  2  2:00
 			-6:00	Mexico	C%sT
-# Campeche, Yucatan
+# Campeche, Yucatán; represented by Mérida
 Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
 			-6:00	-	CST	1981 Dec 23
 			-5:00	-	EST	1982 Dec  2
 			-6:00	Mexico	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (near US border)
 Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT	2010
 			-6:00	US	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (away from US border)
 Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT
 # Central Mexico
-Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
+Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1  0:23:24
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
 			-6:00	-	CST	1931 Oct
 			-7:00	-	MST	1932 Apr  1
-			-6:00	Mexico	C%sT	2001 Sep 30 02:00
+			-6:00	Mexico	C%sT	2001 Sep 30  2:00
 			-6:00	-	CST	2002 Feb 20
 			-6:00	Mexico	C%sT
 # Chihuahua (near US border)
-Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
+Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan  1  0:02:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
@@ -2429,7 +2372,7 @@
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT	2010
 			-7:00	US	M%sT
 # Chihuahua (away from US border)
@@ -2441,7 +2384,7 @@
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT
 # Sonora
 Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
@@ -2457,42 +2400,33 @@
 			-7:00	-	MST
 
 # From Alexander Krivenyshev (2010-04-21):
-# According to news, Bah&iacute;a de Banderas (Mexican state of Nayarit)
+# According to news, Bahía de Banderas (Mexican state of Nayarit)
 # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
 # share the same time zone as nearby city Puerto Vallarta, Jalisco).
 #
 # (Spanish)
-# Bah&iacute;a de Banderas homologa su horario al del centro del
-# pa&iacute;s, a partir de este domingo
-# <a href="http://www.nayarit.gob.mx/notes.asp?id=20748">
+# Bahía de Banderas homologa su horario al del centro del
+# país, a partir de este domingo
 # http://www.nayarit.gob.mx/notes.asp?id=20748
-# </a>
 #
-# Bah&iacute;a de Banderas homologa su horario con el del Centro del
-# Pa&iacute;s
-# <a href="http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50">
-# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
-# </a>
+# Bahía de Banderas homologa su horario con el del Centro del
+# País
+# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50
 #
 # (English)
-# Puerto Vallarta and Bah&iacute;a de Banderas: One Time Zone
-# <a href="http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml">
+# Puerto Vallarta and Bahía de Banderas: One Time Zone
 # http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
-# </a>
-#
-# or
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_mexico08.html">
 # http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
-# </a>
 #
 # "Mexico's Senate approved the amendments to the Mexican Schedule System that
-# will allow Bah&iacute;a de Banderas and Puerto Vallarta to share the same time
+# will allow Bahía de Banderas and Puerto Vallarta to share the same time
 # zone ..."
 # Baja California Sur, Nayarit, Sinaloa
 
 # From Arthur David Olson (2010-05-01):
 # Use "Bahia_Banderas" to keep the name to fourteen characters.
 
+# Mazatlán
 Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2504,6 +2438,7 @@
 			-8:00	-	PST	1970
 			-7:00	Mexico	M%sT
 
+# Bahía de Banderas
 Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2513,7 +2448,7 @@
 			-6:00	-	CST	1942 Apr 24
 			-7:00	-	MST	1949 Jan 14
 			-8:00	-	PST	1970
-			-7:00	Mexico	M%sT	2010 Apr 4 2:00
+			-7:00	Mexico	M%sT	2010 Apr  4  2:00
 			-6:00	Mexico	C%sT
 
 # Baja California (near US border)
@@ -2560,7 +2495,7 @@
 # America/Tijuana only in that it did not observe DST from 1976
 # through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
 # Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
-# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# that the 1987 OAG says "Only Ensenada, Mexicali, San Felipe and
 # Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
 # DST-observance was a town-by-town matter back then.  This concerns
 # data after 1970 so most likely there should be at least one Zone
@@ -2573,7 +2508,7 @@
 ###############################################################################
 
 # Anguilla
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Antigua and Barbuda
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2609,8 +2544,8 @@
 Rule	Barb	1979	only	-	Sep	30	2:00	0	S
 Rule	Barb	1980	only	-	Sep	25	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Barbados	-3:58:29 -	LMT	1924		# Bridgetown
-			-3:58:29 -	BMT	1932	  # Bridgetown Mean Time
+Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
+			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
 			-4:00	Barb	A%sT
 
 # Belize
@@ -2640,20 +2575,20 @@
 # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1 2:00    # Hamilton
-			-4:00	-	AST	1974 Apr 28 2:00
+Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
+			-4:00	-	AST	1974 Apr 28  2:00
 			-4:00	Canada	A%sT	1976
 			-4:00	US	A%sT
 
 # Cayman Is
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
+Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
 			-5:00	-	EST
 
 # Costa Rica
 
-# Milne gives -5:36:13.3 as San Jose mean time; round to nearest.
+# Milne gives -5:36:13.3 as San José mean time; round to nearest.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
@@ -2663,10 +2598,10 @@
 # go with Shanks & Pottenger.
 Rule	CR	1991	only	-	Jul	 1	0:00	0	S
 Rule	CR	1992	only	-	Mar	15	0:00	0	S
-# There are too many San Joses elsewhere, so we'll use 'Costa Rica'.
+# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
-			-5:36:13 -	SJMT	1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
+			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
 			-6:00	CR	C%sT
 # Coco
 # no information; probably like America/Costa_Rica
@@ -2685,8 +2620,8 @@
 # During the game, play-by-play announcer Jim Hunter noted that
 # "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
 # Time today."  (The "two hour" remark referred to losing one hour of
-# sleep on 1999-03-28--when the announcers were in Cuba as it switched
-# to DST--and one more hour on 1999-04-04--when the announcers will have
+# sleep on 1999-03-28 - when the announcers were in Cuba as it switched
+# to DST - and one more hour on 1999-04-04 - when the announcers will have
 # returned to Baltimore, which switches on that date.)
 
 # From Steffen Thorsen (2013-11-11):
@@ -2708,16 +2643,16 @@
 # adjustment in Cuba.  We will stay in daylight saving time:
 # http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
 
-# From Jesper Norgaard Welen (2006-10-21):
+# From Jesper Nørgaard Welen (2006-10-21):
 # An article in GRANMA INTERNACIONAL claims that Cuba will end
 # the 3 years of permanent DST next weekend, see
 # http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
 # "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
-# watches should be set back one hour -- going back to 00:00 hours -- returning
+# watches should be set back one hour - going back to 00:00 hours - returning
 # to the normal schedule....
 
 # From Paul Eggert (2007-03-02):
-# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
+# <http://www.granma.cubaweb.cu/english/news/art89.html>, dated yesterday,
 # says Cuban clocks will advance at midnight on March 10.
 # For lack of better information, assume Cuba will use US rules,
 # except that it switches at midnight standard time as usual.
@@ -2731,10 +2666,10 @@
 # http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
 # http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
 #
-# From Alex Kryvenishev (2007-10-25):
+# From Alex Krivenyshev (2007-10-25):
 # Here is also article from Granma (Cuba):
 #
-# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
+# Regirá el Horario Normal desde el próximo domingo 28 de octubre
 # http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
 #
 # http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
@@ -2742,23 +2677,18 @@
 # From Arthur David Olson (2008-03-09):
 # I'm in Maryland which is now observing United States Eastern Daylight
 # Time. At 9:44 local time I used RealPlayer to listen to
-# <a href="http://media.enet.cu/radioreloj">
 # http://media.enet.cu/radioreloj
-# </a>, a Cuban information station, and heard
+# a Cuban information station, and heard
 # the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
 # indicating that Cuba is still on standard time.
 
 # From Steffen Thorsen (2008-03-12):
 # It seems that Cuba will start DST on Sunday, 2007-03-16...
 # It was announced yesterday, according to this source (in Spanish):
-# <a href="http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm">
 # http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
-# </a>
 #
 # Some more background information is posted here:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
-# </a>
 #
 # The article also says that Cuba has been observing DST since 1963,
 # while Shanks (and tzdata) has 1965 as the first date (except in the
@@ -2768,18 +2698,14 @@
 # change some historic records as well.
 #
 # One example:
-# <a href="http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm">
 # http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
-# </a>
 
-# From Jesper Norgaard Welen (2008-03-13):
+# From Jesper Nørgaard Welen (2008-03-13):
 # The Cuban time change has just been confirmed on the most authoritative
 # web site, the Granma.  Please check out
-# <a href="http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html">
 # http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
-# </a>
 #
-# Basically as expected after Steffen Thorsens information, the change
+# Basically as expected after Steffen Thorsen's information, the change
 # will take place midnight between Saturday and Sunday.
 
 # From Arthur David Olson (2008-03-12):
@@ -2790,18 +2716,14 @@
 # midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
 # not on midnight March 14 / March 15 as previously thought.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_cuba05.html">
 # http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
 # (in Spanish)
-# </a>
 
 # From Arthur David Olson (2009-03-09)
 # I listened over the Internet to
-# <a href="http://media.enet.cu/readioreloj">
 # http://media.enet.cu/readioreloj
-# </a>
 # this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
-# the time was announced as "diez cinco"--the same time as here, indicating
+# the time was announced as "diez cinco" - the same time as here, indicating
 # that has indeed switched to DST. Assume second Sunday from 2009 forward.
 
 # From Steffen Thorsen (2011-03-08):
@@ -2810,42 +2732,30 @@
 # changed at all).
 #
 # Source:
-# <a href="http://granma.co.cu/2011/03/08/nacional/artic01.html">
 # http://granma.co.cu/2011/03/08/nacional/artic01.html
-# </a>
 #
 # Our info:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
-# </a>
 #
 # From Steffen Thorsen (2011-10-30)
 # Cuba will end DST two weeks later this year. Instead of going back
 # tonight, it has been delayed to 2011-11-13 at 01:00.
 #
 # One source (Spanish)
-# <a href="http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html">
 # http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
-# </a>
 #
 # Our page:
-# <a href="http://www.timeanddate.com/news/time/cuba-time-changes-2011.html">
 # http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
-# </a>
 #
 # From Steffen Thorsen (2012-03-01)
 # According to Radio Reloj, Cuba will start DST on Midnight between March
 # 31 and April 1.
 #
 # Radio Reloj has the following info (Spanish):
-# <a href="http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril">
 # http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
-# </a>
 #
 # Our info on it:
-# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html">
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
-# </a>
 
 # From Steffen Thorsen (2012-11-03):
 # Radio Reloj and many other sources report that Cuba is changing back
@@ -2901,7 +2811,7 @@
 			-5:00	Cuba	C%sT
 
 # Dominica
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Dominican Republic
 
@@ -2934,8 +2844,8 @@
 Zone America/Santo_Domingo -4:39:36 -	LMT	1890
 			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
 			-5:00	DR	E%sT	1974 Oct 27
-			-4:00	-	AST	2000 Oct 29 02:00
-			-5:00	US	E%sT	2000 Dec  3 01:00
+			-4:00	-	AST	2000 Oct 29  2:00
+			-5:00	US	E%sT	2000 Dec  3  1:00
 			-4:00	-	AST
 
 # El Salvador
@@ -2946,20 +2856,20 @@
 # There are too many San Salvadors elsewhere, so use America/El_Salvador
 # instead of America/San_Salvador.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
+Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
 			-6:00	Salv	C%sT
 
 # Grenada
 # Guadeloupe
-# St Barthelemy
+# St Barthélemy
 # St Martin (French part)
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Guatemala
 #
 # From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
 # Diario Co Latino, at
-# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
+# <http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079>,
 # says in an article dated 2006-04-19 that the Guatemalan government had
 # decided on that date to advance official time by 60 minutes, to lessen the
 # impact of the elevated cost of oil....  Daylight saving time will last from
@@ -2967,7 +2877,7 @@
 # From Paul Eggert (2006-06-22):
 # The Ministry of Energy and Mines, press release CP-15/2006
 # (2006-04-19), says DST ends at 24:00.  See
-# <http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf>.
+# http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
@@ -2984,11 +2894,10 @@
 
 # Haiti
 # From Gwillim Law (2005-04-15):
-# Risto O. Nykanen wrote me that Haiti is now on DST.
-# I searched for confirmation, and I found a
-# <a href="http://www.haitianconsulate.org/time.doc"> press release
+# Risto O. Nykänen wrote me that Haiti is now on DST.
+# I searched for confirmation, and I found a press release
 # on the Web page of the Haitian Consulate in Chicago (2005-03-31),
-# </a>.  Translated from French, it says:
+# <http://www.haitianconsulate.org/time.doc>.  Translated from French, it says:
 #
 #  "The Prime Minister's Communication Office notifies the public in general
 #   and the press in particular that, following a decision of the Interior
@@ -3065,14 +2974,14 @@
 # <http://www.latribuna.hn/99299.html> that Manuel Zelaya, the president
 # of Honduras, refused to back down on this.
 
-# From Jesper Norgaard Welen (2006-08-08):
+# From Jesper Nørgaard Welen (2006-08-08):
 # It seems that Honduras has returned from DST to standard time this Monday at
 # 00:00 hours (prolonging Sunday to 25 hours duration).
 # http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
 
 # From Paul Eggert (2006-08-08):
-# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
-# <http://www.elheraldo.hn/nota.php?nid=54941&sec=12>.
+# Also see Diario El Heraldo, The country returns to standard time (2006-08-08).
+# http://www.elheraldo.hn/nota.php?nid=54941&sec=12
 # It mentions executive decree 18-2006.
 
 # From Steffen Thorsen (2006-08-17):
@@ -3100,22 +3009,22 @@
 # unspecified official document, and says "This time is used throughout the
 # island".  Go with Milne.  Round to the nearest second as required by zic.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Jamaica	-5:07:11 -	LMT	1890		# Kingston
+Zone	America/Jamaica	-5:07:11 -	LMT	1890        # Kingston
 			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	-	EST	1974 Apr 28 2:00
+			-5:00	-	EST	1974 Apr 28  2:00
 			-5:00	US	E%sT	1984
 			-5:00	-	EST
 
 # Martinique
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
-			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
+Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
+			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
 			-4:00	-	AST	1980 Apr  6
 			-4:00	1:00	ADT	1980 Sep 28
 			-4:00	-	AST
 
 # Montserrat
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Nicaragua
 #
@@ -3138,27 +3047,27 @@
 # From Gwillim Law (2005-04-21):
 # The Associated Press story on the time change, which can be found at
 # http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
-# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
+# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
 # time that a change of clocks was applied to save energy was in the year 2000
-# during the Arnoldo Aleman administration."...
+# during the Arnoldo Alemán administration."...
 # The northamerica file says that Nicaragua has been on UTC-6 continuously
 # since December 1998.  I wasn't able to find any details of Nicaraguan time
 # changes in 2000.  Perhaps a note could be added to the northamerica file, to
 # the effect that we have indirect evidence that DST was observed in 2000.
 #
-# From Jesper Norgaard Welen (2005-11-02):
+# From Jesper Nørgaard Welen (2005-11-02):
 # Nicaragua left DST the 2005-10-02 at 00:00 (local time).
 # http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
 # (2005-09-26)
 #
-# From Jesper Norgaard Welen (2006-05-05):
+# From Jesper Nørgaard Welen (2006-05-05):
 # http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
 # (my informal translation)
-# By order of the president of the republic, Enrique Bolanos, Nicaragua
+# By order of the president of the republic, Enrique Bolaños, Nicaragua
 # advanced by sixty minutes their official time, yesterday at 2 in the
-# morning, and will stay that way until 30.th. of september.
+# morning, and will stay that way until 30th of September.
 #
-# From Jesper Norgaard Welen (2006-09-30):
+# From Jesper Nørgaard Welen (2006-09-30):
 # http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
 # My informal translation runs:
 # The natural sun time is restored in all the national territory, in that the
@@ -3176,7 +3085,7 @@
 			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
 			-6:00	-	CST	1973 May
 			-5:00	-	EST	1975 Feb 16
-			-6:00	Nic	C%sT	1992 Jan  1 4:00
+			-6:00	Nic	C%sT	1992 Jan  1  4:00
 			-5:00	-	EST	1992 Sep 24
 			-6:00	-	CST	1993
 			-5:00	-	EST	1997
@@ -3185,36 +3094,36 @@
 # Panama
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Panama	-5:18:08 -	LMT	1890
-			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
+			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
 			-5:00	-	EST
 
 # Puerto Rico
 # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
+Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
 			-4:00	-	AST	1942 May  3
 			-4:00	US	A%sT	1946
 			-4:00	-	AST
 
 # St Kitts-Nevis
 # St Lucia
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # St Pierre and Miquelon
 # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
+Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
 			-4:00	-	AST	1980 May
 			-3:00	-	PMST	1987 # Pierre & Miquelon Time
 			-3:00	Canada	PM%sT
 
 # St Vincent and the Grenadines
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Turks and Caicos
 #
 # From Chris Dunn in
-# <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007>
+# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007
 # (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
 # daylight saving dates for time changes have been adjusted to match
 # the recent U.S. change of dates.
@@ -3227,21 +3136,23 @@
 # Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
 # indicating that the normal ET rules are followed.
 #
-# From Paul Eggert (2006-05-01):
-# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
-# says they switch at midnight.  Go with Shanks & Pottenger.
+# From Paul Eggert (2014-08-19):
+# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
+# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
+# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
 #
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
-Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
-Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
-Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
-Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Grand_Turk	-4:44:32 -	LMT	1890
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	TC	E%sT
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
+			-5:00	-	EST	1979
+			-5:00	US	E%sT	2014 Nov  2  2:00
+			-4:00	-	AST
 
 # British Virgin Is
 # Virgin Is
-# See 'southamerica'.
+# See America/Port_of_Spain.
+
+
+# Local Variables:
+# coding: utf-8
+# End:
--- a/jdk/test/sun/util/calendar/zi/tzdata/pacificnew	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/pacificnew	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/test/sun/util/calendar/zi/tzdata/southamerica	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica	Wed Jul 05 20:00:59 2017 +0200
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2006-03-22):
 # A good source for time zone historical data outside the U.S. is
@@ -35,8 +35,8 @@
 # San Diego: ACS Publications, Inc. (2003).
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <http://www.jstor.org/stable/1774359>.
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # Gwillim Law writes that a good source
 # for recent time zone data is the International Air Transport
@@ -53,24 +53,24 @@
 #	I suggest the use of _Summer time_ instead of the more cumbersome
 #	_daylight-saving time_.  _Summer time_ seems to be in general use
 #	in Europe and South America.
-#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
+#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
 #	H L Mencken, _The American Language: Supplement I_ (1960), p 466
 #
 # Earlier editions of these tables also used the North American style
 # for time zones in Brazil, but this was incorrect, as Brazilians say
-# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
+# "summer time".  Reinaldo Goulart, a São Paulo businessman active in
 # the railroad sector, writes (1999-07-06):
 #	The subject of time zones is currently a matter of discussion/debate in
-#	Brazil.  Let's say that "the Brasilia time" is considered the
-#	"official time" because Brasilia is the capital city.
-#	The other three time zones are called "Brasilia time "minus one" or
+#	Brazil.  Let's say that "the Brasília time" is considered the
+#	"official time" because Brasília is the capital city.
+#	The other three time zones are called "Brasília time "minus one" or
 #	"plus one" or "plus two".  As far as I know there is no such
 #	name/designation as "Eastern Time" or "Central Time".
 # So I invented the following (English-language) abbreviations for now.
 # Corrections are welcome!
 #		std	dst
 #	-2:00	FNT	FNST	Fernando de Noronha
-#	-3:00	BRT	BRST	Brasilia
+#	-3:00	BRT	BRST	Brasília
 #	-4:00	AMT	AMST	Amazon
 #	-5:00	ACT	ACST	Acre
 
@@ -84,7 +84,7 @@
 # Argentina: first Sunday in October to first Sunday in April since 1976.
 # Double Summer time from 1969 to 1974.  Switches at midnight.
 
-# From U. S. Naval Observatory (1988-01-199):
+# From U. S. Naval Observatory (1988-01-19):
 # ARGENTINA           3 H BEHIND   UTC
 
 # From Hernan G. Otero (1995-06-26):
@@ -118,7 +118,7 @@
 # From Hernan G. Otero (1995-06-26):
 # These corrections were contributed by InterSoft Argentina S.A.,
 # obtaining the data from the:
-# Talleres de Hidrografia Naval Argentina
+# Talleres de Hidrografía Naval Argentina
 # (Argentine Naval Hydrography Institute)
 Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
 Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
@@ -140,13 +140,13 @@
 Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 #
 # From Peter Gradelski via Steffen Thorsen (2000-03-01):
-# We just checked with our Sao Paulo office and they say the government of
+# We just checked with our São Paulo office and they say the government of
 # Argentina decided not to become one of the countries that go on or off DST.
 # So Buenos Aires should be -3 hours from GMT at all times.
 #
-# From Fabian L. Arce Jofre (2000-04-04):
+# From Fabián L. Arce Jofré (2000-04-04):
 # The law that claimed DST for Argentina was derogated by President Fernando
-# de la Rua on March 2, 2000, because it would make people spend more energy
+# de la Rúa on March 2, 2000, because it would make people spend more energy
 # in the winter time, rather than less.  The change took effect on March 3.
 #
 # From Mariano Absatz (2001-06-06):
@@ -179,15 +179,13 @@
 # that Argentina will use DST next year as well, from October to
 # March, although exact rules are not given.
 #
-# From Jesper Norgaard Welen (2007-12-26)
+# From Jesper Nørgaard Welen (2007-12-26)
 # The last hurdle of Argentina DST is over, the proposal was approved in
-# the lower chamber too (Deputados) with a vote 192 for and 2 against.
+# the lower chamber too (Diputados) with a vote 192 for and 2 against.
 # By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
 # the original scanned proposal, where the dates and the zero hours are
 # clear and unambiguous...This is the article about final approval:
-# <a href="http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996">
 # http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
-# </a>
 #
 # From Paul Eggert (2007-12-22):
 # For dates after mid-2008, the following rules are my guesses and
@@ -197,13 +195,8 @@
 # As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
 # Argentina will start DST on Sunday October 19, 2008.
 #
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_argentina03.html">
 # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
-# </a>
-# OR
-# <a href="http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)">
 # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# </a>
 
 # From Rodrigo Severo (2008-10-06):
 # Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
@@ -212,48 +205,39 @@
 # Hi, there is a problem with timezone-data-2008e and maybe with
 # timezone-data-2008f
 # Argentinian law [Number] 25.155 is no longer valid.
-# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm">
 # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# </a>
 # The new one is law [Number] 26.350
-# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm">
 # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
-# </a>
 # So there is no summer time in Argentina for now.
 
 # From Mariano Absatz (2008-10-20):
-# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
-# From 2008-10-19 until 2009-03-15
-# <a href="http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01">
+# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST
+# in Argentina from 2008-10-19 until 2009-03-15.
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
-# </a>
 #
-# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
-# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
-# and Tierra del Fuego
-# <a href="http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01">
+
+# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer
+# 2008/2009: Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La
+# Pampa, Neuquén, Rio Negro, Chubut, Santa Cruz and Tierra del Fuego
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
-# </a>
 #
-# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
-# it will not apply DST either (even when it was not included in Decree 1705/2008)
-# <a href="http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc">
+# Press release 235 dated Saturday October 18th, from the Government of the
+# Province of Jujuy saying it will not apply DST either (even when it was not
+# included in Decree 1705/2008).
 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
-# </a>
 
 # From fullinet (2009-10-18):
 # As announced in
-# <a hef="http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356">
 # http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
-# </a>
-# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
+# (an official .gob.ar) under title: "Sin Cambio de Hora"
+# (English: "No hour change").
 #
-# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
-# oficial, decision que estaba en estudio para su implementacion el
-# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
-# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
-# la modificacion del huso horario, ya que 2009 nos encuentra con
-# crecimiento en la produccion y distribucion energetica."
+# "Por el momento, el Gobierno Nacional resolvió no modificar la hora
+# oficial, decisión que estaba en estudio para su implementación el
+# domingo 18 de octubre. Desde el Ministerio de Planificación se anunció
+# que la Argentina hoy, en estas condiciones meteorológicas, no necesita
+# la modificación del huso horario, ya que 2009 nos encuentra con
+# crecimiento en la producción y distribución energética."
 
 Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
 Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
@@ -267,10 +251,10 @@
 # It's Law No. 7,210.  This change is due to a public power emergency, so for
 # now we'll assume it's for this year only.
 #
-# From Paul Eggert (2006-03-22):
-# <a href="http://www.spicasc.net/horvera.html">
-# Hora de verano para la Republica Argentina (2003-06-08)
-# </a> says that standard time in Argentina from 1894-10-31
+# From Paul Eggert (2014-08-09):
+# Hora de verano para la República Argentina
+# http://buenasiembra.com.ar/esoterismo/astrologia/hora-de-verano-de-la-republica-argentina-27.html
+# says that standard time in Argentina from 1894-10-31
 # to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
 # over Shanks & Pottenger.
 #
@@ -285,10 +269,10 @@
 # time in October 17th.
 #
 # Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
-# Tierra del Fuego, Tucuman.
+# Tierra del Fuego, Tucumán.
 #
 # From Mariano Absatz (2004-06-14):
-# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
+# ... this weekend, the Province of Tucumán decided it'd go back to UTC-03:00
 # yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
 # annoyance with the change is much higher than the power savings obtained....
 #
@@ -323,49 +307,38 @@
 # Here are articles that Argentina Province San Luis is planning to end DST
 # as earlier as upcoming Monday January 21, 2008 or February 2008:
 #
-# Provincia argentina retrasa reloj y marca diferencia con resto del pais
+# Provincia argentina retrasa reloj y marca diferencia con resto del país
 # (Argentine Province delayed clock and mark difference with the rest of the
 # country)
-# <a href="http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel">
 # http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
-# </a>
 #
 # Es inminente que en San Luis atrasen una hora los relojes
 # (It is imminent in San Luis clocks one hour delay)
-# <a href="http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414">
-# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
-# </a>
-#
-# <a href="http://www.worldtimezone.net/dst_news/dst_news_argentina02.html">
+# http://www.lagaceta.com.ar/nota/253414/Economia/Es-inminente-que-en-San-Luis-atrasen-una-hora-los-relojes.html
 # http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
-# </a>
 
-# From Jesper Norgaard Welen (2008-01-18):
+# From Jesper Nørgaard Welen (2008-01-18):
 # The page of the San Luis provincial government
-# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812">
 # http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
-# </a>
 # confirms what Alex Krivenyshev has earlier sent to the tz
 # emailing list about that San Luis plans to return to standard
 # time much earlier than the rest of the country. It also
 # confirms that upon request the provinces San Juan and Mendoza
 # refused to follow San Luis in this change.
 #
-# The change is supposed to take place Monday the 21.st at 0:00
+# The change is supposed to take place Monday the 21st at 0:00
 # hours. As far as I understand it if this goes ahead, we need
 # a new timezone for San Luis (although there are also documented
 # independent changes in the southamerica file of San Luis in
 # 1990 and 1991 which has not been confirmed).
 
-# From Jesper Norgaard Welen (2008-01-25):
+# From Jesper Nørgaard Welen (2008-01-25):
 # Unfortunately the below page has become defunct, about the San Luis
 # time change. Perhaps because it now is part of a group of pages "Most
 # important pages of 2008."
 #
 # You can use
-# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834">
 # http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
-# </a>
 # instead it seems. Or use "Buscador" from the main page of the San Luis
 # government, and fill in "huso" and click OK, and you will get 3 pages
 # from which the first one is identical to the above.
@@ -385,9 +358,9 @@
 # back in 2004, when these provinces changed to UTC-4 for a few days, I
 # mailed them personally and never got an answer).
 
-# From Paul Eggert (2008-06-30):
-# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
-# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
+# From Paul Eggert (2014-08-12):
+# Unless otherwise specified, data entries are from Shanks & Pottenger through
+# 1992, from the IATA otherwise.  As noted below, Shanks & Pottenger say that
 # America/Cordoba split into 6 subregions during 1991/1992, one of which
 # was America/San_Luis, but we haven't verified this yet so for now we'll
 # keep America/Cordoba a single region rather than splitting it into the
@@ -399,14 +372,9 @@
 # to utc-04:00 until the second Saturday in October...
 #
 # The press release is at
-# <a href="http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102">
 # http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
-# </a>
-# (I couldn't find the decree, but
-# <a href="http://www.sanluis.gov.ar">
-# www.sanluis.gov.ar
-# <a/>
-# is the official page for the Province Government).
+# (I couldn't find the decree, but www.sanluis.gov.ar
+# is the official page for the Province Government.)
 #
 # There's also a note in only one of the major national papers ...
 # http://www.lanacion.com.ar/nota.asp?nota_id=1107912
@@ -423,9 +391,7 @@
 # ...the Province of San Luis is a case in itself.
 #
 # The Law at
-# <a href="http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276>"
 # http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276
-# </a>
 # is ambiguous because establishes a calendar from the 2nd Sunday in
 # October at 0:00 thru the 2nd Saturday in March at 24:00 and the
 # complement of that starting on the 2nd Sunday of March at 0:00 and
@@ -454,19 +420,15 @@
 # ...
 
 # From Alexander Krivenyshev (2010-04-09):
-# According to news reports from El Diario de la Republica Province San
+# According to news reports from El Diario de la República Province San
 # Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
-# after April 11, 2010--will continue to have same time as rest of
+# after April 11, 2010 - will continue to have same time as rest of
 # Argentina (UTC-3) (no DST).
 #
-# Confirmaron la pr&oacute;rroga del huso horario de verano (Spanish)
-# <a href="http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9">
+# Confirmaron la prórroga del huso horario de verano (Spanish)
 # http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
-# </a>
 # or (some English translation):
-# <a href="http://www.worldtimezone.com/dst_news/dst_news_argentina08.html">
 # http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
-# </a>
 
 # From Mariano Absatz (2010-04-12):
 # yes...I can confirm this...and given that San Luis keeps calling
@@ -478,7 +440,7 @@
 # Perhaps San Luis operates on the legal fiction that it is at UTC-4
 # with perpetual summer time, but ordinary usage typically seems to
 # just say it's at UTC-3; see, for example,
-# <http://es.wikipedia.org/wiki/Hora_oficial_argentina>.
+# http://es.wikipedia.org/wiki/Hora_oficial_argentina
 # We've documented similar situations as being plain changes to
 # standard time, so let's do that here too.  This does not change UTC
 # offsets, only tm_isdst and the time zone abbreviations.  One minor
@@ -486,20 +448,20 @@
 # setting for time stamps past 2038.
 
 # From Paul Eggert (2013-02-21):
-# Milne says Cordoba time was -4:16:48.2.  Round to the nearest second.
+# Milne says Córdoba time was -4:16:48.2.  Round to the nearest second.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
-Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
+# Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN),
 # Chaco (CC), Formosa (FM), Santiago del Estero (SE)
 #
 # Shanks & Pottenger also make the following claims, which we haven't verified:
@@ -519,7 +481,7 @@
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
+# Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN)
 Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -531,7 +493,7 @@
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tucuman (TM)
+# Tucumán (TM)
 Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -642,8 +604,8 @@
 			-3:00	-	ART
 #
 # Santa Cruz (SC)
-Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -653,9 +615,9 @@
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
-Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+# Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF)
+Zone America/Argentina/Ushuaia -4:33:12 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -686,13 +648,13 @@
 
 # From IATA SSIM (1996-02):
 # _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
-# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
-# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Santa Catarina (SC), Paraná (PR), São Paulo (SP), Rio de Janeiro (RJ),
+# Espírito Santo (ES), Minas Gerais (MG), Bahia (BA), Goiás (GO),
 # Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
 # [The last three states are new to this issue of the IATA SSIM.]
 
 # From Gwillim Law (1996-10-07):
-# Geography, history (Tocantins was part of Goias until 1989), and other
+# Geography, history (Tocantins was part of Goiás until 1989), and other
 # sources of time zone information lead me to believe that AL, SE, and TO were
 # always in BR1, and so the only change was whether or not they observed DST....
 # The earliest issue of the SSIM I have is 2/91.  Each issue from then until
@@ -706,16 +668,14 @@
 # However, some conclusions can be drawn from another IATA manual: the Airline
 # Coding Directory, which lists close to 400 airports in Brazil.  For each
 # airport it gives a time zone which is coded to the SSIM.  From that
-# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
-# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
-# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
+# information, I'm led to conclude that the states of Amapá (AP), Ceará (CE),
+# Maranhão (MA), Paraíba (PR), Pernambuco (PE), Piauí (PI), and Rio Grande do
+# Norte (RN), and the eastern part of Pará (PA) are all in BR1 without DST.
 
 # From Marcos Tadeu (1998-09-27):
-# <a href="http://pcdsh01.on.br/verao1.html">
-# Brazilian official page
-# </a>
+# Brazilian official page <http://pcdsh01.on.br/verao1.html>
 
-# From Jesper Norgaard (2000-11-03):
+# From Jesper Nørgaard (2000-11-03):
 # [For an official list of which regions in Brazil use which time zones, see:]
 # http://pcdsh01.on.br/Fusbr.htm
 # http://pcdsh01.on.br/Fusbrhv.htm
@@ -748,13 +708,13 @@
 
 # From Paul Schulze (2008-06-24):
 # ...by law number 11.662 of April 24, 2008 (published in the "Diario
-# Oficial da Uniao"...) in Brazil there are changes in the timezones,
+# Oficial da União"...) in Brazil there are changes in the timezones,
 # effective today (00:00am at June 24, 2008) as follows:
 #
-# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
+# a) The timezone UTC+5 is extinguished, with all the Acre state and the
 # part of the Amazonas state that had this timezone now being put to the
 # timezone UTC+4
-# b) The whole Para state now is put at timezone UTC+3, instead of just
+# b) The whole Pará state now is put at timezone UTC+3, instead of just
 # part of it, as was before.
 #
 # This change follows a proposal of senator Tiao Viana of Acre state, that
@@ -767,13 +727,11 @@
 
 # From Rodrigo Severo (2008-06-24):
 # Just correcting the URL:
-# <a href="https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008">
 # https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
-# </a>
 #
 # As a result of the above Decree I believe the America/Rio_Branco
 # timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
-# be created to represent the...west side of the Para State. I
+# be created to represent the...west side of the Pará State. I
 # suggest this new timezone be called Santarem as the most
 # important/populated city in the affected area.
 #
@@ -782,19 +740,16 @@
 
 # From Alex Krivenyshev (2008-06-24):
 # This is a quick reference page for New and Old Brazil Time Zones map.
-# <a href="http://www.worldtimezone.com/brazil-time-new-old.php">
 # http://www.worldtimezone.com/brazil-time-new-old.php
-# </a>
 #
-# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
-# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
-# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
+# - 4 time zones replaced by 3 time zones - eliminating time zone UTC-05
+# (state Acre and the part of the Amazonas will be UTC/GMT-04) - western
+# part of Par state is moving to one timezone UTC-03 (from UTC-04).
 
 # From Paul Eggert (2002-10-10):
 # The official decrees referenced below are mostly taken from
-# <a href="http://pcdsh01.on.br/DecHV.html">
-# Decretos sobre o Horario de Verao no Brasil
-# </a>.
+# Decretos sobre o Horário de Verão no Brasil.
+# http://pcdsh01.on.br/DecHV.html
 
 # From Steffen Thorsen (2008-08-29):
 # As announced by the government and many newspapers in Brazil late
@@ -806,25 +761,17 @@
 # It has not yet been posted to http://pcdsh01.on.br/DecHV.html
 #
 # An official page about it:
-# <a href="http://www.mme.gov.br/site/news/detail.do?newsId=16722">
 # http://www.mme.gov.br/site/news/detail.do?newsId=16722
-# </a>
 # Note that this link does not always work directly, but must be accessed
 # by going to
-# <a href="http://www.mme.gov.br/first">
 # http://www.mme.gov.br/first
-# </a>
 #
 # One example link that works directly:
-# <a href="http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54">
 # http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
 # (Portuguese)
-# </a>
 #
 # We have a written a short article about it as well:
-# <a href="http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html">
 # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
-# </a>
 #
 # From Alexander Krivenyshev (2011-10-04):
 # State Bahia will return to Daylight savings time this year after 8 years off.
@@ -832,17 +779,12 @@
 # television station in Salvador.
 
 # In Portuguese:
-# <a href="http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html">
 # http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
-# </a> and
-# <a href="http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html">
 # http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
-# </a>
 
 # From Guilherme Bernardes Rodrigues (2011-10-07):
 # There is news in the media, however there is still no decree about it.
-# I just send a e-mail to Zulmira Brandao at
-# <a href="http://pcdsh01.on.br/">http://pcdsh01.on.br/</a> the
+# I just send a e-mail to Zulmira Brandao at http://pcdsh01.on.br/ the
 # official agency about time in Brazil, and she confirmed that the old rule is
 # still in force.
 
@@ -854,9 +796,7 @@
 #
 # DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
 # Link :
-# <a href="http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6">
 # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
-# </a>
 
 # From Kelley Cook (2012-10-16):
 # The governor of state of Bahia in Brazil announced on Thursday that
@@ -884,42 +824,42 @@
 # For now, assume western Amazonas will change as well.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
-# Decree <a href="http://pcdsh01.on.br/HV21896.htm">21,896</a> (1932-01-10)
+# Decree 20,466 <http://pcdsh01.on.br/HV20466.htm> (1931-10-01)
+# Decree 21,896 <http://pcdsh01.on.br/HV21896.htm> (1932-01-10)
 Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
 Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
 Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV23195.htm">23,195</a> (1933-10-10)
+# Decree 23,195 <http://pcdsh01.on.br/HV23195.htm> (1933-10-10)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV27496.htm">27,496</a> (1949-11-24)
-# Decree <a href="http://pcdsh01.on.br/HV27998.htm">27,998</a> (1950-04-13)
+# Decree 27,496 <http://pcdsh01.on.br/HV27496.htm> (1949-11-24)
+# Decree 27,998 <http://pcdsh01.on.br/HV27998.htm> (1950-04-13)
 Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
 Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
 Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV32308.htm">32,308</a> (1953-02-24)
+# Decree 32,308 <http://pcdsh01.on.br/HV32308.htm> (1953-02-24)
 Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV34724.htm">34,724</a> (1953-11-30)
+# Decree 34,724 <http://pcdsh01.on.br/HV34724.htm> (1953-11-30)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV52700.htm">52,700</a> (1963-10-18)
+# Decree 52,700 <http://pcdsh01.on.br/HV52700.htm> (1963-10-18)
 # established DST from 1963-10-23 00:00 to 1964-02-29 00:00
 # in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
-# Decree <a href="http://pcdsh01.on.br/HV53071.htm">53,071</a> (1963-12-03)
+# Decree 53,071 <http://pcdsh01.on.br/HV53071.htm> (1963-12-03)
 # extended the above decree to all of the national territory on 12-09.
 Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV53604.htm">53,604</a> (1964-02-25)
+# Decree 53,604 <http://pcdsh01.on.br/HV53604.htm> (1964-02-25)
 # extended summer time by one day to 1964-03-01 00:00 (start of school).
 Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV55639.htm">55,639</a> (1965-01-27)
+# Decree 55,639 <http://pcdsh01.on.br/HV55639.htm> (1965-01-27)
 Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
 Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV57303.htm">57,303</a> (1965-11-22)
+# Decree 57,303 <http://pcdsh01.on.br/HV57303.htm> (1965-11-22)
 Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV57843.htm">57,843</a> (1966-02-18)
+# Decree 57,843 <http://pcdsh01.on.br/HV57843.htm> (1966-02-18)
 Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
 Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/HV63429.htm">63,429</a> (1968-10-15)
+# Decree 63,429 <http://pcdsh01.on.br/HV63429.htm> (1968-10-15)
 # revoked DST.
-# Decree <a href="http://pcdsh01.on.br/HV91698.htm">91,698</a> (1985-09-27)
+# Decree 91,698 <http://pcdsh01.on.br/HV91698.htm> (1985-09-27)
 Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
 # Decree 92,310 (1986-01-21)
 # Decree 92,463 (1986-03-13)
@@ -927,42 +867,42 @@
 # Decree 93,316 (1986-10-01)
 Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV94922.htm">94,922</a> (1987-09-22)
+# Decree 94,922 <http://pcdsh01.on.br/HV94922.htm> (1987-09-22)
 Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV96676.htm">96,676</a> (1988-09-12)
+# Decree 96,676 <http://pcdsh01.on.br/HV96676.htm> (1988-09-12)
 # except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
 Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
 Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV98077.htm">98,077</a> (1989-08-21)
+# Decree 98,077 <http://pcdsh01.on.br/HV98077.htm> (1989-08-21)
 # with the same exceptions
 Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
 Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV99530.htm">99,530</a> (1990-09-17)
+# Decree 99,530 <http://pcdsh01.on.br/HV99530.htm> (1990-09-17)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
 # Decree 99,629 (1990-10-19) adds BA, MT.
 Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
 Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
-# <a href="http://pcdsh01.on.br/HV1991.htm">Unnumbered decree</a> (1991-09-25)
+# Unnumbered decree <http://pcdsh01.on.br/HV1991.htm> (1991-09-25)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
 Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
 Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
-# <a href="http://pcdsh01.on.br/HV1992.htm">Unnumbered decree</a> (1992-10-16)
+# Unnumbered decree <http://pcdsh01.on.br/HV1992.htm> (1992-10-16)
 # adopted by same states.
 Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV942.htm">942</a> (1993-09-28)
+# Decree 942 <http://pcdsh01.on.br/HV942.htm> (1993-09-28)
 # adopted by same states, plus AM.
-# Decree <a href="http://pcdsh01.on.br/HV1252.htm">1,252</a> (1994-09-22;
+# Decree 1,252 <http://pcdsh01.on.br/HV1252.htm> (1994-09-22;
 # web page corrected 2004-01-07) adopted by same states, minus AM.
-# Decree <a href="http://pcdsh01.on.br/HV1636.htm">1,636</a> (1995-09-14)
+# Decree 1,636 <http://pcdsh01.on.br/HV1636.htm> (1995-09-14)
 # adopted by same states, plus MT and TO.
-# Decree <a href="http://pcdsh01.on.br/HV1674.htm">1,674</a> (1995-10-13)
+# Decree 1,674 <http://pcdsh01.on.br/HV1674.htm> (1995-10-13)
 # adds AL, SE.
 Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
 Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
 Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/HV2000.htm">2,000</a> (1996-09-04)
+# Decree 2,000 <http://pcdsh01.on.br/HV2000.htm> (1996-09-04)
 # adopted by same states, minus AL, SE.
 Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
 Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
@@ -975,53 +915,51 @@
 #
 # Decree 2,317 (1997-09-04), adopted by same states.
 Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/figuras/HV2495.JPG">2,495</a>
+# Decree 2,495 <http://pcdsh01.on.br/figuras/HV2495.JPG>
 # (1998-02-10)
 Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/figuras/Hv98.jpg">2,780</a> (1998-09-11)
+# Decree 2,780 <http://pcdsh01.on.br/figuras/Hv98.jpg> (1998-09-11)
 # adopted by the same states as before.
 Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
 Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/figuras/HV3150.gif">3,150</a>
+# Decree 3,150 <http://pcdsh01.on.br/figuras/HV3150.gif>
 # (1999-08-23) adopted by same states.
-# Decree <a href="http://pcdsh01.on.br/DecHV99.gif">3,188</a> (1999-09-30)
+# Decree 3,188 <http://pcdsh01.on.br/DecHV99.gif> (1999-09-30)
 # adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
 Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
 Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/DEC3592.htm">3,592</a> (2000-09-06)
+# Decree 3,592 <http://pcdsh01.on.br/DEC3592.htm> (2000-09-06)
 # adopted by the same states as before.
-# Decree <a href="http://pcdsh01.on.br/Dec3630.jpg">3,630</a> (2000-10-13)
+# Decree 3,630 <http://pcdsh01.on.br/Dec3630.jpg> (2000-10-13)
 # repeals DST in PE and RR, effective 2000-10-15 00:00.
-# Decree <a href="http://pcdsh01.on.br/Dec3632.jpg">3,632</a> (2000-10-17)
+# Decree 3,632 <http://pcdsh01.on.br/Dec3632.jpg> (2000-10-17)
 # repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
-# Decree <a href="http://pcdsh01.on.br/figuras/HV3916.gif">3,916</a>
+# Decree 3,916 <http://pcdsh01.on.br/figuras/HV3916.gif>
 # (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
 Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
 Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
 # Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
-# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2002/D4399.htm">4,399</a>
+# 4,399 <http://www.presidencia.gov.br/CCIVIL/decreto/2002/D4399.htm>
 Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
 # Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
-# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2003/D4844.htm">4,844</a>
+# 4,844 <http://www.presidencia.gov.br/CCIVIL/decreto/2003/D4844.htm>
 Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
 # Decree 5,223 (2004-10-01) reestablishes DST in MT.
-# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2004-2006/2004/Decreto/D5223.htm">5,223</a>
+# 5,223 <http://www.planalto.gov.br/ccivil_03/_Ato2004-2006/2004/Decreto/D5223.htm>
 Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/DecHV5539.gif">5,539</a> (2005-09-19),
+# Decree 5,539 <http://pcdsh01.on.br/DecHV5539.gif> (2005-09-19),
 # adopted by the same states as before.
 Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
-# Decree <a href="http://pcdsh01.on.br/DecHV5920.gif">5,920</a> (2006-10-03),
+# Decree 5,920 <http://pcdsh01.on.br/DecHV5920.gif> (2006-10-03),
 # adopted by the same states as before.
 Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
 Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
-# Decree <a href="http://pcdsh01.on.br/DecHV6212.gif">6,212</a> (2007-09-26),
+# Decree 6,212 <http://pcdsh01.on.br/DecHV6212.gif> (2007-09-26),
 # adopted by the same states as before.
 Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
 # From Frederico A. C. Neves (2008-09-10):
 # According to this decree
-# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm">
 # http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
-# </a>
 # [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
 # 3rd Feb Sunday. There is an exception on the return date when this is
 # the Carnival Sunday then the return date will be the next Sunday...
@@ -1056,29 +994,29 @@
 			-2:00	Brazil	FN%sT	2002 Oct  1
 			-2:00	-	FNT
 # Other Atlantic islands have no permanent settlement.
-# These include Trindade and Martin Vaz (administratively part of ES),
-# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
+# These include Trindade and Martim Vaz (administratively part of ES),
+# Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE).
 # Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
 # it also included the Penedos.
 #
-# Amapa (AP), east Para (PA)
-# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
-# The division between east and west Para is the river Xingu.
+# Amapá (AP), east Pará (PA)
+# East Pará includes Belém, Marabá, Serra Norte, and São Félix do Xingu.
+# The division between east and west Pará is the river Xingu.
 # In the north a very small part from the river Javary (now Jari I guess,
-# the border with Amapa) to the Amazon, then to the Xingu.
+# the border with Amapá) to the Amazon, then to the Xingu.
 Zone America/Belem	-3:13:56 -	LMT	1914
 			-3:00	Brazil	BR%sT	1988 Sep 12
 			-3:00	-	BRT
 #
-# west Para (PA)
-# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+# west Pará (PA)
+# West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém.
 Zone America/Santarem	-3:38:48 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
-			-4:00	-	AMT	2008 Jun 24 00:00
+			-4:00	-	AMT	2008 Jun 24  0:00
 			-3:00	-	BRT
 #
-# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
-# Paraiba (PB)
+# Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN),
+# Paraíba (PB)
 Zone America/Fortaleza	-2:34:00 -	LMT	1914
 			-3:00	Brazil	BR%sT	1990 Sep 17
 			-3:00	-	BRT	1999 Sep 30
@@ -1125,11 +1063,11 @@
 			-3:00	Brazil	BR%sT	2012 Oct 21
 			-3:00	-	BRT
 #
-# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
-# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Goiás (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR),
 # Santa Catarina (SC), Rio Grande do Sul (RS)
 Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
-			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
+			-3:00	Brazil	BR%sT	1963 Oct 23  0:00
 			-3:00	1:00	BRST	1964
 			-3:00	Brazil	BR%sT
 #
@@ -1143,7 +1081,7 @@
 			-4:00	-	AMT	2004 Oct  1
 			-4:00	Brazil	AM%sT
 #
-# Rondonia (RO)
+# Rondônia (RO)
 Zone America/Porto_Velho -4:15:36 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
 			-4:00	-	AMT
@@ -1155,7 +1093,7 @@
 			-4:00	Brazil	AM%sT	2000 Oct 15
 			-4:00	-	AMT
 #
-# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
+# east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto
 # The great circle line from Tabatinga to Porto Acre divides
 # east from west Amazonas.
 Zone America/Manaus	-4:00:04 -	LMT	1914
@@ -1165,19 +1103,19 @@
 			-4:00	-	AMT
 #
 # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
-#	Eirunepe, Envira, Ipixuna
+#	Eirunepé, Envira, Ipixuna
 Zone America/Eirunepe	-4:39:28 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
 			-5:00	-	ACT	1993 Sep 28
 			-5:00	Brazil	AC%sT	1994 Sep 22
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 #
 # Acre (AC)
 Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 
@@ -1198,66 +1136,54 @@
 # From Oscar van Vlijmen (2006-10-08):
 # http://www.horaoficial.cl/cambio.htm
 
-# From Jesper Norgaard Welen (2006-10-08):
+# From Jesper Nørgaard Welen (2006-10-08):
 # I think that there are some obvious mistakes in the suggested link
 # from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
 # ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
 # (they should have been 1990-09-15 and 1990-09-16 respectively), but
 # anyhow it clears up some doubts too.
 
-# From Paul Eggert (2006-12-27):
-# The following data for Chile and America/Santiago are from
+# From Paul Eggert (2014-08-12):
+# The following data entries for Chile and America/Santiago are from
 # <http://www.horaoficial.cl/horaof.htm> (2006-09-20), transcribed by
-# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
+# Jesper Nørgaard Welen.  The data entries for Pacific/Easter are from Shanks
 # & Pottenger, except with DST transitions after 1932 cloned from
-# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
+# America/Santiago.  The pre-1980 Pacific/Easter data entries are dubious,
 # but we have no other source.
 
-# From German Poo-Caaman~o (2008-03-03):
+# From Germán Poo-Caamaño (2008-03-03):
 # Due to drought, Chile extends Daylight Time in three weeks.  This
 # is one-time change (Saturday 3/29 at 24:00 for America/Santiago
 # and Saturday 3/29 at 22:00 for Pacific/Easter)
 # The Supreme Decree is located at
-# <a href="http://www.shoa.cl/servicios/supremo316.pdf">
 # http://www.shoa.cl/servicios/supremo316.pdf
-# </a>
 # and the instructions for 2008 are located in:
-# <a href="http://www.horaoficial.cl/cambio.htm">
 # http://www.horaoficial.cl/cambio.htm
-# </a>.
 
-# From Jose Miguel Garrido (2008-03-05):
+# From José Miguel Garrido (2008-03-05):
 # ...
 # You could see the announces of the change on
-# <a href="http://www.shoa.cl/noticias/2008/04hora/hora.htm">
 # http://www.shoa.cl/noticias/2008/04hora/hora.htm
-# </a>.
 
 # From Angel Chiang (2010-03-04):
 # Subject: DST in Chile exceptionally extended to 3 April due to earthquake
-# <a href="http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098">
 # http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
-# </a>
 # (in Spanish, last paragraph).
 #
 # This is breaking news. There should be more information available later.
 
-# From Arthur Daivd Olson (2010-03-06):
+# From Arthur David Olson (2010-03-06):
 # Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
 
-# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
+# From Glenn Eychaner (2011-03-02):
 # It appears that the Chilean government has decided to postpone the
 # change from summer time to winter time again, by three weeks to April
 # 2nd:
-# <a href="http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651">
 # http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
-# </a>
 #
 # This is not yet reflected in the official "cambio de hora" site, but
 # probably will be soon:
-# <a href="http://www.horaoficial.cl/cambio.htm">
 # http://www.horaoficial.cl/cambio.htm
-# </a>
 
 # From Arthur David Olson (2011-03-02):
 # The emol.com article mentions a water shortage as the cause of the
@@ -1265,9 +1191,7 @@
 
 # From Glenn Eychaner (2011-03-28):
 # The article:
-# <a href="http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}">
 # http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
-# </a>
 #
 # In English:
 # Chile's clocks will go back an hour this year on the 7th of May instead
@@ -1298,7 +1222,7 @@
 # start date is 2013-09-08 00:00....
 # http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm
 
-# From Jose Miguel Garrido (2014-02-19):
+# From José Miguel Garrido (2014-02-19):
 # Today appeared in the Diario Oficial a decree amending the time change
 # dates to 2014.
 # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
@@ -1352,7 +1276,7 @@
 # (1996-09) says 1998-03-08.  Ignore these.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santiago	-4:42:46 -	LMT	1890
-			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
+			-4:42:46 -	SMT	1910        # Santiago Mean Time
 			-5:00	-	CLT	1916 Jul  1 # Chile Time
 			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
 			-4:00	-	CLT	1919 Jul  1 # Chile Time
@@ -1361,16 +1285,16 @@
 			-4:00	Chile	CL%sT
 Zone Pacific/Easter	-7:17:44 -	LMT	1890
 			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
-			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
+			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter Time
 			-6:00	Chile	EAS%sT
 #
-# Sala y Gomez Island is like Pacific/Easter.
-# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
-# San Felix, and Antarctic bases, are like America/Santiago.
+# Salas y Gómez Island is uninhabited.
+# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
+# and Antarctic bases, are like America/Santiago.
 
 # Colombia
 
-# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest.  He writes,
+# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest.  He writes,
 # "A variation of fifteen minutes in the public clocks of Bogota is not rare."
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1378,37 +1302,37 @@
 Rule	CO	1993	only	-	Apr	 4	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
-			-4:56:16 -	BMT	1914 Nov 23 # Bogota Mean Time
+			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
 			-5:00	CO	CO%sT	# Colombia Time
 # Malpelo, Providencia, San Andres
 # no information; probably like America/Bogota
 
-# Curacao
+# Curaçao
 
-# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
+# Milne gives 4:35:46.9 for Curaçao mean time; round to nearest.
 #
 # From Paul Eggert (2006-03-22):
 # Shanks & Pottenger say that The Bottom and Philipsburg have been at
 # -4:00 since standard time was introduced on 1912-03-02; and that
 # Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
 # 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
-# Saba Island has been like Curacao.
+# Saba Island has been like Curaçao.
 # This all predates our 1970 cutoff, though.
 #
-# By July 2007 Curacao and St Maarten are planned to become
+# By July 2007 Curaçao and St Maarten are planned to become
 # associated states within the Netherlands, much like Aruba;
 # Bonaire, Saba and St Eustatius would become directly part of the
 # Netherlands as Kingdom Islands.  This won't affect their time zones
 # though, as far as we know.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12	# Willemstad
+Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
 			-4:30	-	ANT	1965 # Netherlands Antilles Time
 			-4:00	-	AST
 
 # From Arthur David Olson (2011-06-15):
 # use links for places with new iso3166 codes.
-# The name "Lower Prince's Quarter" is both longer than fourteen charaters
+# The name "Lower Prince's Quarter" is both longer than fourteen characters
 # and contains an apostrophe; use "Lower_Princes" below.
 
 Link	America/Curacao	America/Lower_Princes	# Sint Maarten
@@ -1416,7 +1340,7 @@
 
 # Ecuador
 #
-# Milne says the Sentral and South American Telegraph Company used -5:24:15.
+# Milne says the Central and South American Telegraph Company used -5:24:15.
 #
 # From Paul Eggert (2007-03-04):
 # Apparently Ecuador had a failed experiment with DST in 1992.
@@ -1427,10 +1351,10 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guayaquil	-5:19:20 -	LMT	1890
 			-5:14:00 -	QMT	1931 # Quito Mean Time
-			-5:00	-	ECT	     # Ecuador Time
+			-5:00	-	ECT	# Ecuador Time
 Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 			-5:00	-	ECT	1986
-			-6:00	-	GALT	     # Galapagos Time
+			-6:00	-	GALT	# Galápagos Time
 
 # Falklands
 
@@ -1439,7 +1363,7 @@
 # the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
 
 # From Falkland Islands Government Office, London (2001-01-22)
-# via Jesper Norgaard:
+# via Jesper Nørgaard:
 # ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
 # April 2001 and advance one hour to summer time at 2 am on Sunday 2
 # September.  It is anticipated that the clocks will revert back at 2
@@ -1488,9 +1412,7 @@
 # daylight saving time.
 #
 # One source:
-# <a href="http://www.falklandnews.com/public/story.cfm?get=5914&source=3">
 # http://www.falklandnews.com/public/story.cfm?get=5914&source=3
-# </a>
 #
 # We have gotten this confirmed by a clerk of the legislative assembly:
 # Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
@@ -1531,10 +1453,10 @@
 Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
-			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
-			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
+			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
+			-4:00	Falk	FK%sT	1983 May    # Falkland Is Time
 			-3:00	Falk	FK%sT	1985 Sep 15
-			-4:00	Falk	FK%sT	2010 Sep 5 02:00
+			-4:00	Falk	FK%sT	2010 Sep  5  2:00
 			-3:00	-	FKST
 
 # French Guiana
@@ -1545,7 +1467,7 @@
 
 # Guyana
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
+Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
 			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
 			-3:45	-	GYT	1975 Jul 31 # Guyana Time
 			-3:00	-	GYT	1991
@@ -1555,8 +1477,8 @@
 # Paraguay
 #
 # From Paul Eggert (2006-03-22):
-# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
-# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
+# Shanks & Pottenger say that spring transitions are 01:00 -> 02:00,
+# and autumn transitions are 00:00 -> 23:00.  Go with pre-1999
 # editions of Shanks, and with the IATA, who say transitions occur at 00:00.
 #
 # From Waldemar Villamayor-Venialbo (2013-09-20):
@@ -1582,9 +1504,8 @@
 # (10-01).
 #
 # Translated by Gwillim Law (2001-02-27) from
-# <a href="http://www.diarionoticias.com.py/011000/nacional/naciona1.htm">
-# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
-# </a>:
+# Noticias, a daily paper in Asunción, Paraguay (2000-10-01):
+# http://www.diarionoticias.com.py/011000/nacional/naciona1.htm
 # Starting at 0:00 today, the clock will be set forward 60 minutes, in
 # fulfillment of Decree No. 7,273 of the Executive Power....  The time change
 # system has been operating for several years.  Formerly there was a separate
@@ -1605,21 +1526,18 @@
 Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
 Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
 #
-# From Jesper Norgaard Welen (2005-01-02):
+# From Jesper Nørgaard Welen (2005-01-02):
 # There are several sources that claim that Paraguay made
 # a timezone rule change in autumn 2004.
 # From Steffen Thorsen (2005-01-05):
 # Decree 1,867 (2004-03-05)
-# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
-# <http://www.presidencia.gov.py/decretos/D1867.pdf>
+# From Carlos Raúl Perasso via Jesper Nørgaard Welen (2006-10-13)
+# http://www.presidencia.gov.py/decretos/D1867.pdf
 Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
 Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
-# From Carlos Raul Perasso (2010-02-18):
-# By decree number 3958 issued yesterday (
-# <a href="http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf">
+# From Carlos Raúl Perasso (2010-02-18):
+# By decree number 3958 issued yesterday
 # http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
-# </a>
-# )
 # Paraguay changes its DST schedule, postponing the March rule to April and
 # modifying the October date. The decree reads:
 # ...
@@ -1635,25 +1553,25 @@
 # Paraguay will end DST on 2013-03-24 00:00....
 # http://www.ande.gov.py/interna.php?id=1075
 #
-# From Carlos Raul Perasso (2013-03-15):
+# From Carlos Raúl Perasso (2013-03-15):
 # The change in Paraguay is now final.  Decree number 10780
 # http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf
-# From Carlos Raul Perasso (2014-02-28):
+# From Carlos Raúl Perasso (2014-02-28):
 # Decree 1264 can be found at:
 # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
 Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Asuncion	-3:50:40 -	LMT	1890
-			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
-			-4:00	-	PYT	1972 Oct # Paraguay Time
+			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
+			-4:00	-	PYT	1972 Oct    # Paraguay Time
 			-3:00	-	PYT	1974 Apr
 			-4:00	Para	PY%sT
 
 # Peru
 #
-# <a href="news:xrGmb.39935$gA1.13896113@news4.srv.hcvlny.cv.net">
-# From Evelyn C. Leeper via Mark Brader (2003-10-26):</a>
+# From Evelyn C. Leeper via Mark Brader (2003-10-26)
+# <news:xrGmb.39935$gA1.13896113@news4.srv.hcvlny.cv.net>:
 # When we were in Peru in 1985-1986, they apparently switched over
 # sometime between December 29 and January 3 while we were on the Amazon.
 #
@@ -1679,7 +1597,7 @@
 
 # South Georgia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
+Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
 			-2:00	-	GST	# South Georgia Time
 
 # South Sandwich Is
@@ -1689,9 +1607,9 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Paramaribo	-3:40:40 -	LMT	1911
 			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
-			-3:40:36 -	PMT	1945 Oct # The capital moved?
+			-3:40:36 -	PMT	1945 Oct    # The capital moved?
 			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
-			-3:30	-	SRT	1984 Oct # Suriname Time
+			-3:30	-	SRT	1984 Oct    # Suriname Time
 			-3:00	-	SRT
 
 # Trinidad and Tobago
@@ -1706,7 +1624,7 @@
 Link America/Port_of_Spain America/Guadeloupe
 Link America/Port_of_Spain America/Marigot	# St Martin (French part)
 Link America/Port_of_Spain America/Montserrat
-Link America/Port_of_Spain America/St_Barthelemy
+Link America/Port_of_Spain America/St_Barthelemy # St Barthélemy
 Link America/Port_of_Spain America/St_Kitts	# St Kitts & Nevis
 Link America/Port_of_Spain America/St_Lucia
 Link America/Port_of_Spain America/St_Thomas	# Virgin Islands (US)
@@ -1765,7 +1683,7 @@
 Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
 Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
 # From Eduardo Cota (2004-09-20):
-# The uruguayan government has decreed a change in the local time....
+# The Uruguayan government has decreed a change in the local time....
 # http://www.presidencia.gub.uy/decretos/2004091502.htm
 Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
 # From Steffen Thorsen (2005-03-11):
@@ -1779,14 +1697,14 @@
 # 02:00 local time, official time in Uruguay will be at GMT -2.
 Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
 Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
-# From Jesper Norgaard Welen (2006-09-06):
+# From Jesper Nørgaard Welen (2006-09-06):
 # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
 Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
 Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
-			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
-			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
+			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
+			-3:30	Uruguay	UY%sT	1942 Dec 14 # Uruguay Time
 			-3:00	Uruguay	UY%sT
 
 # Venezuela
@@ -1794,14 +1712,14 @@
 # From John Stainforth (2007-11-28):
 # ... the change for Venezuela originally expected for 2007-12-31 has
 # been brought forward to 2007-12-09.  The official announcement was
-# published today in the "Gaceta Oficial de la Republica Bolivariana
-# de Venezuela, numero 38.819" (official document for all laws or
+# published today in the "Gaceta Oficial de la República Bolivariana
+# de Venezuela, número 38.819" (official document for all laws or
 # resolution publication)
 # http://www.globovision.com/news.php?nid=72208
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
-			-4:30	-	VET	1965	     # Venezuela Time
-			-4:00	-	VET	2007 Dec  9 03:00
+			-4:30	-	VET	1965        # Venezuela Time
+			-4:00	-	VET	2007 Dec  9  3:00
 			-4:30	-	VET
--- a/jdk/test/sun/util/calendar/zi/tzdata/systemv	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/systemv	Wed Jul 05 20:00:59 2017 +0200
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# <pre>
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
--- a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab	Wed Jul 05 20:00:59 2017 +0200
@@ -21,39 +21,27 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# TZ zone descriptions
+# tz zone descriptions (deprecated version)
 #
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-08-14):
-#
-# This file contains a table where each row stands for an area that is
-# the intersection of a region identified by a country code and of a
-# zone where civil clocks have agreed since 1970.  The columns of the
-# table are as follows:
+# From Paul Eggert (2014-07-31):
+# This file is intended as a backward-compatibility aid for older programs.
+# New programs should use zone1970.tab.  This file is like zone1970.tab (see
+# zone1970.tab's comments), but with the following additional restrictions:
 #
-# 1.  ISO 3166 2-character country code.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the area's principal location
-#     in ISO 6709 sign-degrees-minutes-seconds format,
-#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
-#     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the 'Theory' file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
-#     table, with column 1 being duplicated.
-# 4.  Comments; present if and only if the country has multiple rows.
+# 1.  This file contains only ASCII characters.
+# 2.  The first data column contains exactly one country code.
 #
-# Columns are separated by a single tab.
-# The table is sorted first by country, then an order within the country that
-# (1) makes some geographical sense, and
-# (2) puts the most populous areas first, where that does not contradict (1).
-#
-# Lines beginning with '#' are comments.
+# Because of (2), each row stands for an area that is the intersection
+# of a region identified by a country code and of a zone where civil
+# clocks have agreed since 1970; this is a narrower definition than
+# that of zone1970.tab.
 #
 # This table is intended as an aid for users, to help them select time
-# zone data appropriate for their practical needs.  It is not intended
-# to take or endorse any position on legal or territorial claims.
+# zone data entries appropriate for their practical needs.  It is not
+# intended to take or endorse any position on legal or territorial claims.
 #
 #country-
 #code	coordinates	TZ			comments
@@ -72,7 +60,7 @@
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
 AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
-AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
+AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Adelie Land
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-720041+0023206	Antarctica/Troll	Troll Station, Queen Maud Land
 AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
@@ -151,7 +139,7 @@
 CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
 CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
 CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
-CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
+CA	+744144-0944945	America/Resolute	Central Time - Resolute, Nunavut
 CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
 CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
 CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
@@ -176,13 +164,10 @@
 CI	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most locations
-CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
+CL	-2709-10926	Pacific/Easter	Easter Island
 CM	+0403+00942	Africa/Douala
-CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
-CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
-CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
-CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
-CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
+CN	+3114+12128	Asia/Shanghai	Beijing Time
+CN	+4348+08735	Asia/Urumqi	Xinjiang Time
 CO	+0436-07405	America/Bogota
 CR	+0956-08405	America/Costa_Rica
 CU	+2308-08222	America/Havana
@@ -364,24 +349,26 @@
 RO	+4426+02606	Europe/Bucharest
 RS	+4450+02030	Europe/Belgrade
 RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
-RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
+RU	+554521+0373704	Europe/Moscow	Moscow+00 - west Russia
+RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
 RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
-RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
-RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
+RU	+5312+05009	Europe/Samara	Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia
 RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
 RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
 RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
-RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
+RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo
 RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
 RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
+RU	+5203+11328	Asia/Chita	Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky
 RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
 RU	+623923+1353314	Asia/Khandyga	Moscow+06 - Tomponsky, Ust-Maysky
 RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
 RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
 RU	+643337+1431336	Asia/Ust-Nera	Moscow+07 - Oymyakonsky
-RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
-RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
-RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
+RU	+5934+15048	Asia/Magadan	Moscow+08 (Moscow+07 after 2014-10-26) - Magadan
+RU	+6728+15343	Asia/Srednekolymsk	Moscow+08 - E Sakha, N Kuril Is
+RU	+5301+15839	Asia/Kamchatka	Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka
+RU	+6445+17729	Asia/Anadyr	Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea
 RW	-0157+03004	Africa/Kigali
 SA	+2438+04643	Asia/Riyadh
 SB	-0932+16012	Pacific/Guadalcanal
@@ -448,13 +435,13 @@
 US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
 US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona (except Navajo)
 US	+340308-1181434	America/Los_Angeles	Pacific Time
+US	+550737-1313435	America/Metlakatla	Pacific Standard Time - Annette Island, Alaska
 US	+611305-1495401	America/Anchorage	Alaska Time
 US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
 US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
 US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
 US	+643004-1652423	America/Nome	Alaska Time - west Alaska
 US	+515248-1763929	America/Adak	Aleutian Islands
-US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
 US	+211825-1575130	Pacific/Honolulu	Hawaii
 UY	-3453-05611	America/Montevideo
 UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
--- a/jdk/test/sun/util/resources/TimeZone/Bug6317929.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/jdk/test/sun/util/resources/TimeZone/Bug6317929.java	Wed Jul 05 20:00:59 2017 +0200
@@ -122,11 +122,11 @@
         TimeZone Currie = TimeZone.getTimeZone("Australia/Currie");
         tzLocale = locales2Test[0];
         if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
-           ("Eastern Standard Time (New South Wales)"))
+           ("Australian Eastern Standard Time (New South Wales)"))
             throw new RuntimeException("\n" + tzLocale + ": LONG, " +
                                        "non-daylight saving name for " +
                                        "Australia/Currie should be " +
-                                       "\"Eastern Standard Time " +
+                                       "\"Australian Eastern Standard Time " +
                                        "(New South Wales)\"");
         tzLocale = locales2Test[1];
         if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
--- a/make/Main.gmk	Thu Sep 11 14:29:01 2014 -0700
+++ b/make/Main.gmk	Wed Jul 05 20:00:59 2017 +0200
@@ -487,17 +487,8 @@
 # Clean targets
 #
 ################################################################################
-
-# If running a clean target, disable parallel execution
-ifneq ($(findstring clean, $(MAKECMDGOALS)), )
-  .NOTPARALLEL:
-  # It's not recommended to run additional targets to clean on the same make
-  # command line. Try to detect this and issue a warning.
-  ifneq ($(filter-out clean%, $(MAKECMDGOALS)), )
-    $(warning Mixing clean targets with normal build targets will not work well \
-        and is not recommended.)
-  endif
-endif
+# Clean targets are automatically run serially by the Makefile calling this 
+# file.
 
 CLEAN_COMPONENTS += langtools corba hotspot jdk nashorn images \
     bootcycle-build docs docstemp test
@@ -543,6 +534,9 @@
 	@if test "x$(IGNORE_OLD_CONFIG)" != "xtrue"; then exit 1; fi
 endif
 
+# The reconfigure target is automatically run serially from everything else
+# by the Makefile calling this file.
+
 reconfigure:
         ifneq ($(CONFIGURE_COMMAND_LINE), )
 	  @$(ECHO) "Re-running configure using arguments '$(CONFIGURE_COMMAND_LINE)'"
--- a/make/common/MakeBase.gmk	Thu Sep 11 14:29:01 2014 -0700
+++ b/make/common/MakeBase.gmk	Wed Jul 05 20:00:59 2017 +0200
@@ -349,7 +349,7 @@
     # (and causing a crash on Cygwin).
     # Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris.
     # Only use time if it's GNU time which supports format and output file.
-    WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log /bin/bash
+    WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(BASH)
     SHELL=$$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL)
   endif
   # Never remove warning messages; this is just for completeness
--- a/make/jprt.properties	Thu Sep 11 14:29:01 2014 -0700
+++ b/make/jprt.properties	Wed Jul 05 20:00:59 2017 +0200
@@ -165,6 +165,7 @@
     ${my.test.target.set:TESTNAME=jdk_security1},			\
     ${my.test.target.set:TESTNAME=jdk_security2},			\
     ${my.test.target.set:TESTNAME=jdk_security3},			\
+    ${my.test.target.set:TESTNAME=jdk_security4},			\
     ${my.test.target.set:TESTNAME=jdk_rmi},				\
     ${my.test.target.set:TESTNAME=jdk_text},				\
     ${my.test.target.set:TESTNAME=jdk_time},				\
--- a/modules.xml	Thu Sep 11 14:29:01 2014 -0700
+++ b/modules.xml	Wed Jul 05 20:00:59 2017 +0200
@@ -1034,6 +1034,12 @@
       <name>org.w3c.dom.ls</name>
     </export>
     <export>
+      <name>org.w3c.dom.ranges</name>
+    </export>
+    <export>
+      <name>org.w3c.dom.traversal</name>
+    </export>
+    <export>
       <name>org.w3c.dom.views</name>
     </export>
     <export>
@@ -1569,6 +1575,12 @@
     <depend>jdk.crypto.ec</depend>
   </module>
   <module>
+    <name>jdk.deploy.osx</name>
+    <depend>java.base</depend>
+    <depend>java.desktop</depend>
+    <depend>java.scripting</depend>
+  </module>
+  <module>
     <name>jdk.dev</name>
     <depend>java.base</depend>
     <depend>java.scripting</depend>
--- a/nashorn/.hgignore	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/.hgignore	Wed Jul 05 20:00:59 2017 +0200
@@ -6,8 +6,7 @@
 /nbproject/private/
 private.xml
 private.properties
-webrev/*
-webrev.zip
+^webrev
 .classpath
 *.class
 *.clazz
--- a/nashorn/.hgtags	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/.hgtags	Wed Jul 05 20:00:59 2017 +0200
@@ -263,3 +263,4 @@
 221a84ef44c00335b563d92f470efaf8162b471e jdk9-b27
 00c31e5eaf26f9b238165157b9d1c617b03abcb6 jdk9-b28
 e541ebaf2ab7038333ad0c13f4decd327c26dd15 jdk9-b29
+072dbed6c5d968a6b9e156c36cd8838b4ff86ea1 jdk9-b30
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Wed Jul 05 20:00:59 2017 +0200
@@ -194,12 +194,12 @@
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
         // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
-        //
         body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
-            public boolean enterFunctionNode(final FunctionNode nestedFn) {
-                // Don't descend into nested functions
-                return false;
+            protected boolean enterDefault(final Node node) {
+                // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
+                // This will also prevent visiting nested functions (as FunctionNode is an expression).
+                return !(node instanceof Expression);
             }
 
             @Override
@@ -443,12 +443,27 @@
 
         if (lc.isFunctionBody()) {
             block.clearSymbols();
+            final FunctionNode fn = lc.getCurrentFunction();
+            if (isUnparsedFunction(fn)) {
+                // It's a skipped nested function. Just mark the symbols being used by it as being in use.
+                for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) {
+                    nameIsUsed(name, null);
+                }
+                // Don't bother descending into it, it must be empty anyway.
+                assert block.getStatements().isEmpty();
+                return false;
+            }
+
             enterFunctionBody();
         }
 
         return true;
     }
 
+    private boolean isUnparsedFunction(final FunctionNode fn) {
+        return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+    }
+
     @Override
     public boolean enterCatchNode(final CatchNode catchNode) {
         final IdentNode exception = catchNode.getException();
@@ -492,18 +507,13 @@
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        // TODO: once we have information on symbols used by nested functions, we can stop descending into nested
-        // functions with on-demand compilation, e.g. add
-        // if(!thisProperties.isEmpty() && env.isOnDemandCompilation()) {
-        //    return false;
-        // }
         start(functionNode, false);
 
         thisProperties.push(new HashSet<String>());
 
-        //an outermost function in our lexical context that is not a program
-        //is possible - it is a function being compiled lazily
         if (functionNode.isDeclared()) {
+            // Can't use lc.getCurrentBlock() as we can have an outermost function in our lexical context that
+            // is not a program - it is a function being compiled on-demand.
             final Iterator<Block> blocks = lc.getBlocks();
             if (blocks.hasNext()) {
                 final IdentNode ident = functionNode.getIdent();
@@ -511,6 +521,11 @@
             }
         }
 
+        // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
+        // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
+        // are used in them.
+        assert functionNode.getBody() != null;
+
         return true;
     }
 
@@ -533,7 +548,7 @@
 
     /**
      * This has to run before fix assignment types, store any type specializations for
-     * paramters, then turn then to objects for the generic version of this method
+     * parameters, then turn them into objects for the generic version of this method.
      *
      * @param functionNode functionNode
      */
@@ -733,14 +748,20 @@
 
     @Override
     public Node leaveBlock(final Block block) {
-        // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's
-        // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand
-        // optimistic compilation, so we can skip locals marking then.
+        // It's not necessary to guard the marking of symbols as locals with this "if" condition for
+        // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
+        // is not an on-demand optimistic compilation, so we can skip locals marking then.
         if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
-            for (final Symbol symbol: block.getSymbols()) {
-                if (!symbol.isScope()) {
-                    assert symbol.isVar() || symbol.isParam();
-                    compiler.declareLocalSymbol(symbol.getName());
+            // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
+            // compilation, and we're skipping parsing the function bodies for nested functions, this
+            // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
+            // symbol in the outer function named the same as one of the parameters, though.
+            if (lc.getFunction(block) == lc.getOutermostFunction()) {
+                for (final Symbol symbol: block.getSymbols()) {
+                    if (!symbol.isScope()) {
+                        assert symbol.isVar() || symbol.isParam();
+                        compiler.declareLocalSymbol(symbol.getName());
+                    }
                 }
             }
         }
@@ -811,24 +832,45 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-
-        return markProgramBlock(
+        final FunctionNode finalizedFunction;
+        if (isUnparsedFunction(functionNode)) {
+            finalizedFunction = functionNode;
+        } else {
+            finalizedFunction =
+               markProgramBlock(
                removeUnusedSlots(
                createSyntheticInitializers(
                finalizeParameters(
                        lc.applyTopFlags(functionNode))))
-                       .setThisProperties(lc, thisProperties.pop().size())
-                       .setState(lc, CompilationState.SYMBOLS_ASSIGNED));
+                       .setThisProperties(lc, thisProperties.pop().size()));
+        }
+        return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED);
     }
 
     @Override
     public Node leaveIdentNode(final IdentNode identNode) {
-        final String name = identNode.getName();
-
         if (identNode.isPropertyName()) {
             return identNode;
         }
 
+        final Symbol symbol = nameIsUsed(identNode.getName(), identNode);
+
+        if (!identNode.isInitializedHere()) {
+            symbol.increaseUseCount();
+        }
+
+        IdentNode newIdentNode = identNode.setSymbol(symbol);
+
+        // If a block-scoped var is used before its declaration mark it as dead.
+        // We can only statically detect this for local vars, cross-function symbols require runtime checks.
+        if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) {
+            newIdentNode = newIdentNode.markDead();
+        }
+
+        return end(newIdentNode);
+    }
+
+    private Symbol nameIsUsed(final String name, final IdentNode origin) {
         final Block block = lc.getCurrentBlock();
 
         Symbol symbol = findSymbol(block, name);
@@ -847,24 +889,11 @@
             maybeForceScope(symbol);
         } else {
             log.info("No symbol exists. Declare as global: ", name);
-            symbol = defineSymbol(block, name, identNode, IS_GLOBAL | IS_SCOPE);
+            symbol = defineSymbol(block, name, origin, IS_GLOBAL | IS_SCOPE);
         }
 
         functionUsesSymbol(symbol);
-
-        if (!identNode.isInitializedHere()) {
-            symbol.increaseUseCount();
-        }
-
-        IdentNode newIdentNode = identNode.setSymbol(symbol);
-
-        // If a block-scoped var is used before its declaration mark it as dead.
-        // We can only statically detect this for local vars, cross-function symbols require runtime checks.
-        if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) {
-            newIdentNode = newIdentNode.markDead();
-        }
-
-        return end(newIdentNode);
+        return symbol;
     }
 
     @Override
@@ -912,7 +941,6 @@
             return functionNode;
         }
 
-        assert functionNode.getId() == 1;
         return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE));
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Jul 05 20:00:59 2017 +0200
@@ -59,6 +59,7 @@
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
+
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
@@ -135,6 +136,16 @@
     /** Set of constants access methods required. */
     private Set<Class<?>> constantMethodNeeded;
 
+    private int methodCount;
+
+    private int initCount;
+
+    private int clinitCount;
+
+    private int fieldCount;
+
+    private final Set<String> methodNames;
+
     /**
      * Constructor - only used internally in this class as it breaks
      * abstraction towards ASM or other code generator below
@@ -146,6 +157,11 @@
         this.context        = context;
         this.cw             = cw;
         this.methodsStarted = new HashSet<>();
+        this.methodNames    = new HashSet<>();
+    }
+
+    public Set<String> getMethodNames() {
+        return methodNames;
     }
 
     /**
@@ -209,6 +225,38 @@
     }
 
     /**
+     * Get the method count, including init and clinit methods
+     * @return method count
+     */
+    public int getMethodCount() {
+        return methodCount;
+    }
+
+    /**
+     * Get the clinit count
+     * @return clinit count
+     */
+    public int getClinitCount() {
+        return clinitCount;
+    }
+
+    /**
+     * Get the init count
+     * @return init count
+     */
+    public int getInitCount() {
+        return initCount;
+    }
+
+    /**
+     * Get the field count
+     * @return field count
+     */
+    public int getFieldCount() {
+        return fieldCount;
+    }
+
+    /**
      * Convert a binary name to a package/class name.
      *
      * @param name Binary name.
@@ -359,9 +407,16 @@
      */
     @Override
     public void end() {
-        assert classStarted;
+        assert classStarted : "class not started for " + unitClassName;
 
         if (unitClassName != null) {
+            final MethodEmitter initMethod = init(EnumSet.of(Flag.PRIVATE));
+            initMethod.begin();
+            initMethod.load(Type.OBJECT, 0);
+            initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
+            initMethod.returnVoid();
+            initMethod.end();
+
             defineCommonUtilities();
         }
 
@@ -419,6 +474,8 @@
     }
 
     SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+        methodCount++;
+        methodNames.add(methodName);
         return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode);
     }
 
@@ -446,6 +503,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+        methodCount++;
+        methodNames.add(methodName);
         return new MethodEmitter(this, methodVisitor(methodFlags, methodName, rtype, ptypes));
     }
 
@@ -471,6 +530,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) {
+        methodCount++;
+        methodNames.add(methodName);
         return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null));
     }
 
@@ -481,6 +542,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final FunctionNode functionNode) {
+        methodCount++;
+        methodNames.add(functionNode.getName());
         final FunctionSignature signature = new FunctionSignature(functionNode);
         final MethodVisitor mv = cw.visitMethod(
             ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0),
@@ -499,6 +562,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter restOfMethod(final FunctionNode functionNode) {
+        methodCount++;
+        methodNames.add(functionNode.getName());
         final MethodVisitor mv = cw.visitMethod(
             ACC_PUBLIC | ACC_STATIC,
             functionNode.getName(),
@@ -516,6 +581,7 @@
      * @return method emitter to use for weaving <clinit>
      */
     MethodEmitter clinit() {
+        clinitCount++;
         return method(EnumSet.of(Flag.STATIC), CLINIT.symbolName(), void.class);
     }
 
@@ -525,6 +591,7 @@
      * @return method emitter to use for weaving <init>()V
      */
     MethodEmitter init() {
+        initCount++;
         return method(INIT.symbolName(), void.class);
     }
 
@@ -535,6 +602,7 @@
      * @return method emitter to use for weaving <init>()V
      */
     MethodEmitter init(final Class<?>... ptypes) {
+        initCount++;
         return method(INIT.symbolName(), void.class, ptypes);
     }
 
@@ -547,6 +615,7 @@
      * @return method emitter to use for weaving <init>(...)V
      */
     MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) {
+        initCount++;
         return method(flags, INIT.symbolName(), void.class, ptypes);
     }
 
@@ -561,6 +630,7 @@
      * @see ClassEmitter.Flag
      */
     final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) {
+        fieldCount++;
         cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd();
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1622,9 +1622,18 @@
 
             @Override
             protected void evaluate() {
-                method.load(ITERATOR_TYPE, iterSlot);
-                // TODO: optimistic for-in iteration
-                method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
+                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
+                    @Override
+                    void loadStack() {
+                        method.load(ITERATOR_TYPE, iterSlot);
+                    }
+
+                    @Override
+                    void consumeStack() {
+                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
+                        convertOptimisticReturnValue();
+                    }
+                }.emit();
             }
         }.store();
         body.accept(this);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Wed Jul 05 20:00:59 2017 +0200
@@ -31,6 +31,7 @@
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.Map;
+
 import jdk.nashorn.internal.IntDeque;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Block;
@@ -158,7 +159,9 @@
 
     CompileUnit popCompileUnit(final CompileUnit oldUnit) {
         assert compileUnits.peek() == oldUnit;
-        compileUnits.pop();
+        final CompileUnit unit = compileUnits.pop();
+        assert unit.hasCode() : "compile unit popped without code";
+        unit.setUsed();
         return compileUnits.isEmpty() ? null : compileUnits.peek();
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Jul 05 20:00:59 2017 +0200
@@ -48,6 +48,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -300,6 +301,7 @@
         }
     },
 
+
     /**
      * Reuse compile units, if they are already present. We are using the same compiler
      * to recompile stuff
@@ -334,6 +336,8 @@
                 if (phases.isRestOfCompilation()) {
                     sb.append("$restOf");
                 }
+                //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what
+                //fills those out anyway. Thus no need for a copy constructor
                 final CompileUnit newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight());
                 log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
                 map.put(oldUnit, newUnit);
@@ -430,8 +434,14 @@
 
             FunctionNode newFunctionNode = fn;
 
+            //root class is special, as it is bootstrapped from createProgramFunction, thus it's skipped
+            //in CodeGeneration - the rest can be used as a working "is compile unit used" metric
+            fn.getCompileUnit().setUsed();
+
             compiler.getLogger().fine("Starting bytecode generation for ", quote(fn.getName()), " - restOf=", phases.isRestOfCompilation());
+
             final CodeGenerator codegen = new CodeGenerator(compiler, phases.isRestOfCompilation() ? compiler.getContinuationEntryPoints() : null);
+
             try {
                 // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program
                 // in the lazy + optimistic world. See CodeGenerator.skipFunction().
@@ -455,12 +465,18 @@
                 final ClassEmitter classEmitter = compileUnit.getClassEmitter();
                 classEmitter.end();
 
+                if (!compileUnit.isUsed()) {
+                    compiler.getLogger().fine("Skipping unused compile unit ", compileUnit);
+                    continue;
+                }
+
                 final byte[] bytecode = classEmitter.toByteArray();
                 assert bytecode != null;
 
                 final String className = compileUnit.getUnitClassName();
+                compiler.addClass(className, bytecode); //classes are only added to the bytecode map if compile unit is used
 
-                compiler.addClass(className, bytecode);
+                CompileUnit.increaseEmitCount();
 
                 // should we verify the generated code?
                 if (senv._verify_code) {
@@ -536,6 +552,9 @@
 
             // initialize function in the compile units
             for (final CompileUnit unit : compiler.getCompileUnits()) {
+                if (!unit.isUsed()) {
+                    continue;
+                }
                 unit.setCode(installedClasses.get(unit.getUnitClassName()));
             }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Wed Jul 05 20:00:59 2017 +0200
@@ -42,6 +42,10 @@
 
     private Class<?> clazz;
 
+    private boolean isUsed;
+
+    private static int emittedUnitCount;
+
     CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
         this.className    = className;
         this.weight       = initialWeight;
@@ -52,6 +56,33 @@
         return new TreeSet<>();
     }
 
+    static void increaseEmitCount() {
+        emittedUnitCount++;
+    }
+
+    public static int getEmittedUnitCount() {
+        return emittedUnitCount;
+    }
+
+    /**
+     * Check if this compile unit is used
+     * @return true if tagged as in use - i.e active code that needs to be generated
+     */
+    public boolean isUsed() {
+        return isUsed;
+    }
+
+    public boolean hasCode() {
+        return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
+    }
+
+    /**
+     * Tag this compile unit as used
+     */
+    public void setUsed() {
+        this.isUsed = true;
+    }
+
     /**
      * Return the class that contains the code for this unit, null if not
      * generated yet
@@ -121,7 +152,8 @@
 
     @Override
     public String toString() {
-        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
+        final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>";
+        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']';
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Wed Jul 05 20:00:59 2017 +0200
@@ -38,7 +38,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -51,8 +50,8 @@
 import java.util.function.Consumer;
 import java.util.logging.Level;
 import jdk.internal.dynalink.support.NameCodec;
-import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
@@ -65,6 +64,7 @@
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -248,6 +248,15 @@
             return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
         }
 
+        @SuppressWarnings("unused") //TODO I'll use this soon
+        private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) {
+            final LinkedList<CompilationPhase> list = new LinkedList<>();
+            for (final CompilationPhase p : phases) {
+                list.add(p == phase ? newPhase : p);
+            }
+            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
+        }
+
         private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
             final LinkedList<CompilationPhase> list = new LinkedList<>();
             for (final CompilationPhase p : phases) {
@@ -473,6 +482,19 @@
         return typeEvaluator.getOptimisticType(node);
     }
 
+    /**
+     * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property names retrieved through
+     * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+     * property name types.
+     * @param expr the expression to test
+     * @return true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property iterators.
+     */
+    boolean hasStringPropertyIterator(final Expression expr) {
+        return typeEvaluator.hasStringPropertyIterator(expr);
+    }
+
     void addInvalidatedProgramPoint(final int programPoint, final Type type) {
         invalidatedProgramPoints.put(programPoint, type);
     }
@@ -675,16 +697,8 @@
     CompileUnit createCompileUnit(final String unitClassName, final long initialWeight) {
         final ClassEmitter classEmitter = new ClassEmitter(context, sourceName, unitClassName, isStrict());
         final CompileUnit  compileUnit  = new CompileUnit(unitClassName, classEmitter, initialWeight);
-
         classEmitter.begin();
 
-        final MethodEmitter initMethod = classEmitter.init(EnumSet.of(Flag.PRIVATE));
-        initMethod.begin();
-        initMethod.load(Type.OBJECT, 0);
-        initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
-        initMethod.returnVoid();
-        initMethod.end();
-
         return compileUnit;
     }
 
@@ -722,13 +736,6 @@
         return name.replace('/', '.');
     }
 
-    RecompilableScriptFunctionData getProgram() {
-        if (compiledFunction == null) {
-            return null;
-        }
-        return compiledFunction.getProgram();
-    }
-
     RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
         return compiledFunction == null ? null : compiledFunction.getScriptFunctionData(functionId);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java	Wed Jul 05 20:00:59 2017 +0200
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getClassName;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.util.HashMap;
@@ -34,6 +32,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -44,7 +43,6 @@
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -208,14 +206,10 @@
 
         assert nestedFunctions != null;
         // Generate the object class and property map in case this function is ever used as constructor
-        final int         fieldCount         = getPaddedFieldCount(newFunctionNode.getThisProperties());
-        final String      allocatorClassName = Compiler.binaryName(getClassName(fieldCount));
-        final PropertyMap allocatorMap       = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
         final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
                 newFunctionNode,
                 compiler.getCodeInstaller(),
-                allocatorClassName,
-                allocatorMap,
+                new AllocatorDescriptor(newFunctionNode.getThisProperties()),
                 nestedFunctions,
                 externalSymbolDepths.get(fnId),
                 internalSymbols.get(fnId)
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -551,13 +551,19 @@
 
         final Expression init = forNode.getInit();
         if(forNode.isForIn()) {
-            forNode.getModify().accept(this);
-            enterTestFirstLoop(forNode, null, init);
+            final JoinPredecessorExpression iterable = forNode.getModify();
+            iterable.accept(this);
+            enterTestFirstLoop(forNode, null, init,
+                    // If we're iterating over property names, and we can discern from the runtime environment
+                    // of the compilation that the object being iterated over must use strings for property
+                    // names (e.g., it is a native JS object or array), then we'll not bother trying to treat
+                    // the property names optimistically.
+                    !forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()));
         } else {
             if(init != null) {
                 init.accept(this);
             }
-            enterTestFirstLoop(forNode, forNode.getModify(), null);
+            enterTestFirstLoop(forNode, forNode.getModify(), null, false);
         }
         return false;
     }
@@ -792,7 +798,8 @@
         return false;
     }
 
-    private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, final Expression iteratorValues) {
+    private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify,
+            final Expression iteratorValues, final boolean iteratorValuesAreObject) {
         final JoinPredecessorExpression test = loopNode.getTest();
         if(isAlwaysFalse(test)) {
             test.accept(this);
@@ -814,8 +821,12 @@
                 jumpToLabel(test, breakLabel);
             }
             if(iteratorValues instanceof IdentNode) {
-                // Receives iterator values; they're currently all objects (JDK-8034954).
-                onAssignment((IdentNode)iteratorValues, LvarType.OBJECT);
+                final IdentNode ident = (IdentNode)iteratorValues;
+                // Receives iterator values; the optimistic type of the iterator values is tracked on the
+                // identifier, but we override optimism if it's known that the object being iterated over will
+                // never have primitive property names.
+                onAssignment(ident, iteratorValuesAreObject ? LvarType.OBJECT :
+                    toLvarType(compiler.getOptimisticType(ident)));
             }
             final Block body = loopNode.getBody();
             body.accept(this);
@@ -955,7 +966,7 @@
         if(whileNode.isDoWhile()) {
             enterDoWhileLoop(whileNode);
         } else {
-            enterTestFirstLoop(whileNode, null, null);
+            enterTestFirstLoop(whileNode, null, null, false);
         }
         return false;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Wed Jul 05 20:00:59 2017 +0200
@@ -71,7 +71,6 @@
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Source;
@@ -93,9 +92,6 @@
 
     private final DebugLogger log;
 
-    // needed only to get unique eval id
-    private final CodeInstaller<?> installer;
-
     /**
      * Constructor.
      */
@@ -143,7 +139,6 @@
             }
         });
 
-        this.installer = compiler.getCodeInstaller();
         this.log       = initLogger(compiler.getContext());
     }
 
@@ -566,16 +561,13 @@
     private String evalLocation(final IdentNode node) {
         final Source source = lc.getCurrentFunction().getSource();
         final int pos = node.position();
-        // Code installer is null when running with --compile-only, use 0 as id in that case
-        final long id = installer == null ? 0 : installer.getUniqueEvalId();
         return new StringBuilder().
             append(source.getName()).
             append('#').
             append(source.getLine(pos)).
             append(':').
             append(source.getColumn(pos)).
-            append("<eval>@").
-            append(id).
+            append("<eval>").
             toString();
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -308,7 +308,7 @@
         newEmptyInit(className, classEmitter);
         newAllocate(className, classEmitter);
 
-        return toByteArray(classEmitter);
+        return toByteArray(className, classEmitter);
     }
 
     /**
@@ -341,7 +341,7 @@
         initWithArguments.returnVoid();
         initWithArguments.end();
 
-        return toByteArray(classEmitter);
+        return toByteArray(className, classEmitter);
     }
 
     /**
@@ -484,15 +484,13 @@
      * @param classEmitter Open class emitter.
      * @return Byte codes for the class.
      */
-    private byte[] toByteArray(final ClassEmitter classEmitter) {
+    private byte[] toByteArray(final String className, final ClassEmitter classEmitter) {
         classEmitter.end();
 
         final byte[] code = classEmitter.toByteArray();
         final ScriptEnvironment env = context.getEnv();
 
-        if (env._print_code && env._print_code_dir == null) {
-            env.getErr().println(ClassEmitter.disassemble(code));
-        }
+        DumpBytecode.dumpBytecode(env, log, code, className);
 
         if (env._verify_code) {
             context.verify(code);
@@ -827,5 +825,45 @@
         return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types));
     }
 
+    /**
+     * Describes the allocator class name and property map for a constructor function with the specified
+     * number of "this" properties that it initializes.
+     *
+     */
+    public static class AllocatorDescriptor {
+        private final String allocatorClassName;
+        private final PropertyMap allocatorMap;
 
+        /**
+         * Creates a new allocator descriptor
+         * @param thisProperties the number of "this" properties that the function initializes
+         */
+        public AllocatorDescriptor(final int thisProperties) {
+            final int paddedFieldCount = getPaddedFieldCount(thisProperties);
+            this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount));
+            this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0);
+        }
+
+        /**
+         * Returns the name of the class that the function allocates
+         * @return the name of the class that the function allocates
+         */
+        public String getAllocatorClassName() {
+            return allocatorClassName;
+        }
+
+        /**
+         * Returns the allocator map for the function.
+         * @return the allocator map for the function.
+         */
+        public PropertyMap getAllocatorMap() {
+            return allocatorMap;
+        }
+
+        @Override
+        public String toString() {
+            return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+                    allocatorMap.size() + "]";
+        }
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -55,6 +55,19 @@
         this.runtimeScope = runtimeScope;
     }
 
+    /**
+     * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property names retrieved through
+     * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+     * property name types.
+     * @param expr the expression to test
+     * @return true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property iterators.
+     */
+    boolean hasStringPropertyIterator(final Expression expr) {
+        return evaluateSafely(expr) instanceof ScriptObject;
+    }
+
     Type getOptimisticType(final Optimistic node) {
         assert compiler.useOptimisticTypes();
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Wed Jul 05 20:00:59 2017 +0200
@@ -277,6 +277,14 @@
     }
 
     /**
+     * Returns the number of statements in the block.
+     * @return the number of statements in the block.
+     */
+    public int getStatementCount() {
+        return statements.size();
+    }
+
+    /**
      * Returns the line number of the first statement in the block.
      * @return the line number of the first statement in the block, or -1 if the block has no statements.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CompileUnitHolder.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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 jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.CompileUnit;
+
+/**
+ * Marker interface for things in the IR that can hold compile units.
+ * {@link CompileUnit}
+ */
+public interface CompileUnitHolder {
+    /**
+     * Return the compile unit held by this instance
+     * @return compile unit
+     */
+    public CompileUnit getCompileUnit();
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Wed Jul 05 20:00:59 2017 +0200
@@ -34,10 +34,8 @@
 
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 import java.util.function.Function;
 import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.CompileUnit;
@@ -48,6 +46,7 @@
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.UserAccessorProperty;
@@ -57,7 +56,7 @@
  * IR representation for function (or script.)
  */
 @Immutable
-public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
+public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
     /** Type used for all FunctionNodes */
     public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
 
@@ -110,8 +109,11 @@
     /** Source of entity. */
     private final Source source;
 
-    /** Unique ID used for recompilation among other things */
-    private final int id;
+    /**
+     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
+     * to skip parsing inner functions.
+     */
+    private final Object endParserState;
 
     /** External function identifier. */
     @Ignore
@@ -256,6 +258,14 @@
     /** trace callsite values in this function? */
     public static final int IS_TRACE_VALUES    = 1 << 26;
 
+    /**
+     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
+     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
+     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
+     * will, however, cache the value of this flag.
+     */
+    public static final int NEEDS_CALLEE       = 1 << 27;
+
     /** extension callsite flags mask */
     public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
         IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
@@ -271,16 +281,9 @@
     /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
     private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
 
-    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval.
-     *  We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */
+    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval. */
     private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL;
 
-    /** Used to signify "null", e.g. if someone asks for the parent of the program node */
-    public static final int NO_FUNCTION_ID = 0;
-
-    /** Where to start assigning global and unique function node ids */
-    public static final int FIRST_FUNCTION_ID = NO_FUNCTION_ID + 1;
-
     /** What is the return type of this function? */
     private Type returnType = Type.UNKNOWN;
 
@@ -288,11 +291,10 @@
      * Constructor
      *
      * @param source     the source
-     * @param id         unique id
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param firstToken first token of the funtion node (including the function declaration)
+     * @param firstToken first token of the function node (including the function declaration)
      * @param namespace  the namespace
      * @param ident      the identifier
      * @param name       the name of the function
@@ -302,7 +304,6 @@
      */
     public FunctionNode(
         final Source source,
-        final int id,
         final int lineNumber,
         final long token,
         final int finish,
@@ -316,7 +317,6 @@
         super(token, finish);
 
         this.source           = source;
-        this.id               = id;
         this.lineNumber       = lineNumber;
         this.ident            = ident;
         this.name             = name;
@@ -331,11 +331,13 @@
         this.body             = null;
         this.thisProperties   = 0;
         this.rootClass        = null;
+        this.endParserState    = null;
     }
 
     private FunctionNode(
         final FunctionNode functionNode,
         final long lastToken,
+        Object endParserState,
         final int flags,
         final String name,
         final Type returnType,
@@ -347,6 +349,7 @@
         final Class<?> rootClass) {
         super(functionNode);
 
+        this.endParserState    = endParserState;
         this.lineNumber       = functionNode.lineNumber;
         this.flags            = flags;
         this.name             = name;
@@ -361,7 +364,6 @@
 
         // the fields below never change - they are final and assigned in constructor
         this.source          = functionNode.source;
-        this.id              = functionNode.id;
         this.ident           = functionNode.ident;
         this.namespace       = functionNode.namespace;
         this.kind            = functionNode.kind;
@@ -429,11 +431,11 @@
     }
 
     /**
-     * Get the unique ID for this function
+     * Get the unique ID for this function within the script file.
      * @return the id
      */
     public int getId() {
-        return id;
+        return position();
     }
 
     /**
@@ -535,6 +537,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -606,6 +609,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -644,15 +648,24 @@
     }
 
     /**
-     * Check if the {@code eval} keyword is used in this function
+     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
      *
-     * @return true if {@code eval} is used
+     * @return true if {@code eval} is called.
      */
     public boolean hasEval() {
         return getFlag(HAS_EVAL);
     }
 
     /**
+     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
+     *
+     * @return true if a nested function calls {@code eval}.
+     */
+    public boolean hasNestedEval() {
+        return getFlag(HAS_NESTED_EVAL);
+    }
+
+    /**
      * Get the first token for this function
      * @return the first token
      */
@@ -741,6 +754,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags |
                             (body.needsScope() ?
                                     FunctionNode.HAS_SCOPE_BLOCK :
@@ -839,6 +853,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -899,6 +914,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -911,6 +927,41 @@
     }
 
     /**
+     * Returns the end parser state for this function.
+     * @return the end parser state for this function.
+     */
+    public Object getEndParserState() {
+        return endParserState;
+    }
+
+    /**
+     * Set the end parser state for this function.
+     * @param lc lexical context
+     * @param endParserState the parser state to set
+     * @return function node or a new one if state was changed
+     */
+    public FunctionNode setEndParserState(final LexicalContext lc, final Object endParserState) {
+        if (this.endParserState == endParserState) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        endParserState,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties, rootClass));
+    }
+
+    /**
      * Get the name of this function
      * @return the name
      */
@@ -934,6 +985,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -999,6 +1051,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -1077,6 +1130,7 @@
             new FunctionNode(
                 this,
                 lastToken,
+                endParserState,
                 flags,
                 name,
                 type,
@@ -1102,6 +1156,7 @@
      * @see Compiler
      * @return the compile unit
      */
+    @Override
     public CompileUnit getCompileUnit() {
         return compileUnit;
     }
@@ -1123,6 +1178,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -1178,6 +1234,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java	Wed Jul 05 20:00:59 2017 +0200
@@ -351,8 +351,7 @@
     }
 
     /**
-     * Get the function for this block. If the block is itself a function
-     * this returns identity
+     * Get the function for this block.
      * @param block block for which to get function
      * @return function for block
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java	Wed Jul 05 20:00:59 2017 +0200
@@ -603,7 +603,7 @@
          * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
          * be split if they are too large, for bytecode generation reasons
          */
-        public static final class ArrayUnit {
+        public static final class ArrayUnit implements CompileUnitHolder {
             /** Compile unit associated with the postsets range. */
             private final CompileUnit compileUnit;
 
@@ -642,6 +642,7 @@
              * The array compile unit
              * @return array compile unit
              */
+            @Override
             public CompileUnit getCompileUnit() {
                 return compileUnit;
             }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitNode.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitNode.java	Wed Jul 05 20:00:59 2017 +0200
@@ -39,7 +39,7 @@
  * Node indicating code is split across classes.
  */
 @Immutable
-public class SplitNode extends LexicalContextStatement implements Labels {
+public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder {
     /** Split node method name. */
     private final String name;
 
@@ -116,6 +116,7 @@
      * Get the compile unit for this split node
      * @return compile unit
      */
+    @Override
     public CompileUnit getCompileUnit() {
         return compileUnit;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Wed Jul 05 20:00:59 2017 +0200
@@ -631,6 +631,24 @@
     }
 
     /**
+     * Returns a method handle that creates a wrapper object for a JS primitive value.
+     *
+     * @param self receiver object
+     * @return method handle to create wrapper objects for primitive receiver
+     */
+    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
+        if (self instanceof String || self instanceof ConsString) {
+            return NativeString.WRAPFILTER;
+        } else if (self instanceof Number) {
+            return NativeNumber.WRAPFILTER;
+        } else if (self instanceof Boolean) {
+            return NativeBoolean.WRAPFILTER;
+        }
+        throw new IllegalArgumentException("Unsupported primitive: " + self);
+    }
+
+
+    /**
      * Create a new empty script object
      *
      * @return the new ScriptObject
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java	Wed Jul 05 20:00:59 2017 +0200
@@ -51,9 +51,9 @@
 public final class NativeBoolean extends ScriptObject {
     private final boolean value;
 
-    // Method handle to create an object wrapper for a primitive boolean
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
-    // Method handle to retrieve the Boolean prototype object
+    /** Method handle to create an object wrapper for a primitive boolean. */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
+    /** Method handle to retrieve the Boolean prototype object. */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     // initialized by nasgen
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Wed Jul 05 20:00:59 2017 +0200
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -697,7 +698,7 @@
                 if (methodHandle != null) {
                     return new GuardedInvocation(
                             methodHandle,
-                            testJSAdaptor(adaptee, findData.getGetter(Object.class, UnwarrantedOptimismException.INVALID_PROGRAM_POINT), findData.getOwner(), func),
+                            testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
                             adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
                 }
              }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java	Wed Jul 05 20:00:59 2017 +0200
@@ -57,9 +57,9 @@
 @ScriptClass("Number")
 public final class NativeNumber extends ScriptObject {
 
-    // Method handle to create an object wrapper for a primitive number
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
-    // Method handle to retrieve the Number prototype object
+    /** Method handle to create an object wrapper for a primitive number. */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
+    /** Method handle to retrieve the Number prototype object. */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     /** ECMA 15.7.3.2 largest positive finite value */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Wed Jul 05 20:00:59 2017 +0200
@@ -71,9 +71,9 @@
 
     private final CharSequence value;
 
-    // Method handle to create an object wrapper for a primitive string
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
-    // Method handle to retrieve the String prototype object
+    /** Method handle to create an object wrapper for a primitive string */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
+    /** Method handle to retrieve the String prototype object */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     // initialized by nasgen
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -326,18 +326,28 @@
     }
 
     /**
-     * Check next token and advance.
+     * Check current token and advance to the next token.
      *
      * @param expected Expected tokenType.
      *
      * @throws ParserException on unexpected token type
      */
     protected final void expect(final TokenType expected) throws ParserException {
+        expectDontAdvance(expected);
+        next();
+    }
+
+    /**
+     * Check current token, but don't advance to the next token.
+     *
+     * @param expected Expected tokenType.
+     *
+     * @throws ParserException on unexpected token type
+     */
+    protected final void expectDontAdvance(final TokenType expected) throws ParserException {
         if (type != expected) {
             throw error(expectMessage(expected));
         }
-
-        next();
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java	Wed Jul 05 20:00:59 2017 +0200
@@ -35,6 +35,7 @@
 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
 import static jdk.nashorn.internal.parser.TokenType.EXECSTRING;
 import static jdk.nashorn.internal.parser.TokenType.FLOATING;
+import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
 import static jdk.nashorn.internal.parser.TokenType.HEXADECIMAL;
 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
@@ -85,6 +86,9 @@
     /** Type of last token added. */
     private TokenType last;
 
+    private final boolean pauseOnFunctionBody;
+    private boolean pauseOnNextLeftBrace;
+
     private static final String SPACETAB = " \t";  // ASCII space and tab
     private static final String LFCR     = "\n\r"; // line feed and carriage return (ctrl-m)
 
@@ -182,20 +186,23 @@
      * @param scripting are we in scripting mode
      */
     public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
-        this(source, 0, source.getLength(), stream, scripting);
+        this(source, 0, source.getLength(), stream, scripting, false);
     }
 
     /**
-     * Contructor
+     * Constructor
      *
      * @param source    the source
      * @param start     start position in source from which to start lexing
      * @param len       length of source segment to lex
      * @param stream    token stream to lex
      * @param scripting are we in scripting mode
+     * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
+     * function body. This is used with the feature where the parser is skipping nested function bodies to
+     * avoid reading ahead unnecessarily when we skip the function bodies.
      */
 
-    public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting) {
+    public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
         super(source.getContent(), 1, start, len);
         this.source      = source;
         this.stream      = stream;
@@ -203,6 +210,8 @@
         this.nested      = false;
         this.pendingLine = 1;
         this.last        = EOL;
+
+        this.pauseOnFunctionBody = pauseOnFunctionBody;
     }
 
     private Lexer(final Lexer lexer, final State state) {
@@ -216,6 +225,7 @@
         pendingLine = state.pendingLine;
         linePosition = state.linePosition;
         last = EOL;
+        pauseOnFunctionBody = false;
     }
 
     static class State extends Scanner.State {
@@ -810,6 +820,9 @@
         final int length = scanIdentifier();
         // Check to see if it is a keyword.
         final TokenType type = TokenLookup.lookupKeyword(content, start, length);
+        if (type == FUNCTION && pauseOnFunctionBody) {
+            pauseOnNextLeftBrace = true;
+        }
         // Add keyword or identifier token.
         add(type, start);
     }
@@ -1597,6 +1610,9 @@
                 // We break to let the parser decide what it is.
                 if (canStartLiteral(type)) {
                     break;
+                } else if (type == LBRACE && pauseOnNextLeftBrace) {
+                    pauseOnNextLeftBrace = false;
+                    break;
                 }
             } else if (Character.isJavaIdentifierStart(ch0) || ch0 == '\\' && ch1 == 'u') {
                 // Scan and add identifier or keyword.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 20:00:59 2017 +0200
@@ -148,7 +148,7 @@
     /** to receive line information from Lexer when scanning multine literals. */
     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 
-    private int nextFunctionId;
+    private RecompilableScriptFunctionData reparsedFunction;
 
     /**
      * Constructor
@@ -171,7 +171,7 @@
      * @param log debug logger if one is needed
      */
     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
-        this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0, log);
+        this(env, source, errors, strict, 0, log);
     }
 
     /**
@@ -181,15 +181,13 @@
      * @param source  source to parse
      * @param errors  error manager
      * @param strict  parser created with strict mode enabled.
-     * @param nextFunctionId  starting value for assigning new unique ids to function nodes
      * @param lineOffset line offset to start counting lines from
      * @param log debug logger if one is needed
      */
-    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset, final DebugLogger log) {
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
         super(source, errors, strict, lineOffset);
         this.env = env;
         this.namespace = new Namespace(env.getNamespace());
-        this.nextFunctionId    = nextFunctionId;
         this.scripting = env._scripting;
         if (this.scripting) {
             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@@ -228,6 +226,16 @@
     }
 
     /**
+     * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
+     * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
+     * This will trigger various special behaviors, such as skipping nested function bodies.
+     * @param reparsedFunction the function being reparsed.
+     */
+    public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
+        this.reparsedFunction = reparsedFunction;
+    }
+
+    /**
      * Execute parse and return the resulting function node.
      * Errors will be thrown and the error manager will contain information
      * if parsing should fail
@@ -264,7 +272,7 @@
 
         try {
             stream = new TokenStream();
-            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions);
+            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null);
             lexer.line = lexer.pendingLine = lineOffset + 1;
             line = lineOffset;
 
@@ -472,7 +480,6 @@
         final FunctionNode functionNode =
             new FunctionNode(
                 source,
-                nextFunctionId++,
                 functionLine,
                 token,
                 Token.descPosition(token),
@@ -2828,10 +2835,14 @@
         FunctionNode functionNode = null;
         long lastToken = 0L;
 
+        final boolean parseBody;
+        Object endParserState = null;
         try {
             // Create a new function block.
             functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine);
-
+            assert functionNode != null;
+            final int functionId = functionNode.getId();
+            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
             // Nashorn extension: expression closures
             if (!env._no_syntax_extensions && type != LBRACE) {
                 /*
@@ -2847,34 +2858,143 @@
                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
                 // EOL uses length field to store the line number
                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
-                final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
-                appendStatement(returnNode);
+                // Only create the return node if we aren't skipping nested functions. Note that we aren't
+                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
+                // they don't end with a single well known token, so it'd be very hard to get correctly (see
+                // the note below for reasoning on skipping happening before instead of after RBRACE for
+                // details).
+                if (parseBody) {
+                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
+                    appendStatement(returnNode);
+                }
                 functionNode.setFinish(lastFinish);
-
             } else {
-                expect(LBRACE);
-
-                // Gather the function elements.
-                final List<Statement> prevFunctionDecls = functionDeclarations;
-                functionDeclarations = new ArrayList<>();
-                try {
-                    sourceElements(false);
-                    addFunctionDeclarations(functionNode);
-                } finally {
-                    functionDeclarations = prevFunctionDecls;
+                expectDontAdvance(LBRACE);
+                if (parseBody || !skipFunctionBody(functionNode)) {
+                    next();
+                    // Gather the function elements.
+                    final List<Statement> prevFunctionDecls = functionDeclarations;
+                    functionDeclarations = new ArrayList<>();
+                    try {
+                        sourceElements(false);
+                        addFunctionDeclarations(functionNode);
+                    } finally {
+                        functionDeclarations = prevFunctionDecls;
+                    }
+
+                    lastToken = token;
+                    if (parseBody) {
+                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
+                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
+                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
+                        // ahead) state.
+                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
+
+                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
+                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
+                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
+                        // will never involve us getting into a weird lexer state, and as such is a great reparse
+                        // point. Typical example of a weird lexer state after RBRACE would be:
+                        //     function this_is_skipped() { ... } "use strict";
+                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
+                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
+                        // we'll rather just restart parsing from this well-known, friendly token instead.
+                    }
                 }
-
-                lastToken = token;
                 expect(RBRACE);
                 functionNode.setFinish(finish);
             }
         } finally {
             functionNode = restoreFunctionNode(functionNode, lastToken);
         }
+
+        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
+
+        if (parseBody) {
+            functionNode = functionNode.setEndParserState(lc, endParserState);
+        } else if (functionNode.getBody().getStatementCount() > 0){
+            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
+            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
+            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
+            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
+            // nested bodies early if we were supposed to skip 'em.
+            functionNode = functionNode.setBody(null, functionNode.getBody().setStatements(null,
+                    Collections.<Statement>emptyList()));
+        }
+
+        if (reparsedFunction != null) {
+            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
+            // eagerly parsed the code. We're doing it because some flags would be set based on the
+            // content of the function, or even content of its nested functions, most of which are normally
+            // skipped during an on-demand compilation.
+            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+            if (data != null) {
+                // Data can be null if when we originally parsed the file, we removed the function declaration
+                // as it was dead code.
+                functionNode = functionNode.setFlags(lc, data.getFunctionFlags());
+                // This compensates for missing markEval() in case the function contains an inner function
+                // that contains eval(), that now we didn't discover since we skipped the inner function.
+                if (functionNode.hasNestedEval()) {
+                    assert functionNode.hasScopeBlock();
+                    functionNode = functionNode.setBody(lc, functionNode.getBody().setNeedsScope(null));
+                }
+            }
+        }
         printAST(functionNode);
         return functionNode;
     }
 
+    private boolean skipFunctionBody(final FunctionNode functionNode) {
+        if (reparsedFunction == null) {
+            // Not reparsing, so don't skip any function body.
+            return false;
+        }
+        // Skip to the RBRACE of this function, and continue parsing from there.
+        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+        if (data == null) {
+            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
+            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
+            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
+            return false;
+        }
+        final ParserState parserState = (ParserState)data.getEndParserState();
+        assert parserState != null;
+
+        stream.reset();
+        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
+        line = parserState.line;
+        linePosition = parserState.linePosition;
+        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
+        // the RBRACE.
+        type = SEMICOLON;
+        k = -1;
+        next();
+
+        return true;
+    }
+
+    /**
+     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
+     * for resuming parsing after skipping a function body.
+     */
+    private static class ParserState {
+        private final int position;
+        private final int line;
+        private final int linePosition;
+
+        ParserState(final int position, final int line, final int linePosition) {
+            this.position = position;
+            this.line = line;
+            this.linePosition = linePosition;
+        }
+
+        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
+            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
+            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
+            return newLexer;
+        }
+    }
+
     private void printAST(final FunctionNode functionNode) {
         if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
             env.getErr().println(new ASTWriter(functionNode));
@@ -3247,6 +3367,9 @@
             } else {
                 lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL);
             }
+            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
+            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
+            // this method when the parser skips a nested function.
             lc.setBlockNeedsScope(lc.getFunctionBody(fn));
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenStream.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenStream.java	Wed Jul 05 20:00:59 2017 +0200
@@ -209,4 +209,8 @@
         in = count;
         buffer = newBuffer;
     }
+
+    void reset() {
+        in = out = count = base = 0;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AllocationStrategy.java	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 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 jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+
+/**
+ * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as
+ * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a
+ * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority
+ * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would
+ * otherwise be lost to identical tuples of (map, className, handle) fields.
+ */
+final class AllocationStrategy implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0));
+
+    /** Allocator map from allocator descriptor */
+    private final PropertyMap allocatorMap;
+
+    /** Name of class where allocator function resides */
+    private final String allocatorClassName;
+
+    /** lazily generated allocator */
+    private transient MethodHandle allocator;
+
+    private AllocationStrategy(final AllocatorDescriptor desc) {
+        this.allocatorMap = desc.getAllocatorMap();
+        // These classes get loaded, so an interned variant of their name is most likely around anyway.
+        this.allocatorClassName = desc.getAllocatorClassName().intern();
+    }
+
+    private boolean matches(final AllocatorDescriptor desc) {
+        return desc.getAllocatorMap().size() == allocatorMap.size() &&
+                desc.getAllocatorClassName().equals(allocatorClassName);
+    }
+
+    static AllocationStrategy get(final AllocatorDescriptor desc) {
+        return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc);
+    }
+
+    PropertyMap getAllocatorMap() {
+        return allocatorMap;
+    }
+
+    ScriptObject allocate(final PropertyMap map) {
+        try {
+            if (allocator == null) {
+                allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName),
+                        CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
+            }
+            return (ScriptObject)allocator.invokeExact(map);
+        } catch (final RuntimeException | Error e) {
+            throw e;
+        } catch (final Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    private Object readResolve() {
+        if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() &&
+                allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) {
+            return DEFAULT_STRATEGY;
+        }
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+                allocatorMap.size() + "]";
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java	Wed Jul 05 20:00:59 2017 +0200
@@ -80,12 +80,6 @@
     public long getUniqueScriptId();
 
     /**
-     * Get next unique eval id
-     * @return unique eval id
-     */
-    public long getUniqueEvalId();
-
-    /**
      * Store a compiled script for later reuse
      * @param source the script source
      * @param mainClassName the main class name
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Jul 05 20:00:59 2017 +0200
@@ -27,7 +27,6 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
-
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -39,6 +38,7 @@
 import java.util.TreeMap;
 import java.util.function.Supplier;
 import java.util.logging.Level;
+
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Wed Jul 05 20:00:59 2017 +0200
@@ -196,16 +196,11 @@
         }
 
         @Override
-        public long getUniqueEvalId() {
-            return context.getUniqueEvalId();
-        }
-
-        @Override
-        public void storeScript(final String classInfoFile, final Source source, final String mainClassName,
+        public void storeScript(final String cacheKey, final Source source, final String mainClassName,
                                 final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
                                 final Object[] constants, final int compilationId) {
             if (context.codeStore != null) {
-                context.codeStore.storeScript(classInfoFile, source, mainClassName, classBytes, initializers, constants, compilationId);
+                context.codeStore.storeScript(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
             }
         }
 
@@ -334,9 +329,6 @@
     /** Unique id for script. Used only when --loader-per-compile=false */
     private final AtomicLong uniqueScriptId;
 
-    /** Unique id for 'eval' */
-    private final AtomicLong uniqueEvalId;
-
     /** Optional class filter to use for Java classes. Can be null. */
     private final ClassFilter classFilter;
 
@@ -450,7 +442,6 @@
             this.uniqueScriptId = new AtomicLong();
         }
         this.errors    = errors;
-        this.uniqueEvalId = new AtomicLong();
 
         // if user passed -classpath option, make a class loader with that and set it as
         // thread context class loader so that script can access classes from that path.
@@ -1190,10 +1181,6 @@
              }, CREATE_LOADER_ACC_CTXT);
     }
 
-    private long getUniqueEvalId() {
-        return uniqueEvalId.getAndIncrement();
-    }
-
     private long getUniqueScriptId() {
         return uniqueScriptId.getAndIncrement();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jul 05 20:00:59 2017 +0200
@@ -29,7 +29,9 @@
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 
 import java.lang.invoke.MethodHandle;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * This class represents the result from a find property search.
@@ -79,25 +81,17 @@
      * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic
      * @return method handle for the getter
      */
-    public MethodHandle getGetter(final Class<?> type, final int programPoint) {
+    public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) {
         final MethodHandle getter;
         if (isValid(programPoint)) {
             getter = property.getOptimisticGetter(type, programPoint);
         } else {
             getter = property.getGetter(type);
         }
-        return getGetterInner(getter);
-    }
-
-    private MethodHandle getGetterInner(final MethodHandle getter) {
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc        = (UserAccessorProperty)property;
-            final ScriptObject         owner     = getOwner();
-            final ScriptObject         container = (owner != null) ? owner : self;
-            return MH.insertArguments(getter, 0, uc.getAccessors(container));
+            return insertAccessorsGetter((UserAccessorProperty) property, request, getter);
         }
         return getter;
-
     }
 
     /**
@@ -111,18 +105,31 @@
      *
      * @return method handle for the getter
      */
-    public MethodHandle getSetter(final Class<?> type, final boolean strict) {
-        final MethodHandle setter = property.getSetter(type, getOwner().getMap());
+    public MethodHandle getSetter(final Class<?> type, final boolean strict, final LinkRequest request) {
+        MethodHandle setter = property.getSetter(type, getOwner().getMap());
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc        = (UserAccessorProperty)property;
-            final ScriptObject         owner     = getOwner();
-            final ScriptObject         container = (owner != null) ? owner : self;
-            return MH.insertArguments(setter, 0, uc.getAccessors(container), strict ? property.getKey() : null);
+            setter =  MH.insertArguments(setter, 1, strict ? property.getKey() : null);
+            return insertAccessorsGetter((UserAccessorProperty) property, request, setter);
         }
 
         return setter;
     }
 
+    // Fold an accessor getter into the method handle of a user accessor property.
+    private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) {
+        MethodHandle superGetter = uap.getAccessorsGetter();
+        if (isInherited()) {
+            superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength());
+        }
+        if (request != null && !(request.getReceiver() instanceof ScriptObject)) {
+            final MethodHandle wrapFilter = Global.getPrimitiveWrapFilter(request.getReceiver());
+            superGetter = MH.filterArguments(superGetter, 0, wrapFilter.asType(wrapFilter.type().changeReturnType(superGetter.type().parameterType(0))));
+        }
+        superGetter = MH.asType(superGetter, superGetter.type().changeParameterType(0, Object.class));
+
+        return MH.foldArguments(mh, superGetter);
+    }
+
     /**
      * Return the {@code ScriptObject} owning of the property:  this means the prototype.
      * @return owner of property
@@ -136,7 +143,7 @@
      * @return appropriate receiver
      */
     public ScriptObject getGetterReceiver() {
-        return property != null && property.hasGetterFunction(prototype) ? self : prototype;
+        return property != null && property instanceof UserAccessorProperty ? self : prototype;
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java	Wed Jul 05 20:00:59 2017 +0200
@@ -28,6 +28,8 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.lang.invoke.MethodHandle;
@@ -370,22 +372,19 @@
      * @param find      property lookup
      * @param receiver  receiver
      * @param desc      callsite descriptor
-     * @param request   link request
-     * @param operator  operator
      *
      * @return resulting getter, or null if failed to create constant
      */
-    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
-        if (GLOBAL_ONLY && !find.getOwner().isGlobal()) {
+    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
+        // Also return null if property may have side effects
+        if ((GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) {
             return null;
         }
 
-        final int programPoint         = NashornCallSiteDescriptor.isOptimistic(desc) ?
-            NashornCallSiteDescriptor.getProgramPoint(desc) :
-            UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
-        final boolean     isOptimistic = programPoint != UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
-        final Class<?>    retType      = desc.getMethodType().returnType();
-        final String      name         = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final boolean  isOptimistic = NashornCallSiteDescriptor.isOptimistic(desc);
+        final int      programPoint = isOptimistic ? getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+        final Class<?> retType      = desc.getMethodType().returnType();
+        final String   name         = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
 
         final Access acc = getOrCreateSwitchPoint(name);
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Jul 05 20:00:59 2017 +0200
@@ -42,6 +42,7 @@
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
 import jdk.nashorn.internal.codegen.TypeMap;
 import jdk.nashorn.internal.codegen.types.Type;
@@ -55,7 +56,6 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
-
 /**
  * This is a subclass that represents a script function that may be regenerated,
  * for example with specialization based on call site types, or lazily generated.
@@ -81,26 +81,29 @@
     /** Token of this function within the source. */
     private final long token;
 
-    /** Allocator map from makeMap() */
-    private final PropertyMap allocatorMap;
+    /**
+     * Represents the allocation strategy (property map, script object class, and method handle) for when
+     * this function is used as a constructor. Note that majority of functions (those not setting any this.*
+     * properties) will share a single canonical "default strategy" instance.
+     */
+    private final AllocationStrategy allocationStrategy;
+
+    /**
+     * Opaque object representing parser state at the end of the function. Used when reparsing outer function
+     * to help with skipping parsing inner functions.
+     */
+    private final Object endParserState;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
     private transient CodeInstaller<ScriptEnvironment> installer;
 
-    /** Name of class where allocator function resides */
-    private final String allocatorClassName;
-
-    /** lazily generated allocator */
-    private transient MethodHandle allocator;
-
     private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
 
     /** Id to parent function if one exists */
     private RecompilableScriptFunctionData parent;
 
-    private final boolean isDeclared;
-    private final boolean isAnonymous;
-    private final boolean needsCallee;
+    /** Copy of the {@link FunctionNode} flags. */
+    private final int functionFlags;
 
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
@@ -119,8 +122,7 @@
      *
      * @param functionNode        functionNode that represents this function code
      * @param installer           installer for code regeneration versions of this function
-     * @param allocatorClassName  name of our allocator class, will be looked up dynamically if used as a constructor
-     * @param allocatorMap        allocator map to seed instances with, when constructing
+     * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor
      * @param nestedFunctions     nested function map
      * @param externalScopeDepths external scope depths
      * @param internalSymbols     internal symbols to method, defined in its scope
@@ -128,30 +130,27 @@
     public RecompilableScriptFunctionData(
         final FunctionNode functionNode,
         final CodeInstaller<ScriptEnvironment> installer,
-        final String allocatorClassName,
-        final PropertyMap allocatorMap,
+        final AllocatorDescriptor allocationDescriptor,
         final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
         final Map<String, Integer> externalScopeDepths,
         final Set<String> internalSymbols) {
 
         super(functionName(functionNode),
               Math.min(functionNode.getParameters().size(), MAX_ARITY),
-              getFlags(functionNode));
+              getDataFlags(functionNode));
 
         this.functionName        = functionNode.getName();
         this.lineNumber          = functionNode.getLineNumber();
-        this.isDeclared          = functionNode.isDeclared();
-        this.needsCallee         = functionNode.needsCallee();
-        this.isAnonymous         = functionNode.isAnonymous();
+        this.functionFlags       = functionNode.getFlags() | (functionNode.needsCallee() ? FunctionNode.NEEDS_CALLEE : 0);
         this.functionNodeId      = functionNode.getId();
         this.source              = functionNode.getSource();
+        this.endParserState      = functionNode.getEndParserState();
         this.token               = tokenFor(functionNode);
         this.installer           = installer;
-        this.allocatorClassName  = allocatorClassName;
-        this.allocatorMap        = allocatorMap;
-        this.nestedFunctions     = nestedFunctions;
-        this.externalScopeDepths = externalScopeDepths;
-        this.internalSymbols     = new HashSet<>(internalSymbols);
+        this.allocationStrategy  = AllocationStrategy.get(allocationDescriptor);
+        this.nestedFunctions     = smallMap(nestedFunctions);
+        this.externalScopeDepths = smallMap(externalScopeDepths);
+        this.internalSymbols     = smallSet(new HashSet<>(internalSymbols));
 
         for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) {
             assert nfn.getParent() == null;
@@ -161,6 +160,27 @@
         createLogger();
     }
 
+    private static <K, V> Map<K, V> smallMap(final Map<K, V> map) {
+        if (map == null || map.isEmpty()) {
+            return Collections.emptyMap();
+        } else if (map.size() == 1) {
+            final Map.Entry<K, V> entry = map.entrySet().iterator().next();
+            return Collections.singletonMap(entry.getKey(), entry.getValue());
+        } else {
+            return map;
+        }
+    }
+
+    private static <T> Set<T> smallSet(final Set<T> set) {
+        if (set == null || set.isEmpty()) {
+            return Collections.emptySet();
+        } else if (set.size() == 1) {
+            return Collections.singleton(set.iterator().next());
+        } else {
+            return set;
+        }
+    }
+
     @Override
     public DebugLogger getLogger() {
         return log;
@@ -190,11 +210,7 @@
      * @return the external symbol table with proto depths
      */
     public int getExternalSymbolDepth(final String symbolName) {
-        final Map<String, Integer> map = externalScopeDepths;
-        if (map == null) {
-            return -1;
-        }
-        final Integer depth = map.get(symbolName);
+        final Integer depth = externalScopeDepths.get(symbolName);
         if (depth == null) {
             return -1;
         }
@@ -202,6 +218,23 @@
     }
 
     /**
+     * Returns the names of all external symbols this function uses.
+     * @return the names of all external symbols this function uses.
+     */
+    public Set<String> getExternalSymbolNames() {
+        return Collections.unmodifiableSet(externalScopeDepths.keySet());
+    }
+
+    /**
+     * Returns the opaque object representing the parser state at the end of this function's body, used to
+     * skip parsing this function when reparsing its containing outer function.
+     * @return the object representing the end parser state
+     */
+    public Object getEndParserState() {
+        return endParserState;
+    }
+
+    /**
      * Get the parent of this RecompilableScriptFunctionData. If we are
      * a nested function, we have a parent. Note that "null" return value
      * can also mean that we have a parent but it is unknown, so this can
@@ -269,7 +302,7 @@
 
     @Override
     public boolean inDynamicContext() {
-        return (flags & IN_DYNAMIC_CONTEXT) != 0;
+        return getFunctionFlag(FunctionNode.IN_DYNAMIC_CONTEXT);
     }
 
     private static String functionName(final FunctionNode fn) {
@@ -293,7 +326,7 @@
         return Token.toDesc(TokenType.FUNCTION, position, length);
     }
 
-    private static int getFlags(final FunctionNode functionNode) {
+    private static int getDataFlags(final FunctionNode functionNode) {
         int flags = IS_CONSTRUCTOR;
         if (functionNode.isStrict()) {
             flags |= IS_STRICT;
@@ -307,37 +340,20 @@
         if (functionNode.isVarArg()) {
             flags |= IS_VARIABLE_ARITY;
         }
-        if (functionNode.inDynamicContext()) {
-            flags |= IN_DYNAMIC_CONTEXT;
-        }
         return flags;
     }
 
     @Override
     PropertyMap getAllocatorMap() {
-        return allocatorMap;
+        return allocationStrategy.getAllocatorMap();
     }
 
     @Override
     ScriptObject allocate(final PropertyMap map) {
-        try {
-            ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
-            return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
-        } catch (final RuntimeException | Error e) {
-            throw e;
-        } catch (final Throwable t) {
-            throw new RuntimeException(t);
-        }
-    }
-
-    private void ensureHasAllocator() throws ClassNotFoundException {
-        if (allocator == null && allocatorClassName != null) {
-            this.allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
-        }
+        return allocationStrategy.allocate(map);
     }
 
     FunctionNode reparse() {
-        final boolean isProgram = functionNodeId == FunctionNode.FIRST_FUNCTION_ID;
         // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node
         final int descPosition = Token.descPosition(token);
         final Context context = Context.getContextTrusted();
@@ -346,18 +362,27 @@
             source,
             new Context.ThrowErrorManager(),
             isStrict(),
-            functionNodeId - (isProgram ? 0 : 1),
             lineNumber - 1,
             context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
 
-        if (isAnonymous) {
+        if (getFunctionFlag(FunctionNode.IS_ANONYMOUS)) {
             parser.setFunctionName(functionName);
         }
+        parser.setReparsedFunction(this);
 
-        final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, Token.descLength(token), true);
-        // Parser generates a program AST even if we're recompiling a single function, so when we are only recompiling a
-        // single function, extract it from the program.
-        return (isProgram ? program : extractFunctionFromScript(program)).setName(null, functionName);
+        final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition,
+                Token.descLength(token), true);
+        // Parser generates a program AST even if we're recompiling a single function, so when we are only
+        // recompiling a single function, extract it from the program.
+        return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
+    }
+
+    private boolean getFunctionFlag(final int flag) {
+        return (functionFlags & flag) != 0;
+    }
+
+    private boolean isProgram() {
+        return getFunctionFlag(FunctionNode.IS_PROGRAM);
     }
 
     TypeMap typeMap(final MethodType fnCallSiteType) {
@@ -546,7 +571,7 @@
         assert fns.size() == 1 : "got back more than one method in recompilation";
         final FunctionNode f = fns.iterator().next();
         assert f.getId() == functionNodeId;
-        if (!isDeclared && f.isDeclared()) {
+        if (!getFunctionFlag(FunctionNode.IS_DECLARED) && f.isDeclared()) {
             return f.clearFlag(null, FunctionNode.IS_DECLARED);
         }
         return f;
@@ -669,7 +694,15 @@
 
     @Override
     public boolean needsCallee() {
-        return needsCallee;
+        return getFunctionFlag(FunctionNode.NEEDS_CALLEE);
+    }
+
+    /**
+     * Returns the {@link FunctionNode} flags associated with this function data.
+     * @return the {@link FunctionNode} flags associated with this function data.
+     */
+    public int getFunctionFlags() {
+        return functionFlags;
     }
 
     @Override
@@ -721,21 +754,6 @@
     }
 
     /**
-     * Get the uppermost parent, the program, for this data
-     * @return program
-     */
-    public RecompilableScriptFunctionData getProgram() {
-        RecompilableScriptFunctionData program = this;
-        while (true) {
-            final RecompilableScriptFunctionData p = program.getParent();
-            if (p == null) {
-                return program;
-            }
-            program = p;
-        }
-    }
-
-    /**
      * Check whether a certain name is a global symbol, i.e. only exists as defined
      * in outermost scope and not shadowed by being parameter or assignment in inner
      * scopes
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Wed Jul 05 20:00:59 2017 +0200
@@ -90,8 +90,6 @@
     public static final int USES_THIS      = 1 << 4;
     /** Is this a variable arity function? */
     public static final int IS_VARIABLE_ARITY = 1 << 5;
-    /** Is this declared in a dynamic context */
-    public static final int IN_DYNAMIC_CONTEXT = 1 << 6;
 
     /** Flag for strict or built-in functions */
     public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jul 05 20:00:59 2017 +0200
@@ -1050,7 +1050,7 @@
     }
 
     private static int getIntValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(int.class, programPoint);
+        final MethodHandle getter = find.getGetter(int.class, programPoint, null);
         if (getter != null) {
             try {
                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1065,7 +1065,7 @@
     }
 
     private static long getLongValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(long.class, programPoint);
+        final MethodHandle getter = find.getGetter(long.class, programPoint, null);
         if (getter != null) {
             try {
                 return (long)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1080,7 +1080,7 @@
     }
 
     private static double getDoubleValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(double.class, programPoint);
+        final MethodHandle getter = find.getGetter(double.class, programPoint, null);
         if (getter != null) {
             try {
                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1971,7 +1971,7 @@
             }
         }
 
-        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc, request, operator);
+        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc);
         if (cinv != null) {
             return cinv;
         }
@@ -1983,7 +1983,7 @@
                 NashornCallSiteDescriptor.getProgramPoint(desc) :
                 UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
-        mh = find.getGetter(returnType, programPoint);
+        mh = find.getGetter(returnType, programPoint, request);
         // Get the appropriate guard for this callsite and property.
         final MethodHandle guard = NashornGuards.getGuard(this, property, desc, explicitInstanceOfCheck);
         final ScriptObject owner = find.getOwner();
@@ -1995,8 +1995,9 @@
             mh = Lookup.emptyGetter(returnType);
             protoSwitchPoint = getProtoSwitchPoint(name, owner);
         } else if (!find.isSelf()) {
-            assert mh.type().returnType().equals(returnType) : "returntype mismatch for getter " + mh.type().returnType() + " != " + returnType;
-            if (!property.hasGetterFunction(owner)) {
+            assert mh.type().returnType().equals(returnType) :
+                    "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
+            if (!(property instanceof UserAccessorProperty)) {
                 // Add a filter that replaces the self object with the prototype owning the property.
                 mh = addProtoFilter(mh, find.getProtoChainLength());
             }
@@ -2167,7 +2168,7 @@
             }
         }
 
-        final GuardedInvocation inv = new SetMethodCreator(this, find, desc, explicitInstanceOfCheck).createGuardedInvocation();
+        final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation();
 
         final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request);
         if (cinv != null) {
@@ -2320,13 +2321,13 @@
                         find.isSelf()?
                             getKnownFunctionPropertyGuardSelf(
                                 getMap(),
-                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 func)
                             :
                             //TODO this always does a scriptobject check
                             getKnownFunctionPropertyGuardProto(
                                 getMap(),
-                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 find.getProtoChainLength(),
                                 func),
                         getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,6 +33,7 @@
 import java.lang.invoke.SwitchPoint;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
@@ -48,7 +49,7 @@
     private final FindProperty       find;
     private final CallSiteDescriptor desc;
     private final Class<?>           type;
-    private final boolean            explicitInstanceOfCheck;
+    private final LinkRequest        request;
 
     /**
      * Creates a new property setter method creator.
@@ -56,14 +57,15 @@
      * @param find a result of a {@link ScriptObject#findProperty(String, boolean)} on the object for the property we
      * want to create a setter for. Can be null if the property does not yet exist on the object.
      * @param desc the descriptor of the call site that triggered the property setter lookup
+     * @param request the link request
      */
-    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) {
-        this.sobj = sobj;
-        this.map  = sobj.getMap();
-        this.find = find;
-        this.desc = desc;
-        this.type = desc.getMethodType().parameterType(1);
-        this.explicitInstanceOfCheck = explicitInstanceOfCheck;
+    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final LinkRequest request) {
+        this.sobj    = sobj;
+        this.map     = sobj.getMap();
+        this.find    = find;
+        this.desc    = desc;
+        this.type    = desc.getMethodType().parameterType(1);
+        this.request = request;
 
     }
 
@@ -111,6 +113,7 @@
             // getGuard() and getException() either both return null, or neither does. The reason for that is that now
             // getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
             // relink on ClassCastException.
+            final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request);
             return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
                     (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
         }
@@ -140,6 +143,7 @@
 
     private SetMethod createExistingPropertySetter() {
         final Property property = find.getProperty();
+        final boolean isStrict  = NashornCallSiteDescriptor.isStrict(desc);
         final MethodHandle methodHandle;
 
         if (NashornCallSiteDescriptor.isDeclaration(desc)) {
@@ -152,7 +156,7 @@
             final PropertyMap oldMap = getMap();
             final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION);
             final PropertyMap newMap = oldMap.replaceProperty(property, newProperty);
-            final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, NashornCallSiteDescriptor.isStrict(desc));
+            final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request);
             final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type());
 
             // cas map used as guard, if true that means we can do the set fast
@@ -161,14 +165,14 @@
             casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
             methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter);
         } else {
-            methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc));
+            methodHandle = find.getSetter(type, isStrict, request);
         }
 
         assert methodHandle != null;
         assert property     != null;
 
         final MethodHandle boundHandle;
-        if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) {
+        if (!(property instanceof UserAccessorProperty) && find.isInherited()) {
             boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
         } else {
             boundHandle = methodHandle;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java	Wed Jul 05 20:00:59 2017 +0200
@@ -33,6 +33,8 @@
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
+
+import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
@@ -189,7 +191,7 @@
             maxKeyLength++;
 
             final StringBuilder sb = new StringBuilder();
-            sb.append("Accumulated complation phase Timings:\n\n");
+            sb.append("Accumulated compilation phase timings:\n\n");
             for (final Map.Entry<String, Long> entry : timings.entrySet()) {
                 int len;
 
@@ -224,6 +226,9 @@
                 append((int)(knownTime * 100.0 / total)).
                 append("%])");
 
+            sb.append("\n\nEmitted compile units: ").
+                append(CompileUnit.getEmittedUnitCount());
+
             return sb.toString();
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Jul 05 20:00:59 2017 +0200
@@ -34,8 +34,8 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.util.concurrent.Callable;
-import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -48,7 +48,7 @@
 
     private static final long serialVersionUID = -5928687246526840321L;
 
-    static class Accessors {
+    static final class Accessors {
         Object getter;
         Object setter;
 
@@ -67,20 +67,20 @@
         }
     }
 
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
     /** Getter method handle */
-    private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorGetter", Object.class, Accessors.class, Object.class);
+    private final static MethodHandle INVOKE_GETTER_ACCESSOR = findOwnMH_S("invokeGetterAccessor", Object.class, Accessors.class, Object.class);
 
     /** Setter method handle */
-    private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorSetter", void.class, Accessors.class, String.class, Object.class, Object.class);
+    private final static MethodHandle INVOKE_SETTER_ACCESSOR = findOwnMH_S("invokeSetterAccessor", void.class, Accessors.class, String.class, Object.class, Object.class);
 
     /** Dynamic invoker for getter */
-    private static final Object INVOKE_UA_GETTER = new Object();
+    private static final Object GETTER_INVOKER_KEY = new Object();
 
     private static MethodHandle getINVOKE_UA_GETTER() {
 
-        return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER,
+        return Context.getGlobal().getDynamicInvoker(GETTER_INVOKER_KEY,
                 new Callable<MethodHandle>() {
                     @Override
                     public MethodHandle call() {
@@ -91,10 +91,10 @@
     }
 
     /** Dynamic invoker for setter */
-    private static Object INVOKE_UA_SETTER = new Object();
+    private static Object SETTER_INVOKER_KEY = new Object();
 
     private static MethodHandle getINVOKE_UA_SETTER() {
-        return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
+        return Context.getGlobal().getDynamicInvoker(SETTER_INVOKER_KEY,
                 new Callable<MethodHandle>() {
                     @Override
                     public MethodHandle call() {
@@ -190,7 +190,7 @@
 
     @Override
     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
-        return userAccessorGetter(getAccessors((owner != null) ? owner : self), self);
+        return invokeGetterAccessor(getAccessors((owner != null) ? owner : self), self);
     }
 
     @Override
@@ -210,13 +210,13 @@
 
     @Override
     public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
-        userAccessorSetter(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
+        invokeSetterAccessor(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
     }
 
     @Override
     public MethodHandle getGetter(final Class<?> type) {
         //this returns a getter on the format (Accessors, Object receiver)
-        return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type);
+        return Lookup.filterReturnType(INVOKE_GETTER_ACCESSOR, type);
     }
 
     @Override
@@ -260,7 +260,7 @@
 
     @Override
     public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
-        return USER_ACCESSOR_SETTER.methodHandle();
+        return INVOKE_SETTER_ACCESSOR;
     }
 
     @Override
@@ -269,11 +269,21 @@
         return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
     }
 
+    /**
+     * Get the getter for the {@code Accessors} object.
+     * This is the the super {@code Object} type getter with {@code Accessors} return type.
+     *
+     * @return The getter handle for the Accessors
+     */
+    MethodHandle getAccessorsGetter() {
+        return super.getGetter(Object.class).asType(MethodType.methodType(Accessors.class, Object.class));
+    }
+
     // User defined getter and setter are always called by "dyn:call". Note that the user
     // getter/setter may be inherited. If so, proto is bound during lookup. In either
     // inherited or self case, slot is also bound during lookup. Actual ScriptFunction
     // to be called is retrieved everytime and applied.
-    static Object userAccessorGetter(final Accessors gs, final Object self) {
+    private static Object invokeGetterAccessor(final Accessors gs, final Object self) {
         final Object func = gs.getter;
         if (func instanceof ScriptFunction) {
             try {
@@ -288,7 +298,7 @@
         return UNDEFINED;
     }
 
-    static void userAccessorSetter(final Accessors gs, final String name, final Object self, final Object value) {
+    private static void invokeSetterAccessor(final Accessors gs, final String name, final Object self, final Object value) {
         final Object func = gs.setter;
         if (func instanceof ScriptFunction) {
             try {
@@ -303,4 +313,8 @@
         }
     }
 
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(LOOKUP, UserAccessorProperty.class, name, MH.type(rtype, types));
+    }
+
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Wed Jul 05 20:00:59 2017 +0200
@@ -32,11 +32,10 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.internal.dynalink.support.Guards;
-import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.FindProperty;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UserAccessorProperty;
 
 /**
  * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and
@@ -86,15 +85,6 @@
                                                     final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
                                                     final MethodHandle protoFilter) {
         final CallSiteDescriptor desc = request.getCallSiteDescriptor();
-        final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
-        if ("setProp".equals(operator) || "setElem".equals(operator)) {
-            final MethodType type = desc.getMethodType();
-            MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1)));
-            if (type.parameterCount() == 3) {
-                method = MH.dropArguments(method, 2, type.parameterType(2));
-            }
-            return new GuardedInvocation(method, guard);
-        }
 
         if(desc.getNameTokenCount() > 2) {
             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
@@ -102,7 +92,7 @@
             if(find == null) {
                 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
                 return null;
-            } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) {
+            } else if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
                 // If property is found in the prototype object bind the method handle directly to
                 // the proto filter instead of going through wrapper instantiation below.
                 final ScriptObject proto = wrappedReceiver.getProto();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Wed Jul 05 20:00:59 2017 +0200
@@ -246,7 +246,7 @@
 
             // For each file on the command line.
             for (final String fileName : files) {
-                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse();
+                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, 0, context.getLogger(Parser.class)).parse();
 
                 if (errors.getNumberOfErrors() != 0) {
                     return COMPILATION_ERROR;
--- a/nashorn/test/script/basic/JDK-8030182_2.js	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8030182_2.js	Wed Jul 05 20:00:59 2017 +0200
@@ -41,6 +41,6 @@
 try {
     eval(str);
 } catch (e) {
-    print(e.stack.replace(/\\/g, '/').replace(/<eval>@[0-9]+/, '<eval>@<id>'));
+    print(e.stack.replace(/\\/g, '/'));
 }
 
--- a/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -1,3 +1,3 @@
 ReferenceError: "g" is not defined
-	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@<id>:-1)
+	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>:-1)
 	at <program> (test/script/basic/JDK-8030182_2.js:42)
--- a/nashorn/test/script/basic/JDK-8048079_1.js	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- *
- * 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-8048079: Persistent code store is broken after optimistic types merge
- *
- * @test
- * @run
- * @option -pcc
- * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
- * @fork
- */
-
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
--- a/nashorn/test/script/basic/JDK-8048079_1.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_1a.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_1a.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_1b.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_1b.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- a/nashorn/test/script/basic/JDK-8048079_2.js	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- *
- * 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-8048079: Persistent code store is broken after optimistic types merge
- *
- * @test
- * @run
- * @option -pcc
- * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
- * @fork
- */
-
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
--- a/nashorn/test/script/basic/JDK-8048079_2.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_2a.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8048079: Persistent code store is broken after optimistic types merge.
+ * Same script as JDK-8048079_1a.js to exercise code cache.
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_2a.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_2b.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8048079: Persistent code store is broken after optimistic types merge
+ * Same script as JDK-8048079_1b.js to exercise code cache again.
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8048079_2b.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058179.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ * 
+ * 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-8058179: Global constants get in the way of self-modifying properties
+ *
+ * @test
+ * @run
+ */
+
+var global = this;
+
+Object.defineProperty(global, "value", {
+    get: function() {
+        print("getting value");
+        global["value"] = "value 2";
+        return "value 1";
+    },
+    set: function(value) {
+        print("setting value: " + value);
+        delete global["value"];
+        global["value"] = value;
+    },
+    configurable: true
+});
+
+print(value);
+print(value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058179.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,4 @@
+getting value
+setting value: value 2
+value 1
+value 2
--- a/nashorn/test/script/basic/es6/const-empty.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/es6/const-empty.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>@1:2:7 Missing assignment to constant "x"
+SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>:2:7 Missing assignment to constant "x"
 const x;
        ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/const-redeclare-extra.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 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.
+ * 
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    "use strict";
+    const x = 2;
+    var x = {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    var x = 2;
+    const x = {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    function x () {}
+    const x = 5;
+CODE)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/const-redeclare-extra.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,9 @@
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
+    var x = {};
+        ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared
+    function x () {}
+             ^
--- a/nashorn/test/script/basic/es6/const-redeclare.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/es6/const-redeclare.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>@1:2:6 Variable "x" has already been declared
+SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>:2:6 Variable "x" has already been declared
 const x = 2;
       ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-redeclare-extra.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, 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.
+ * 
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    "use strict";
+    let x = 2;
+    const x = function (a,b,c) {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    let x = {};
+    var x = 2;
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    var x = 2;
+    let x = undefined;
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    const x = function (){};
+    let x = {};
+CODE)
+
+
+tryIt(<<CODE
+    "use strict";
+    let a = 2;
+    function a () {};
+CODE)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-redeclare-extra.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,15 @@
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
+    let x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
+    const x = function (){};
+          ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared
+    function a () {};
+             ^
--- a/nashorn/test/script/basic/es6/let-redeclare.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/es6/let-redeclare.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>@1:2:4 Variable "x" has already been declared
+SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>:2:4 Variable "x" has already been declared
 let x = 2;
     ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_const_closure.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt(code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+
+tryIt(<<CODE
+    function a () {
+        this.val = 41
+        let self = this
+        this.b = function () {
+            return self.val;
+        }
+    }
+    c = new a()
+    print(c.b.call(null))
+CODE)
+
+
+tryIt(<<CODE
+        function a () {
+            this.val = 42
+            let self = this
+            this.b = function () {
+                return this.val;
+            }.bind(self)
+        }
+        c = new a()
+        print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+    function a () {
+        this.val = 43
+        const self = this
+        this.b = function () {
+            return self.val;
+        }
+    }
+    c = new a()
+    print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+        function a () {
+            this.val = 44
+            const self = this
+            this.b = function () {
+                return this.val;
+            }.bind(self)
+        }
+        c = new a()
+        print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+       let a = {name : 'test'}
+       let f = function () {
+            print(this.name)
+       }
+       let nf = f.bind(a)
+       nf()
+       if (true) {
+            let a = null
+            nf()
+       }
+       nf()
+CODE)
+
+
+tryIt(<<CODE
+       let arr = []
+       for (let i = 0; i < 3; i++) {
+           arr[i] = function(){return i;}
+       }
+       for (let i in arr) {
+            print(arr[i]())
+       }
+       arr = []
+       for (var i = 0; i < 3; i++) {
+            (function(i){
+                arr[i] = function(){return i;}
+            })(i)
+       }
+       for (let i in arr) {
+           print(arr[i]())
+       }
+CODE)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_const_closure.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,13 @@
+41
+42
+43
+44
+test
+test
+test
+3
+3
+3
+0
+1
+2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_const_reuse.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+     try {
+         eval(code)
+     } catch (e) {
+         print(e)
+     }
+}
+
+tryIt(<<CODE
+    let a = 23
+    if (true) {
+        a--
+        let a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    const a = 23
+    if (true) {
+        a--
+        const a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    let a = 23
+    if (true) {
+        a--
+        const a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    const a = 23
+    if (true) {
+        a--
+        let a = 43;
+    }
+CODE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_const_reuse.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,8 @@
+ReferenceError: "a" is not defined
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+        a--
+        ^
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+        a--
+        ^
+ReferenceError: "a" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_different_types.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010, 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.
+ * 
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    let a = function () {  var a = "Hello World!"; return a; }
+    print(typeof a)
+    {
+        let a = 34;
+        print(typeof a)
+        if (true) {
+            let c = 54.7
+            var d = c
+            print(typeof c)
+            print(typeof d)
+        }
+    }
+    print(typeof a)
+    print(typeof a())
+    print(typeof c)
+    print(typeof d)
+    print(d)
+CODE)
+
+tryIt(<<CODE
+    let a = {}
+    if (true) {
+        function a () {
+            print (typeof a)
+            return 'Hello World!'
+        }
+        print(typeof a)
+        print(a())
+    }
+    print(typeof a)
+CODE)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_different_types.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,13 @@
+function
+number
+number
+number
+function
+string
+undefined
+number
+54.7
+function
+function
+Hello World!
+object
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_loops.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+      let a = 2;
+      do {
+        a--;
+        let b = a;
+      } while (a > 0);
+      print(a)
+      print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2
+       while(a > 0) {
+            a--
+            let b = a
+       }
+       print(a)
+       print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2
+       while(a > 0) {
+            a--
+            const b = a
+       }
+       print(a)
+       print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2;
+       do {
+         a--;
+         const b = a;
+       } while (a > 0);
+       print(a)
+       print(b)
+CODE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let_loops.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,8 @@
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
--- a/nashorn/test/script/basic/optimistic_check_type.js	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/optimistic_check_type.js	Wed Jul 05 20:00:59 2017 +0200
@@ -36,13 +36,18 @@
 
 // Testing conditional operator
 print(inspect("" ? b : x.a, "ternary operator"))
-print(inspect(x.b ? b : x.a, "ternary operator"))
-print(inspect(c ? b : a, "ternary operator"))
-print(inspect(!c ? b : a, "ternary operator"))
-print(inspect(d ? b : x.c, "ternary operator"))
+var b1 = b;
+print(inspect(x.b ? b1 : x.a, "ternary operator"))
+var b2 = b;
+print(inspect(c ? b2 : a, "ternary operator"))
+var b3 = b;
+print(inspect(!c ? b3 : a, "ternary operator"))
+var b4 = b;
+print(inspect(d ? b4 : x.c, "ternary operator"))
 print(inspect(x.c ? a : c, "ternary operator"))
 print(inspect(c ? d : a, "ternary operator"))
-print(inspect(c ? +a : b, "ternary operator"))
+var b5 = b;
+print(inspect(c ? +a : b5, "ternary operator"))
 
 // Testing format methods
 print(inspect(b.toFixed(2), "global double toFixed()"))
@@ -53,11 +58,14 @@
 print(inspect(trees[1], "member object"))
 trees[1] = undefined;
 print(inspect(trees[1], "member undefined"))
-print(inspect(1 in trees ? b : a, "conditional on array member"))
+var b6=b;
+print(inspect(1 in trees ? b6 : a, "conditional on array member"))
 delete trees[2]
-print(inspect(2 in trees ? b : a, "conditional on array member"))
+var b7=b;
+print(inspect(2 in trees ? b7 : a, "conditional on array member"))
 print(inspect(3 in trees ? trees[2]="bay" : a, "conditional on array member"))
-print(inspect("oak" in trees ? b : a, "conditional on array member"))
+var b8=b;
+print(inspect("oak" in trees ? b8 : a, "conditional on array member"))
 
 // Testing nested functions and return value
 function f1() {
--- a/nashorn/test/script/basic/splitter.js	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/splitter.js	Wed Jul 05 20:00:59 2017 +0200
@@ -30,7 +30,5 @@
  * @fork
  */
 
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
 load(__DIR__ + 'NASHORN-689.js');
 load(__DIR__ + 'NASHORN-58.js');
--- a/nashorn/test/script/basic/splitter.js.EXPECTED	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/script/basic/splitter.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -1,6 +1,3 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
 a=10
 a=9
 a=8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/splitter_prototype.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * 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 various scripts with low splitter threshold
+ *
+ * @test
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.prototype
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/splitter_prototype.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/splitter_yui.js	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * 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 various scripts with low splitter threshold
+ *
+ * @test
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.yui
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/splitter_yui.js.EXPECTED	Wed Jul 05 20:00:59 2017 +0200
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Wed Jul 05 20:00:59 2017 +0200
@@ -407,6 +407,75 @@
         Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
     }
 
+
+    /**
+     * Test multi-threaded access to prototype user accessor properties for shared script classes with multiple globals.
+     */
+    @Test
+    public static void multiThreadedAccessorTest() throws ScriptException, InterruptedException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Bindings b = e.createBindings();
+        final ScriptContext origContext = e.getContext();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'original context' })", origContext);
+        e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'new context', configurable: true })", newCtxt);
+        final String sharedScript = "({}).foo";
+
+        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+
+        final Object obj3 = e.eval("delete Object.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+        assertEquals(obj3, "newer context");
+        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+        t3.start();
+        t4.start();
+        t3.join();
+        t4.join();
+    }
+
+    /**
+     * Test multi-threaded access to primitive prototype user accessor properties for shared script classes with multiple globals.
+     */
+    @Test
+    public static void multiThreadedPrimitiveAccessorTest() throws ScriptException, InterruptedException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Bindings b = e.createBindings();
+        final ScriptContext origContext = e.getContext();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'original context' })", origContext);
+        e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'new context' })", newCtxt);
+        final String sharedScript = "''.foo";
+
+        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+
+        final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+        assertEquals(obj3, "newer context");
+        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+        t3.start();
+        t4.start();
+        t3.join();
+        t4.join();
+    }
+
     /**
      * Test multi-threaded scope function invocation for shared script classes with multiple globals.
      */
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Sep 11 14:29:01 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Wed Jul 05 20:00:59 2017 +0200
@@ -261,14 +261,17 @@
                     isTest = false;
                     isNotTest = true;
                     break;
-                case "@runif":
-                    if (System.getProperty(scanner.next()) != null) {
+                case "@runif": {
+                    final String prop = scanner.next();
+                    if (System.getProperty(prop) != null) {
                         shouldRun = true;
                     } else {
+                        factory.log("WARNING: (" + prop + ") skipping " + testFile);
                         isTest = false;
                         isNotTest = true;
                     }
                     break;
+                }
                 case "@run":
                     shouldRun = true;
                     break;