Merge
authorduke
Wed, 05 Jul 2017 18:57:52 +0200 (2017-07-05)
changeset 17793 a08d0f5b08bc
parent 17792 a233c04832cf (current diff)
parent 17791 a700a34fd839 (diff)
child 17814 3c57e9e1a5a4
Merge
jaxp/src/com/sun/org/apache/xerces/internal/xinclude/ObjectFactory.java
jaxp/src/com/sun/org/apache/xml/internal/serialize/ObjectFactory.java
jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh
nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CTypeNode.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CallNode.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchGreedyBacktrack.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchRailsRegs.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchSeveralRegexps.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Reduce.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/AsciiTables.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java
nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/Ptr.java
nashorn/src/netscape/javascript/JSObject.java
--- a/.hgtags-top-repo	Thu May 30 10:58:13 2013 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 18:57:52 2017 +0200
@@ -213,3 +213,4 @@
 892a0196d10c67f3a12f0eefb0bb536e423d8868 jdk8-b89
 69b773a221b956a3386933ecdbfeccee0edeac47 jdk8-b90
 cb51fb4789ac0b8be4056482077ddfb8f3bd3805 jdk8-b91
+3a36c926a7aafa9d4a892a45ef3678e87ad8359b jdk8-b92
--- a/common/autoconf/basics.m4	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/basics.m4	Wed Jul 05 18:57:52 2017 +0200
@@ -72,7 +72,7 @@
       AC_MSG_ERROR([The path of $1, which resolves as "$path", is not found.])
     fi
 
-    $1="`cd "$path"; $THEPWDCMD`" 
+    $1="`cd "$path"; $THEPWDCMD -L`" 
   fi
 ])
 
@@ -169,10 +169,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME [$]$1`
             sym_link_file=`$BASENAME [$]$1`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -183,7 +183,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -264,7 +264,6 @@
 BASIC_REQUIRE_PROG(MKTEMP, mktemp)
 BASIC_REQUIRE_PROG(MV, mv)
 BASIC_REQUIRE_PROG(PRINTF, printf)
-BASIC_REQUIRE_PROG(THEPWDCMD, pwd)
 BASIC_REQUIRE_PROG(RM, rm)
 BASIC_REQUIRE_PROG(SH, sh)
 BASIC_REQUIRE_PROG(SORT, sort)
@@ -297,6 +296,10 @@
 # Always force rm.
 RM="$RM -f"
 
+# pwd behaves differently on various platforms and some don't support the -L flag.
+# Always use the bash builtin pwd to get uniform behavior.
+THEPWDCMD=pwd
+
 # These are not required on all platforms
 AC_PATH_PROG(CYGPATH, cygpath)
 AC_PATH_PROG(READLINK, readlink)
@@ -309,13 +312,12 @@
 [
 # Locate the directory of this script.
 SCRIPT="[$]0"
-BASIC_REMOVE_SYMBOLIC_LINKS(SCRIPT)
-AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD`
+AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD -L`
 
 # Where is the source? It is located two levels above the configure script.
 CURDIR="$PWD"
 cd "$AUTOCONF_DIR/../.."
-SRC_ROOT="`$THEPWDCMD`"
+SRC_ROOT="`$THEPWDCMD -L`"
 
 if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
   PATH_SEP=";"
@@ -374,13 +376,9 @@
         [ CONF_NAME=${with_conf_name} ])
 
 # Test from where we are running configure, in or outside of src root.
-# To enable comparison of directories, CURDIR needs to be symlink free
-# just like SRC_ROOT already is
-NOSYM_CURDIR="$CURDIR"
-BASIC_REMOVE_SYMBOLIC_LINKS(NOSYM_CURDIR)
-if test "x$NOSYM_CURDIR" = "x$SRC_ROOT" || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common" \
-        || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/autoconf" \
-        || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
+if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \
+        || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" \
+        || test "x$CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
     # We are running configure from the src root.
     # Create a default ./build/target-variant-debuglevel output root.
     if test "x${CONF_NAME}" = x; then
@@ -617,6 +615,20 @@
 
 if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
   BASIC_REQUIRE_PROG(XATTR, xattr)
+  AC_PATH_PROG(CODESIGN, codesign)
+  if test "x$CODESIGN" != "x"; then
+    # Verify that the openjdk_codesign certificate is present
+    AC_MSG_CHECKING([if openjdk_codesign certificate is present])
+    rm -f codesign-testfile
+    touch codesign-testfile
+    codesign -s openjdk_codesign codesign-testfile 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD || CODESIGN=
+    rm -f codesign-testfile
+    if test "x$CODESIGN" = x; then
+      AC_MSG_RESULT([no])
+    else
+      AC_MSG_RESULT([yes])
+    fi
+  fi
 fi
 ])
 
--- a/common/autoconf/basics_windows.m4	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/basics_windows.m4	Wed Jul 05 18:57:52 2017 +0200
@@ -300,7 +300,7 @@
 # Setup basic configuration paths, and platform-specific stuff related to PATHs.
 AC_DEFUN([BASIC_CHECK_PATHS_WINDOWS],
 [
-  SRC_ROOT_LENGTH=`$THEPWDCMD|$WC -m`
+  SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m`
   if test $SRC_ROOT_LENGTH -gt 100; then
       AC_MSG_ERROR([Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported])
   fi
--- a/common/autoconf/build-performance.m4	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/build-performance.m4	Wed Jul 05 18:57:52 2017 +0200
@@ -145,6 +145,9 @@
     if test "$JOBS" -gt "16"; then
       JOBS=16
     fi
+    if test "$JOBS" -eq "0"; then
+      JOBS=1
+    fi
     AC_MSG_RESULT([$JOBS])
   else
     JOBS=$with_jobs
--- a/common/autoconf/generated-configure.sh	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 18:57:52 2017 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for OpenJDK jdk8.
+# Generated by GNU Autoconf 2.68 for OpenJDK jdk8.
 #
 # Report bugs to <build-dev@openjdk.java.net>.
 #
@@ -91,6 +91,7 @@
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -216,11 +217,18 @@
   # We cannot yet assume a decent shell, so we have to provide a
 	# neutralization value for shells without unset; and this also
 	# works around shells that cannot unset nonexistent variables.
+	# Preserve -v and -x to the replacement shell.
 	BASH_ENV=/dev/null
 	ENV=/dev/null
 	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
 	export CONFIG_SHELL
-	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+	case $- in # ((((
+	  *v*x* | *x*v* ) as_opts=-vx ;;
+	  *v* ) as_opts=-v ;;
+	  *x* ) as_opts=-x ;;
+	  * ) as_opts= ;;
+	esac
+	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
 fi
 
     if test x$as_have_required = xno; then :
@@ -681,8 +689,8 @@
 SHARED_LIBRARY
 OBJ_SUFFIX
 COMPILER_NAME
+JT_HOME
 JTREGEXE
-JT_HOME
 LIPO
 ac_ct_OBJDUMP
 OBJDUMP
@@ -797,6 +805,7 @@
 OS_VERSION_MINOR
 OS_VERSION_MAJOR
 PKG_CONFIG
+CODESIGN
 XATTR
 TIME
 STAT
@@ -900,7 +909,6 @@
 SORT
 SH
 RM
-THEPWDCMD
 PRINTF
 MV
 MKTEMP
@@ -988,6 +996,7 @@
 with_cacerts_file
 enable_unlimited_crypto
 with_milestone
+with_update_version
 with_build_number
 with_user_release_suffix
 with_boot_jdk
@@ -1459,7 +1468,7 @@
     $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
       $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
     ;;
 
   esac
@@ -1727,6 +1736,7 @@
                           group
   --with-cacerts-file     specify alternative cacerts file
   --with-milestone        Set milestone value for build [internal]
+  --with-update-version   Set update version value for build [b00]
   --with-build-number     Set build number value for build [b00]
   --with-user-release-suffix
                           Add a custom string to the version string if build
@@ -1894,7 +1904,7 @@
 if $ac_init_version; then
   cat <<\_ACEOF
 OpenJDK configure jdk8
-generated by GNU Autoconf 2.67
+generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
@@ -1940,7 +1950,7 @@
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_compile
@@ -1978,7 +1988,7 @@
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_compile
@@ -2016,7 +2026,7 @@
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_objc_try_compile
@@ -2053,7 +2063,7 @@
 
     ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_cpp
@@ -2090,7 +2100,7 @@
 
     ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_cpp
@@ -2103,10 +2113,10 @@
 ac_fn_cxx_check_header_mongrel ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval "test \"\${$3+set}\"" = set; then :
+  if eval \${$3+:} false; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 fi
 eval ac_res=\$$3
@@ -2173,7 +2183,7 @@
 esac
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   eval "$3=\$ac_header_compiler"
@@ -2182,7 +2192,7 @@
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_cxx_check_header_mongrel
 
@@ -2223,7 +2233,7 @@
        ac_retval=$ac_status
 fi
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_run
@@ -2237,7 +2247,7 @@
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2255,7 +2265,7 @@
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_cxx_check_header_compile
 
@@ -2432,7 +2442,7 @@
 rm -f conftest.val
 
   fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_compute_int
@@ -2478,7 +2488,7 @@
   # interfere with the next link command; also delete a directory that is
   # left behind by Apple's compiler.  We do this before executing the actions.
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_link
@@ -2491,7 +2501,7 @@
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2546,7 +2556,7 @@
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_cxx_check_func
 
@@ -2559,7 +2569,7 @@
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2577,7 +2587,7 @@
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_compile
 cat >config.log <<_ACEOF
@@ -2585,7 +2595,7 @@
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by OpenJDK $as_me jdk8, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
 
@@ -2843,7 +2853,7 @@
       || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
   fi
 done
 
@@ -3780,7 +3790,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1369723814
+DATE_WHEN_GENERATED=1370470729
 
 ###############################################################################
 #
@@ -3818,7 +3828,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_BASENAME+set}" = set; then :
+if ${ac_cv_path_BASENAME+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $BASENAME in
@@ -3877,7 +3887,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_BASH+set}" = set; then :
+if ${ac_cv_path_BASH+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $BASH in
@@ -3936,7 +3946,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CAT+set}" = set; then :
+if ${ac_cv_path_CAT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CAT in
@@ -3995,7 +4005,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CHMOD+set}" = set; then :
+if ${ac_cv_path_CHMOD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CHMOD in
@@ -4054,7 +4064,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CMP+set}" = set; then :
+if ${ac_cv_path_CMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CMP in
@@ -4113,7 +4123,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_COMM+set}" = set; then :
+if ${ac_cv_path_COMM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $COMM in
@@ -4172,7 +4182,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CP+set}" = set; then :
+if ${ac_cv_path_CP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CP in
@@ -4231,7 +4241,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CPIO+set}" = set; then :
+if ${ac_cv_path_CPIO+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CPIO in
@@ -4290,7 +4300,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CUT+set}" = set; then :
+if ${ac_cv_path_CUT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CUT in
@@ -4349,7 +4359,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_DATE+set}" = set; then :
+if ${ac_cv_path_DATE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $DATE in
@@ -4408,7 +4418,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_DIFF+set}" = set; then :
+if ${ac_cv_path_DIFF+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $DIFF in
@@ -4467,7 +4477,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_DIRNAME+set}" = set; then :
+if ${ac_cv_path_DIRNAME+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $DIRNAME in
@@ -4526,7 +4536,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_ECHO+set}" = set; then :
+if ${ac_cv_path_ECHO+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $ECHO in
@@ -4585,7 +4595,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_EXPR+set}" = set; then :
+if ${ac_cv_path_EXPR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $EXPR in
@@ -4644,7 +4654,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_FILE+set}" = set; then :
+if ${ac_cv_path_FILE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $FILE in
@@ -4703,7 +4713,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_FIND+set}" = set; then :
+if ${ac_cv_path_FIND+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $FIND in
@@ -4762,7 +4772,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_HEAD+set}" = set; then :
+if ${ac_cv_path_HEAD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $HEAD in
@@ -4821,7 +4831,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_LN+set}" = set; then :
+if ${ac_cv_path_LN+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $LN in
@@ -4880,7 +4890,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_LS+set}" = set; then :
+if ${ac_cv_path_LS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $LS in
@@ -4939,7 +4949,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_MKDIR+set}" = set; then :
+if ${ac_cv_path_MKDIR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MKDIR in
@@ -4998,7 +5008,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_MKTEMP+set}" = set; then :
+if ${ac_cv_path_MKTEMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MKTEMP in
@@ -5057,7 +5067,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_MV+set}" = set; then :
+if ${ac_cv_path_MV+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MV in
@@ -5116,7 +5126,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_PRINTF+set}" = set; then :
+if ${ac_cv_path_PRINTF+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $PRINTF in
@@ -5169,72 +5179,13 @@
 
 
 
-    for ac_prog in pwd
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_THEPWDCMD+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $THEPWDCMD in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_THEPWDCMD="$THEPWDCMD" # Let the user override the test with a path.
-  ;;
-  *)
-  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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_THEPWDCMD="$as_dir/$ac_word$ac_exec_ext"
-    $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
-
-  ;;
-esac
-fi
-THEPWDCMD=$ac_cv_path_THEPWDCMD
-if test -n "$THEPWDCMD"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $THEPWDCMD" >&5
-$as_echo "$THEPWDCMD" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$THEPWDCMD" && break
-done
-
-
-    if test "x$THEPWDCMD" = x; then
-        if test "xpwd" = x; then
-          PROG_NAME=thepwdcmd
-        else
-          PROG_NAME=pwd
-        fi
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $PROG_NAME!" >&5
-$as_echo "$as_me: Could not find $PROG_NAME!" >&6;}
-        as_fn_error $? "Cannot continue" "$LINENO" 5
-    fi
-
-
-
     for ac_prog in rm
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_RM+set}" = set; then :
+if ${ac_cv_path_RM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $RM in
@@ -5293,7 +5244,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_SH+set}" = set; then :
+if ${ac_cv_path_SH+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $SH in
@@ -5352,7 +5303,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_SORT+set}" = set; then :
+if ${ac_cv_path_SORT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $SORT in
@@ -5411,7 +5362,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TAIL+set}" = set; then :
+if ${ac_cv_path_TAIL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TAIL in
@@ -5470,7 +5421,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TAR+set}" = set; then :
+if ${ac_cv_path_TAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TAR in
@@ -5529,7 +5480,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TEE+set}" = set; then :
+if ${ac_cv_path_TEE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TEE in
@@ -5588,7 +5539,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TOUCH+set}" = set; then :
+if ${ac_cv_path_TOUCH+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TOUCH in
@@ -5647,7 +5598,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TR+set}" = set; then :
+if ${ac_cv_path_TR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TR in
@@ -5706,7 +5657,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_UNAME+set}" = set; then :
+if ${ac_cv_path_UNAME+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $UNAME in
@@ -5765,7 +5716,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_UNIQ+set}" = set; then :
+if ${ac_cv_path_UNIQ+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $UNIQ in
@@ -5824,7 +5775,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_WC+set}" = set; then :
+if ${ac_cv_path_WC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $WC in
@@ -5883,7 +5834,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_WHICH+set}" = set; then :
+if ${ac_cv_path_WHICH+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $WHICH in
@@ -5942,7 +5893,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_XARGS+set}" = set; then :
+if ${ac_cv_path_XARGS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $XARGS in
@@ -6002,7 +5953,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AWK+set}" = set; then :
+if ${ac_cv_prog_AWK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$AWK"; then
@@ -6052,7 +6003,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then :
+if ${ac_cv_path_GREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$GREP"; then
@@ -6127,7 +6078,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
 $as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then :
+if ${ac_cv_path_EGREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -6206,7 +6157,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
 $as_echo_n "checking for fgrep... " >&6; }
-if test "${ac_cv_path_FGREP+set}" = set; then :
+if ${ac_cv_path_FGREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
@@ -6285,7 +6236,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
 $as_echo_n "checking for a sed that does not truncate output... " >&6; }
-if test "${ac_cv_path_SED+set}" = set; then :
+if ${ac_cv_path_SED+:} false; then :
   $as_echo_n "(cached) " >&6
 else
             ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
@@ -6371,7 +6322,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_NAWK+set}" = set; then :
+if ${ac_cv_path_NAWK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $NAWK in
@@ -6426,12 +6377,16 @@
 # Always force rm.
 RM="$RM -f"
 
+# pwd behaves differently on various platforms and some don't support the -L flag.
+# Always use the bash builtin pwd to get uniform behavior.
+THEPWDCMD=pwd
+
 # These are not required on all platforms
 # Extract the first word of "cygpath", so it can be a program name with args.
 set dummy cygpath; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CYGPATH+set}" = set; then :
+if ${ac_cv_path_CYGPATH+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CYGPATH in
@@ -6471,7 +6426,7 @@
 set dummy readlink; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_READLINK+set}" = set; then :
+if ${ac_cv_path_READLINK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $READLINK in
@@ -6511,7 +6466,7 @@
 set dummy df; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_DF+set}" = set; then :
+if ${ac_cv_path_DF+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $DF in
@@ -6551,7 +6506,7 @@
 set dummy SetFile; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_SETFILE+set}" = set; then :
+if ${ac_cv_path_SETFILE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $SETFILE in
@@ -6597,7 +6552,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
 $as_echo_n "checking build system type... " >&6; }
-if test "${ac_cv_build+set}" = set; then :
+if ${ac_cv_build+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_build_alias=$build_alias
@@ -6613,7 +6568,7 @@
 $as_echo "$ac_cv_build" >&6; }
 case $ac_cv_build in
 *-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
 esac
 build=$ac_cv_build
 ac_save_IFS=$IFS; IFS='-'
@@ -6631,7 +6586,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
 $as_echo_n "checking host system type... " >&6; }
-if test "${ac_cv_host+set}" = set; then :
+if ${ac_cv_host+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test "x$host_alias" = x; then
@@ -6646,7 +6601,7 @@
 $as_echo "$ac_cv_host" >&6; }
 case $ac_cv_host in
 *-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
 esac
 host=$ac_cv_host
 ac_save_IFS=$IFS; IFS='-'
@@ -6664,7 +6619,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
 $as_echo_n "checking target system type... " >&6; }
-if test "${ac_cv_target+set}" = set; then :
+if ${ac_cv_target+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test "x$target_alias" = x; then
@@ -6679,7 +6634,7 @@
 $as_echo "$ac_cv_target" >&6; }
 case $ac_cv_target in
 *-*-*) ;;
-*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5 ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
 esac
 target=$ac_cv_target
 ac_save_IFS=$IFS; IFS='-'
@@ -7133,65 +7088,17 @@
 
 # Locate the directory of this script.
 SCRIPT="$0"
-
-    if test "x$OPENJDK_BUILD_OS" != xwindows; then
-        # Follow a chain of symbolic links. Use readlink
-        # where it exists, else fall back to horribly
-        # complicated shell code.
-        if test "x$READLINK_TESTED" != yes; then
-            # On MacOSX there is a readlink tool with a different
-            # purpose than the GNU readlink tool. Check the found readlink.
-            ISGNU=`$READLINK --version 2>&1 | $GREP GNU`
-            if test "x$ISGNU" = x; then
-                 # A readlink that we do not know how to use.
-                 # Are there other non-GNU readlinks out there?
-                 READLINK_TESTED=yes
-                 READLINK=
-            fi
-        fi
-
-        if test "x$READLINK" != x; then
-            SCRIPT=`$READLINK -f $SCRIPT`
-        else
-            # Save the current directory for restoring afterwards
-            STARTDIR=$PWD
-            COUNTER=0
-            sym_link_dir=`$DIRNAME $SCRIPT`
-            sym_link_file=`$BASENAME $SCRIPT`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
-            cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
-            # Resolve file symlinks
-            while test $COUNTER -lt 20; do
-                ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
-                if test "x$ISLINK" == x; then
-                    # This is not a symbolic link! We are done!
-                    break
-                fi
-                # Again resolve directory symlinks since the target of the just found
-                # link could be in a different directory
-                cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
-                sym_link_file=`$BASENAME $ISLINK`
-                let COUNTER=COUNTER+1
-            done
-            cd $STARTDIR
-            SCRIPT=$sym_link_dir/$sym_link_file
-        fi
-    fi
-
-AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD`
+AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD -L`
 
 # Where is the source? It is located two levels above the configure script.
 CURDIR="$PWD"
 cd "$AUTOCONF_DIR/../.."
-SRC_ROOT="`$THEPWDCMD`"
+SRC_ROOT="`$THEPWDCMD -L`"
 
 if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
   PATH_SEP=";"
 
-  SRC_ROOT_LENGTH=`$THEPWDCMD|$WC -m`
+  SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m`
   if test $SRC_ROOT_LENGTH -gt 100; then
       as_fn_error $? "Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported" "$LINENO" 5
   fi
@@ -7407,7 +7314,7 @@
       as_fn_error $? "The path of SRC_ROOT, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    SRC_ROOT="`cd "$path"; $THEPWDCMD`"
+    SRC_ROOT="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -7529,7 +7436,7 @@
       as_fn_error $? "The path of CURDIR, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    CURDIR="`cd "$path"; $THEPWDCMD`"
+    CURDIR="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -7900,60 +7807,9 @@
 
 
 # Test from where we are running configure, in or outside of src root.
-# To enable comparison of directories, CURDIR needs to be symlink free
-# just like SRC_ROOT already is
-NOSYM_CURDIR="$CURDIR"
-
-    if test "x$OPENJDK_BUILD_OS" != xwindows; then
-        # Follow a chain of symbolic links. Use readlink
-        # where it exists, else fall back to horribly
-        # complicated shell code.
-        if test "x$READLINK_TESTED" != yes; then
-            # On MacOSX there is a readlink tool with a different
-            # purpose than the GNU readlink tool. Check the found readlink.
-            ISGNU=`$READLINK --version 2>&1 | $GREP GNU`
-            if test "x$ISGNU" = x; then
-                 # A readlink that we do not know how to use.
-                 # Are there other non-GNU readlinks out there?
-                 READLINK_TESTED=yes
-                 READLINK=
-            fi
-        fi
-
-        if test "x$READLINK" != x; then
-            NOSYM_CURDIR=`$READLINK -f $NOSYM_CURDIR`
-        else
-            # Save the current directory for restoring afterwards
-            STARTDIR=$PWD
-            COUNTER=0
-            sym_link_dir=`$DIRNAME $NOSYM_CURDIR`
-            sym_link_file=`$BASENAME $NOSYM_CURDIR`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
-            cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
-            # Resolve file symlinks
-            while test $COUNTER -lt 20; do
-                ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
-                if test "x$ISLINK" == x; then
-                    # This is not a symbolic link! We are done!
-                    break
-                fi
-                # Again resolve directory symlinks since the target of the just found
-                # link could be in a different directory
-                cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
-                sym_link_file=`$BASENAME $ISLINK`
-                let COUNTER=COUNTER+1
-            done
-            cd $STARTDIR
-            NOSYM_CURDIR=$sym_link_dir/$sym_link_file
-        fi
-    fi
-
-if test "x$NOSYM_CURDIR" = "x$SRC_ROOT" || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common" \
-        || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/autoconf" \
-        || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
+if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \
+        || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" \
+        || test "x$CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
     # We are running configure from the src root.
     # Create a default ./build/target-variant-debuglevel output root.
     if test "x${CONF_NAME}" = x; then
@@ -8128,7 +7984,7 @@
       as_fn_error $? "The path of OUTPUT_ROOT, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    OUTPUT_ROOT="`cd "$path"; $THEPWDCMD`"
+    OUTPUT_ROOT="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -8175,7 +8031,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_PKGHANDLER+set}" = set; then :
+if ${ac_cv_prog_PKGHANDLER+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$PKGHANDLER"; then
@@ -8540,7 +8396,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CHECK_GMAKE+set}" = set; then :
+if ${ac_cv_path_CHECK_GMAKE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CHECK_GMAKE in
@@ -8894,7 +8750,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CHECK_MAKE+set}" = set; then :
+if ${ac_cv_path_CHECK_MAKE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CHECK_MAKE in
@@ -9253,7 +9109,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CHECK_TOOLSDIR_GMAKE+set}" = set; then :
+if ${ac_cv_path_CHECK_TOOLSDIR_GMAKE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CHECK_TOOLSDIR_GMAKE in
@@ -9606,7 +9462,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CHECK_TOOLSDIR_MAKE+set}" = set; then :
+if ${ac_cv_path_CHECK_TOOLSDIR_MAKE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CHECK_TOOLSDIR_MAKE in
@@ -10002,7 +9858,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_UNZIP+set}" = set; then :
+if ${ac_cv_path_UNZIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $UNZIP in
@@ -10061,7 +9917,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_ZIP+set}" = set; then :
+if ${ac_cv_path_ZIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $ZIP in
@@ -10120,7 +9976,7 @@
 set dummy ldd; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_LDD+set}" = set; then :
+if ${ac_cv_path_LDD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $LDD in
@@ -10166,7 +10022,7 @@
 set dummy otool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_OTOOL+set}" = set; then :
+if ${ac_cv_path_OTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $OTOOL in
@@ -10211,7 +10067,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_READELF+set}" = set; then :
+if ${ac_cv_path_READELF+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $READELF in
@@ -10254,7 +10110,7 @@
 set dummy hg; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_HG+set}" = set; then :
+if ${ac_cv_path_HG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $HG in
@@ -10294,7 +10150,7 @@
 set dummy stat; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_STAT+set}" = set; then :
+if ${ac_cv_path_STAT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $STAT in
@@ -10334,7 +10190,7 @@
 set dummy time; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TIME+set}" = set; then :
+if ${ac_cv_path_TIME+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TIME in
@@ -10379,7 +10235,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_COMM+set}" = set; then :
+if ${ac_cv_path_COMM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $COMM in
@@ -10441,7 +10297,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_XATTR+set}" = set; then :
+if ${ac_cv_path_XATTR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $XATTR in
@@ -10493,6 +10349,62 @@
     fi
 
 
+  # Extract the first word of "codesign", so it can be a program name with args.
+set dummy codesign; 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_path_CODESIGN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $CODESIGN in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CODESIGN="$CODESIGN" # Let the user override the test with a path.
+  ;;
+  *)
+  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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_CODESIGN="$as_dir/$ac_word$ac_exec_ext"
+    $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
+
+  ;;
+esac
+fi
+CODESIGN=$ac_cv_path_CODESIGN
+if test -n "$CODESIGN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CODESIGN" >&5
+$as_echo "$CODESIGN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  if test "x$CODESIGN" != "x"; then
+    # Verify that the openjdk_codesign certificate is present
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openjdk_codesign certificate is present" >&5
+$as_echo_n "checking if openjdk_codesign certificate is present... " >&6; }
+    rm -f codesign-testfile
+    touch codesign-testfile
+    codesign -s openjdk_codesign codesign-testfile 2>&5 >&5 || CODESIGN=
+    rm -f codesign-testfile
+    if test "x$CODESIGN" = x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    fi
+  fi
 fi
 
 
@@ -10505,7 +10417,7 @@
 set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $PKG_CONFIG in
@@ -10548,7 +10460,7 @@
 set dummy pkg-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $ac_pt_PKG_CONFIG in
@@ -10721,7 +10633,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_BDEPS_UNZIP+set}" = set; then :
+if ${ac_cv_prog_BDEPS_UNZIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$BDEPS_UNZIP"; then
@@ -10767,7 +10679,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_BDEPS_FTP+set}" = set; then :
+if ${ac_cv_prog_BDEPS_FTP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$BDEPS_FTP"; then
@@ -10939,6 +10851,18 @@
 fi
 
 
+# Check whether --with-update-version was given.
+if test "${with_update_version+set}" = set; then :
+  withval=$with_update_version;
+fi
+
+if test "x$with_update_version" = xyes; then
+  as_fn_error $? "Update version must have a value" "$LINENO" 5
+elif test "x$with_update_version" != x; then
+  JDK_UPDATE_VERSION="$with_update_version"
+fi
+
+
 # Check whether --with-build-number was given.
 if test "${with_build_number+set}" = set; then :
   withval=$with_build_number;
@@ -11188,7 +11112,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -11520,7 +11444,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -11666,7 +11590,7 @@
       as_fn_error $? "The path of JAVA_HOME_PROCESSED, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    JAVA_HOME_PROCESSED="`cd "$path"; $THEPWDCMD`"
+    JAVA_HOME_PROCESSED="`cd "$path"; $THEPWDCMD -L`"
   fi
 
         if test ! -d "$JAVA_HOME_PROCESSED"; then
@@ -11838,7 +11762,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -12026,7 +11950,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -12055,7 +11979,7 @@
 set dummy javac; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_JAVAC_CHECK+set}" = set; then :
+if ${ac_cv_path_JAVAC_CHECK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $JAVAC_CHECK in
@@ -12095,7 +12019,7 @@
 set dummy java; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_JAVA_CHECK+set}" = set; then :
+if ${ac_cv_path_JAVA_CHECK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $JAVA_CHECK in
@@ -12165,10 +12089,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME $BINARY`
             sym_link_file=`$BASENAME $BINARY`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -12179,7 +12103,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -12354,7 +12278,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -12569,7 +12493,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -12749,7 +12673,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -12957,7 +12881,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -13137,7 +13061,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -13345,7 +13269,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -13525,7 +13449,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -13733,7 +13657,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -13913,7 +13837,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -14108,7 +14032,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -14286,7 +14210,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -14482,7 +14406,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -14660,7 +14584,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -14855,7 +14779,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -15033,7 +14957,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -15229,7 +15153,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -15407,7 +15331,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -15584,7 +15508,7 @@
       as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    BOOT_JDK="`cd "$path"; $THEPWDCMD`"
+    BOOT_JDK="`cd "$path"; $THEPWDCMD -L`"
   fi
 
               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boot JDK" >&5
@@ -16261,14 +16185,28 @@
 # Check whether --with-jtreg was given.
 if test "${with_jtreg+set}" = set; then :
   withval=$with_jtreg;
-fi
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JTReg Regression Test Harness" >&5
-$as_echo_n "checking for JTReg Regression Test Harness... " >&6; }
-
-  if test "x$with_jtreg" != x; then
-    JT_HOME="$with_jtreg"
+else
+  with_jtreg=no
+fi
+
+
+  if test "x$with_jtreg" = xno; then
+    # jtreg disabled
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5
+$as_echo_n "checking for jtreg... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  else
+    if test "x$with_jtreg" != xyes; then
+      # with path specified.
+      JT_HOME="$with_jtreg"
+    fi
+
+    if test "x$JT_HOME" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5
+$as_echo_n "checking for jtreg... " >&6; }
+
+      # use JT_HOME enviroment var.
 
   if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
 
@@ -16388,20 +16326,82 @@
       as_fn_error $? "The path of JT_HOME, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    JT_HOME="`cd "$path"; $THEPWDCMD`"
-  fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JT_HOME" >&5
-$as_echo "$JT_HOME" >&6; }
-
-    # jtreg win32 script works for everybody
-    JTREGEXE="$JT_HOME/win32/bin/jtreg"
-    if test ! -f "$JTREGEXE"; then
-      as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5
-    fi
-  else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+    JT_HOME="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+
+      # jtreg win32 script works for everybody
+      JTREGEXE="$JT_HOME/win32/bin/jtreg"
+
+      if test ! -f "$JTREGEXE"; then
+        as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5
+$as_echo "$JTREGEXE" >&6; }
+    else
+      # try to find jtreg on path
+
+    for ac_prog in jtreg
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; 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_path_JTREGEXE+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JTREGEXE in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path.
+  ;;
+  *)
+  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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext"
+    $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
+
+  ;;
+esac
+fi
+JTREGEXE=$ac_cv_path_JTREGEXE
+if test -n "$JTREGEXE"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5
+$as_echo "$JTREGEXE" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$JTREGEXE" && break
+done
+
+
+    if test "x$JTREGEXE" = x; then
+        if test "xjtreg" = x; then
+          PROG_NAME=jtregexe
+        else
+          PROG_NAME=jtreg
+        fi
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $PROG_NAME!" >&5
+$as_echo "$as_me: Could not find $PROG_NAME!" >&6;}
+        as_fn_error $? "Cannot continue" "$LINENO" 5
+    fi
+
+
+      JT_HOME="`$DIRNAME $JTREGEXE`"
+    fi
   fi
 
 
@@ -16416,7 +16416,7 @@
 set dummy link; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CYGWIN_LINK+set}" = set; then :
+if ${ac_cv_path_CYGWIN_LINK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CYGWIN_LINK in
@@ -17377,7 +17377,7 @@
       as_fn_error $? "The path of MSVCR_DLL, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    MSVCR_DLL="`cd "$path"; $THEPWDCMD`"
+    MSVCR_DLL="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -17534,7 +17534,7 @@
       as_fn_error $? "The path of dxsdk_path, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    dxsdk_path="`cd "$path"; $THEPWDCMD`"
+    dxsdk_path="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -17672,7 +17672,7 @@
       as_fn_error $? "The path of DXSDK_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    DXSDK_LIB_PATH="`cd "$path"; $THEPWDCMD`"
+    DXSDK_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -17808,7 +17808,7 @@
       as_fn_error $? "The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    DXSDK_INCLUDE_PATH="`cd "$path"; $THEPWDCMD`"
+    DXSDK_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 
@@ -17843,7 +17843,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_BUILD_CC+set}" = set; then :
+if ${ac_cv_path_BUILD_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $BUILD_CC in
@@ -18154,7 +18154,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_BUILD_CXX+set}" = set; then :
+if ${ac_cv_path_BUILD_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $BUILD_CXX in
@@ -18463,7 +18463,7 @@
 set dummy ld; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_BUILD_LD+set}" = set; then :
+if ${ac_cv_path_BUILD_LD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $BUILD_LD in
@@ -18979,7 +18979,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TOOLS_DIR_CC+set}" = set; then :
+if ${ac_cv_path_TOOLS_DIR_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TOOLS_DIR_CC in
@@ -19031,7 +19031,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_POTENTIAL_CC+set}" = set; then :
+if ${ac_cv_path_POTENTIAL_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $POTENTIAL_CC in
@@ -19395,10 +19395,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME $TEST_COMPILER`
             sym_link_file=`$BASENAME $TEST_COMPILER`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -19409,7 +19409,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -19444,7 +19444,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_PROPER_COMPILER_CC+set}" = set; then :
+if ${ac_cv_prog_PROPER_COMPILER_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$PROPER_COMPILER_CC"; then
@@ -19488,7 +19488,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_PROPER_COMPILER_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_PROPER_COMPILER_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_PROPER_COMPILER_CC"; then
@@ -19832,10 +19832,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME $PROPER_COMPILER_CC`
             sym_link_file=`$BASENAME $PROPER_COMPILER_CC`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -19846,7 +19846,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -19938,7 +19938,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -19982,7 +19982,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -20035,7 +20035,7 @@
 test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
 $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -20150,7 +20150,7 @@
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -20193,7 +20193,7 @@
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest conftest$ac_cv_exeext
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -20252,7 +20252,7 @@
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot run C compiled programs.
 If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
     fi
   fi
 fi
@@ -20263,7 +20263,7 @@
 ac_clean_files=$ac_clean_files_save
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
 $as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then :
+if ${ac_cv_objext+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20304,7 +20304,7 @@
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
@@ -20314,7 +20314,7 @@
 ac_objext=$OBJEXT
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+if ${ac_cv_c_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20351,7 +20351,7 @@
 ac_save_CFLAGS=$CFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
 $as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then :
+if ${ac_cv_prog_cc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
@@ -20429,7 +20429,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then :
+if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
@@ -20552,7 +20552,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_TOOLS_DIR_CXX+set}" = set; then :
+if ${ac_cv_path_TOOLS_DIR_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $TOOLS_DIR_CXX in
@@ -20604,7 +20604,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_POTENTIAL_CXX+set}" = set; then :
+if ${ac_cv_path_POTENTIAL_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $POTENTIAL_CXX in
@@ -20968,10 +20968,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME $TEST_COMPILER`
             sym_link_file=`$BASENAME $TEST_COMPILER`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -20982,7 +20982,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -21017,7 +21017,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_PROPER_COMPILER_CXX+set}" = set; then :
+if ${ac_cv_prog_PROPER_COMPILER_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$PROPER_COMPILER_CXX"; then
@@ -21061,7 +21061,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_PROPER_COMPILER_CXX+set}" = set; then :
+if ${ac_cv_prog_ac_ct_PROPER_COMPILER_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_PROPER_COMPILER_CXX"; then
@@ -21405,10 +21405,10 @@
             COUNTER=0
             sym_link_dir=`$DIRNAME $PROPER_COMPILER_CXX`
             sym_link_file=`$BASENAME $PROPER_COMPILER_CXX`
-            # Use the system pwd and not the shell builtin to resolve directory symlinks
             cd $sym_link_dir
-            cd `$THEPWDCMD`
-            sym_link_dir=`$THEPWDCMD`
+            # Use -P flag to resolve symlinks in directories.
+            cd `$THEPWDCMD -P`
+            sym_link_dir=`$THEPWDCMD -P`
             # Resolve file symlinks
             while test $COUNTER -lt 20; do
                 ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
@@ -21419,7 +21419,7 @@
                 # Again resolve directory symlinks since the target of the just found
                 # link could be in a different directory
                 cd `$DIRNAME $ISLINK`
-                sym_link_dir=`$THEPWDCMD`
+                sym_link_dir=`$THEPWDCMD -P`
                 sym_link_file=`$BASENAME $ISLINK`
                 let COUNTER=COUNTER+1
             done
@@ -21515,7 +21515,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then :
+if ${ac_cv_prog_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CXX"; then
@@ -21559,7 +21559,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CXX"; then
@@ -21637,7 +21637,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -21674,7 +21674,7 @@
 ac_save_CXXFLAGS=$CXXFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
 $as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then :
+if ${ac_cv_prog_cxx_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -21772,7 +21772,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJC+set}" = set; then :
+if ${ac_cv_prog_OBJC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OBJC"; then
@@ -21816,7 +21816,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OBJC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OBJC"; then
@@ -21892,7 +21892,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5
 $as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; }
-if test "${ac_cv_objc_compiler_gnu+set}" = set; then :
+if ${ac_cv_objc_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -21929,7 +21929,7 @@
 ac_save_OBJCFLAGS=$OBJCFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5
 $as_echo_n "checking whether $OBJC accepts -g... " >&6; }
-if test "${ac_cv_prog_objc_g+set}" = set; then :
+if ${ac_cv_prog_objc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_objc_werror_flag=$ac_objc_werror_flag
@@ -22305,7 +22305,7 @@
 set dummy ${ac_tool_prefix}ar; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AR+set}" = set; then :
+if ${ac_cv_prog_AR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$AR"; then
@@ -22345,7 +22345,7 @@
 set dummy ar; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_AR"; then
@@ -22687,7 +22687,7 @@
 set dummy link; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_WINLD+set}" = set; then :
+if ${ac_cv_prog_WINLD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$WINLD"; then
@@ -23026,7 +23026,7 @@
 set dummy mt; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_MT+set}" = set; then :
+if ${ac_cv_prog_MT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$MT"; then
@@ -23347,7 +23347,7 @@
 set dummy rc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RC+set}" = set; then :
+if ${ac_cv_prog_RC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RC"; then
@@ -23738,7 +23738,7 @@
 set dummy lib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_WINAR+set}" = set; then :
+if ${ac_cv_prog_WINAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$WINAR"; then
@@ -24044,7 +24044,7 @@
 set dummy dumpbin; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+if ${ac_cv_prog_DUMPBIN+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$DUMPBIN"; then
@@ -24363,7 +24363,7 @@
   CPP=
 fi
 if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then :
+  if ${ac_cv_prog_CPP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
       # Double quotes because CPP needs to be expanded
@@ -24479,7 +24479,7 @@
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 
 ac_ext=cpp
@@ -24763,7 +24763,7 @@
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
 $as_echo_n "checking how to run the C++ preprocessor... " >&6; }
 if test -z "$CXXCPP"; then
-  if test "${ac_cv_prog_CXXCPP+set}" = set; then :
+  if ${ac_cv_prog_CXXCPP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
       # Double quotes because CXXCPP needs to be expanded
@@ -24879,7 +24879,7 @@
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 
 ac_ext=cpp
@@ -25181,7 +25181,7 @@
 set dummy as; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_AS+set}" = set; then :
+if ${ac_cv_path_AS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $AS in
@@ -25493,7 +25493,7 @@
 set dummy nm; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_NM+set}" = set; then :
+if ${ac_cv_path_NM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $NM in
@@ -25799,7 +25799,7 @@
 set dummy gnm; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_GNM+set}" = set; then :
+if ${ac_cv_path_GNM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $GNM in
@@ -26105,7 +26105,7 @@
 set dummy strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_STRIP+set}" = set; then :
+if ${ac_cv_path_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $STRIP in
@@ -26411,7 +26411,7 @@
 set dummy mcs; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_MCS+set}" = set; then :
+if ${ac_cv_path_MCS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MCS in
@@ -26719,7 +26719,7 @@
 set dummy ${ac_tool_prefix}nm; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_NM+set}" = set; then :
+if ${ac_cv_prog_NM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$NM"; then
@@ -26759,7 +26759,7 @@
 set dummy nm; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_NM+set}" = set; then :
+if ${ac_cv_prog_ac_ct_NM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_NM"; then
@@ -27079,7 +27079,7 @@
 set dummy ${ac_tool_prefix}strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then :
+if ${ac_cv_prog_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$STRIP"; then
@@ -27119,7 +27119,7 @@
 set dummy strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_STRIP"; then
@@ -27444,7 +27444,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJCOPY+set}" = set; then :
+if ${ac_cv_prog_OBJCOPY+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OBJCOPY"; then
@@ -27488,7 +27488,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OBJCOPY+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OBJCOPY"; then
@@ -27815,7 +27815,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OBJDUMP"; then
@@ -27859,7 +27859,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OBJDUMP"; then
@@ -28183,7 +28183,7 @@
 set dummy lipo; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_LIPO+set}" = set; then :
+if ${ac_cv_path_LIPO+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $LIPO in
@@ -28500,7 +28500,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
 $as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
+if ${ac_cv_header_stdc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -28677,7 +28677,7 @@
 for ac_header in stdio.h
 do :
   ac_fn_cxx_check_header_mongrel "$LINENO" "stdio.h" "ac_cv_header_stdio_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdio_h" = x""yes; then :
+if test "x$ac_cv_header_stdio_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_STDIO_H 1
 _ACEOF
@@ -28706,7 +28706,7 @@
 # This bug is HP SR number 8606223364.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int *" >&5
 $as_echo_n "checking size of int *... " >&6; }
-if test "${ac_cv_sizeof_int_p+set}" = set; then :
+if ${ac_cv_sizeof_int_p+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (int *))" "ac_cv_sizeof_int_p"        "$ac_includes_default"; then :
@@ -28716,7 +28716,7 @@
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "cannot compute sizeof (int *)
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
    else
      ac_cv_sizeof_int_p=0
    fi
@@ -28763,7 +28763,7 @@
 #
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
 $as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if test "${ac_cv_c_bigendian+set}" = set; then :
+if ${ac_cv_c_bigendian+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_c_bigendian=unknown
@@ -29930,8 +29930,8 @@
   have_x=disabled
 else
   case $x_includes,$x_libraries in #(
-    *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5 ;; #(
-    *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then :
+    *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #(
+    *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   # One or both of the vars are not set, and there is no cached value.
@@ -30208,7 +30208,7 @@
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5
 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; }
-if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then :
+if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30242,14 +30242,14 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; }
-if test "x$ac_cv_lib_dnet_dnet_ntoa" = x""yes; then :
+if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
 fi
 
     if test $ac_cv_lib_dnet_dnet_ntoa = no; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5
 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; }
-if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then :
+if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30283,7 +30283,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
-if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = x""yes; then :
+if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
 fi
 
@@ -30302,14 +30302,14 @@
     # The functions gethostbyname, getservbyname, and inet_addr are
     # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
     ac_fn_cxx_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
-if test "x$ac_cv_func_gethostbyname" = x""yes; then :
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
 
 fi
 
     if test $ac_cv_func_gethostbyname = no; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
-if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then :
+if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30343,14 +30343,14 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
-if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then :
+if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
 fi
 
       if test $ac_cv_lib_nsl_gethostbyname = no; then
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
-if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then :
+if ${ac_cv_lib_bsd_gethostbyname+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30384,7 +30384,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
-if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then :
+if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
 fi
 
@@ -30399,14 +30399,14 @@
     # must be given before -lnsl if both are needed.  We assume that
     # if connect needs -lnsl, so does gethostbyname.
     ac_fn_cxx_check_func "$LINENO" "connect" "ac_cv_func_connect"
-if test "x$ac_cv_func_connect" = x""yes; then :
+if test "x$ac_cv_func_connect" = xyes; then :
 
 fi
 
     if test $ac_cv_func_connect = no; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
 $as_echo_n "checking for connect in -lsocket... " >&6; }
-if test "${ac_cv_lib_socket_connect+set}" = set; then :
+if ${ac_cv_lib_socket_connect+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30440,7 +30440,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5
 $as_echo "$ac_cv_lib_socket_connect" >&6; }
-if test "x$ac_cv_lib_socket_connect" = x""yes; then :
+if test "x$ac_cv_lib_socket_connect" = xyes; then :
   X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
 fi
 
@@ -30448,14 +30448,14 @@
 
     # Guillermo Gomez says -lposix is necessary on A/UX.
     ac_fn_cxx_check_func "$LINENO" "remove" "ac_cv_func_remove"
-if test "x$ac_cv_func_remove" = x""yes; then :
+if test "x$ac_cv_func_remove" = xyes; then :
 
 fi
 
     if test $ac_cv_func_remove = no; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5
 $as_echo_n "checking for remove in -lposix... " >&6; }
-if test "${ac_cv_lib_posix_remove+set}" = set; then :
+if ${ac_cv_lib_posix_remove+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30489,7 +30489,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5
 $as_echo "$ac_cv_lib_posix_remove" >&6; }
-if test "x$ac_cv_lib_posix_remove" = x""yes; then :
+if test "x$ac_cv_lib_posix_remove" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
 fi
 
@@ -30497,14 +30497,14 @@
 
     # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
     ac_fn_cxx_check_func "$LINENO" "shmat" "ac_cv_func_shmat"
-if test "x$ac_cv_func_shmat" = x""yes; then :
+if test "x$ac_cv_func_shmat" = xyes; then :
 
 fi
 
     if test $ac_cv_func_shmat = no; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5
 $as_echo_n "checking for shmat in -lipc... " >&6; }
-if test "${ac_cv_lib_ipc_shmat+set}" = set; then :
+if ${ac_cv_lib_ipc_shmat+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30538,7 +30538,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5
 $as_echo "$ac_cv_lib_ipc_shmat" >&6; }
-if test "x$ac_cv_lib_ipc_shmat" = x""yes; then :
+if test "x$ac_cv_lib_ipc_shmat" = xyes; then :
   X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
 fi
 
@@ -30556,7 +30556,7 @@
   # John Interrante, Karl Berry
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5
 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; }
-if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then :
+if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -30590,7 +30590,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
-if test "x$ac_cv_lib_ICE_IceConnectionNumber" = x""yes; then :
+if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then :
   X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
 fi
 
@@ -31131,7 +31131,7 @@
       as_fn_error $? "The path of with_freetype, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    with_freetype="`cd "$path"; $THEPWDCMD`"
+    with_freetype="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 	    FREETYPE2_LIBS="-L$with_freetype/lib -lfreetype"
@@ -31433,7 +31433,7 @@
       as_fn_error $? "The path of FREETYPELOCATION, which resolves as \"$path\", is not found." "$LINENO" 5
     fi
 
-    FREETYPELOCATION="`cd "$path"; $THEPWDCMD`"
+    FREETYPELOCATION="`cd "$path"; $THEPWDCMD -L`"
   fi
 
 	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype in some standard windows locations" >&5
@@ -31609,7 +31609,7 @@
             LDFLAGS="$FREETYPE2_LIBS"
             { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Init_FreeType in -lfreetype" >&5
 $as_echo_n "checking for FT_Init_FreeType in -lfreetype... " >&6; }
-if test "${ac_cv_lib_freetype_FT_Init_FreeType+set}" = set; then :
+if ${ac_cv_lib_freetype_FT_Init_FreeType+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -31643,7 +31643,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_freetype_FT_Init_FreeType" >&5
 $as_echo "$ac_cv_lib_freetype_FT_Init_FreeType" >&6; }
-if test "x$ac_cv_lib_freetype_FT_Init_FreeType" = x""yes; then :
+if test "x$ac_cv_lib_freetype_FT_Init_FreeType" = xyes; then :
   FREETYPE2_FOUND=true
 else
   as_fn_error $? "Could not find freetype2! $HELP_MSG " "$LINENO" 5
@@ -31931,7 +31931,7 @@
 	    for ac_header in alsa/asoundlib.h
 do :
   ac_fn_cxx_check_header_mongrel "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_alsa_asoundlib_h" = x""yes; then :
+if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_ALSA_ASOUNDLIB_H 1
 _ACEOF
@@ -31990,7 +31990,7 @@
 USE_EXTERNAL_LIBJPEG=true
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ljpeg" >&5
 $as_echo_n "checking for main in -ljpeg... " >&6; }
-if test "${ac_cv_lib_jpeg_main+set}" = set; then :
+if ${ac_cv_lib_jpeg_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -32018,7 +32018,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_main" >&5
 $as_echo "$ac_cv_lib_jpeg_main" >&6; }
-if test "x$ac_cv_lib_jpeg_main" = x""yes; then :
+if test "x$ac_cv_lib_jpeg_main" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBJPEG 1
 _ACEOF
@@ -32067,7 +32067,7 @@
     USE_EXTERNAL_LIBGIF=false
 elif test "x${with_giflib}" = "xsystem"; then
     ac_fn_cxx_check_header_mongrel "$LINENO" "gif_lib.h" "ac_cv_header_gif_lib_h" "$ac_includes_default"
-if test "x$ac_cv_header_gif_lib_h" = x""yes; then :
+if test "x$ac_cv_header_gif_lib_h" = xyes; then :
 
 else
    as_fn_error $? "--with-giflib=system specified, but gif_lib.h not found!" "$LINENO" 5
@@ -32076,7 +32076,7 @@
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DGifGetCode in -lgif" >&5
 $as_echo_n "checking for DGifGetCode in -lgif... " >&6; }
-if test "${ac_cv_lib_gif_DGifGetCode+set}" = set; then :
+if ${ac_cv_lib_gif_DGifGetCode+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -32110,7 +32110,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gif_DGifGetCode" >&5
 $as_echo "$ac_cv_lib_gif_DGifGetCode" >&6; }
-if test "x$ac_cv_lib_gif_DGifGetCode" = x""yes; then :
+if test "x$ac_cv_lib_gif_DGifGetCode" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBGIF 1
 _ACEOF
@@ -32142,7 +32142,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5
 $as_echo_n "checking for compress in -lz... " >&6; }
-if test "${ac_cv_lib_z_compress+set}" = set; then :
+if ${ac_cv_lib_z_compress+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -32176,7 +32176,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5
 $as_echo "$ac_cv_lib_z_compress" >&6; }
-if test "x$ac_cv_lib_z_compress" = x""yes; then :
+if test "x$ac_cv_lib_z_compress" = xyes; then :
    ZLIB_FOUND=yes
 else
    ZLIB_FOUND=no
@@ -32269,7 +32269,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
 $as_echo_n "checking for cos in -lm... " >&6; }
-if test "${ac_cv_lib_m_cos+set}" = set; then :
+if ${ac_cv_lib_m_cos+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -32303,7 +32303,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5
 $as_echo "$ac_cv_lib_m_cos" >&6; }
-if test "x$ac_cv_lib_m_cos" = x""yes; then :
+if test "x$ac_cv_lib_m_cos" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBM 1
 _ACEOF
@@ -32327,7 +32327,7 @@
 LIBS=""
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
 $as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+if ${ac_cv_lib_dl_dlopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -32361,7 +32361,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBDL 1
 _ACEOF
@@ -32591,7 +32591,7 @@
 See the pkg-config man page for more details.
 
 To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBFFI_CFLAGS=$pkg_cv_LIBFFI_CFLAGS
 	LIBFFI_LIBS=$pkg_cv_LIBFFI_LIBS
@@ -32607,7 +32607,7 @@
 set dummy llvm-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_LLVM_CONFIG+set}" = set; then :
+if ${ac_cv_prog_LLVM_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$LLVM_CONFIG"; then
@@ -32933,6 +32933,9 @@
     if test "$JOBS" -gt "16"; then
       JOBS=16
     fi
+    if test "$JOBS" -eq "0"; then
+      JOBS=1
+    fi
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JOBS" >&5
 $as_echo "$JOBS" >&6; }
   else
@@ -33216,7 +33219,7 @@
 set dummy ccache; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_CCACHE+set}" = set; then :
+if ${ac_cv_path_CCACHE+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $CCACHE in
@@ -33477,10 +33480,21 @@
      :end' >>confcache
 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
   if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
+    if test "x$cache_file" != "x/dev/null"; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
 $as_echo "$as_me: updating cache $cache_file" >&6;}
-    cat confcache >$cache_file
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
   else
     { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -33512,7 +33526,7 @@
 
 
 
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -33613,6 +33627,7 @@
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -33920,7 +33935,7 @@
 # values after options handling.
 ac_log="
 This file was extended by OpenJDK $as_me jdk8, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -33983,7 +33998,7 @@
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 OpenJDK config.status jdk8
-configured by $0, generated by GNU Autoconf 2.67,
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -34112,7 +34127,7 @@
     "$OUTPUT_ROOT/spec.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/spec.sh:$AUTOCONF_DIR/spec.sh.in" ;;
     "$OUTPUT_ROOT/Makefile") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in" ;;
 
-  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
 done
 
@@ -34134,9 +34149,10 @@
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
 ' 0
   trap 'as_fn_exit 1' 1 2 13 15
 }
@@ -34144,12 +34160,13 @@
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
+  test -d "$tmp"
 }  ||
 {
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
 } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
 
 # Set up the scripts for CONFIG_FILES section.
 # No need to generate them if there are no CONFIG_FILES.
@@ -34171,7 +34188,7 @@
   ac_cs_awk_cr=$ac_cr
 fi
 
-echo 'BEGIN {' >"$tmp/subs1.awk" &&
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
 
@@ -34199,7 +34216,7 @@
 rm -f conf$$subs.sh
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
 _ACEOF
 sed -n '
 h
@@ -34247,7 +34264,7 @@
 rm -f conf$$subs.awk
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACAWK
-cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
   for (key in S) S_is_set[key] = 1
   FS = ""
 
@@ -34279,7 +34296,7 @@
   sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
 else
   cat
-fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
   || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
 _ACEOF
 
@@ -34313,7 +34330,7 @@
 # No need to generate them if there are no CONFIG_HEADERS.
 # This happens for instance with `./config.status Makefile'.
 if test -n "$CONFIG_HEADERS"; then
-cat >"$tmp/defines.awk" <<\_ACAWK ||
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
 BEGIN {
 _ACEOF
 
@@ -34325,8 +34342,8 @@
 # handling of long lines.
 ac_delim='%!_!# '
 for ac_last_try in false false :; do
-  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
-  if test -z "$ac_t"; then
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
     break
   elif $ac_last_try; then
     as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
@@ -34427,7 +34444,7 @@
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -34446,7 +34463,7 @@
     for ac_f
     do
       case $ac_f in
-      -) ac_f="$tmp/stdin";;
+      -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
 	 # because $ac_f cannot contain `:'.
@@ -34455,7 +34472,7 @@
 	   [\\/$]*) false;;
 	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
 	   esac ||
-	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
       esac
       case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
       as_fn_append ac_file_inputs " '$ac_f'"
@@ -34481,8 +34498,8 @@
     esac
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5  ;;
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
     esac
     ;;
   esac
@@ -34607,21 +34624,22 @@
 s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
 $ac_datarootdir_hack
 "
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
-  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&5
 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&2;}
 
-  rm -f "$tmp/stdin"
+  rm -f "$ac_tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out" && rm -f "$tmp/out";;
-  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
   esac \
   || as_fn_error $? "could not create $ac_file" "$LINENO" 5
  ;;
@@ -34632,20 +34650,20 @@
   if test x"$ac_file" != x-; then
     {
       $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
-    } >"$tmp/config.h" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
 $as_echo "$as_me: $ac_file is unchanged" >&6;}
     else
       rm -f "$ac_file"
-      mv "$tmp/config.h" "$ac_file" \
+      mv "$ac_tmp/config.h" "$ac_file" \
 	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
     fi
   else
     $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
       || as_fn_error $? "could not create -" "$LINENO" 5
   fi
  ;;
--- a/common/autoconf/jdk-options.m4	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/jdk-options.m4	Wed Jul 05 18:57:52 2017 +0200
@@ -422,6 +422,14 @@
   MILESTONE=internal
 fi
 
+AC_ARG_WITH(update-version, [AS_HELP_STRING([--with-update-version], 
+                          [Set update version value for build @<:@b00@:>@])])
+if test "x$with_update_version" = xyes; then
+  AC_MSG_ERROR([Update version must have a value])
+elif test "x$with_update_version" != x; then
+  JDK_UPDATE_VERSION="$with_update_version"
+fi
+
 AC_ARG_WITH(build-number, [AS_HELP_STRING([--with-build-number], 
                           [Set build number value for build @<:@b00@:>@])])
 if test "x$with_build_number" = xyes; then
--- a/common/autoconf/spec.gmk.in	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 18:57:52 2017 +0200
@@ -478,6 +478,7 @@
 # CD is going away, but remains to cater for legacy makefiles.
 CD:=cd
 CHMOD:=@CHMOD@
+CODESIGN:=@CODESIGN@
 COMM:=@COMM@
 CP:=@CP@
 CPIO:=@CPIO@
--- a/common/autoconf/toolchain.m4	Thu May 30 10:58:13 2013 -0700
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 18:57:52 2017 +0200
@@ -36,7 +36,7 @@
     $ECHO $COMPILER_VERSION_TEST | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       GCC_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1`
-      
+
       AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler.])
       AC_MSG_NOTICE([The result from running with -V was: "$COMPILER_VERSION_TEST" and with --version: "$GCC_VERSION_TEST"])
       AC_MSG_ERROR([Sun Studio compiler is required. Try setting --with-tools-dir.])
@@ -69,7 +69,7 @@
       AC_MSG_NOTICE([The result from running with --version was: "$COMPILER_VERSION_TEST"])
       AC_MSG_ERROR([GCC compiler is required. Try setting --with-tools-dir.])
     fi
-    
+
     # First line typically looks something like:
     # gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
     COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* \(@<:@1-9@:>@@<:@0-9.@:>@*\)/\1/p"`
@@ -142,7 +142,7 @@
   BASIC_REMOVE_SYMBOLIC_LINKS(TEST_COMPILER)
   AC_MSG_RESULT([$TEST_COMPILER])
   AC_MSG_CHECKING([if $1 is disguised ccache])
-  
+
   COMPILER_BASENAME=`$BASENAME "$TEST_COMPILER"`
   if test "x$COMPILER_BASENAME" = "xccache"; then
     AC_MSG_RESULT([yes, trying to find proper $COMPILER_NAME compiler])
@@ -226,11 +226,11 @@
                     ],
                     [])
 
-if test "x$SYS_ROOT" != "x/" ; then                    
+if test "x$SYS_ROOT" != "x/" ; then
     CFLAGS="--sysroot=$SYS_ROOT $CFLAGS"
     CXXFLAGS="--sysroot=$SYS_ROOT $CXXFLAGS"
-    OBJCFLAGS="--sysroot=$SYS_ROOT $OBJCFLAGS" 
-    OBJCXXFLAGS="--sysroot=$SYS_ROOT $OBJCFLAGS" 
+    OBJCFLAGS="--sysroot=$SYS_ROOT $OBJCFLAGS"
+    OBJCXXFLAGS="--sysroot=$SYS_ROOT $OBJCFLAGS"
     CPPFLAGS="--sysroot=$SYS_ROOT $CPPFLAGS"
     LDFLAGS="--sysroot=$SYS_ROOT $LDFLAGS"
 fi
@@ -330,7 +330,7 @@
 COMPILER_NAME=gcc
 COMPILER_TYPE=CC
 AS_IF([test "x$OPENJDK_TARGET_OS" = xwindows], [
-    # For now, assume that we are always compiling using cl.exe. 
+    # For now, assume that we are always compiling using cl.exe.
     CC_OUT_OPTION=-Fo
     EXE_OUT_OPTION=-out:
     LD_OUT_OPTION=-out:
@@ -491,7 +491,7 @@
 
 ###############################################################################
 #
-# How to compile shared libraries. 
+# How to compile shared libraries.
 #
 
 if test "x$GCC" = xyes; then
@@ -525,7 +525,7 @@
         SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
         SHARED_LIBRARY_SUFFIX='.dylib'
         EXE_SUFFIX=''
-        SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1' 
+        SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1'
         SET_SHARED_LIBRARY_MAPFILE=''
         SET_SHARED_LIBRARY_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
         SET_EXECUTABLE_ORIGIN="$SET_SHARED_LIBRARY_ORIGIN"
@@ -676,7 +676,7 @@
         # Use single precision floating point with 'float'
         CC_HIGHEST="$CC_HIGHEST -fsingle"
         # Assume memory references via basic pointer types do not alias
-        #   (Source with excessing pointer casting and data access with mixed 
+        #   (Source with excessing pointer casting and data access with mixed
         #    pointer types are not recommended)
         CC_HIGHEST="$CC_HIGHEST -xalias_level=basic"
         # Use intrinsic or inline versions for math/std functions
@@ -892,7 +892,7 @@
 fi
 if test "x$OPENJDK_TARGET_OS" = xmacosx; then
     CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMACOSX -D_ALLBSD_SOURCE"
-    # Setting these parameters makes it an error to link to macosx APIs that are 
+    # Setting these parameters makes it an error to link to macosx APIs that are
     # newer than the given OS version and makes the linked binaries compatible even
     # if built on a newer version of the OS.
     # The expected format is X.Y.Z
@@ -940,12 +940,12 @@
 # Which should we link to? Are we lucky enough that the binary api to the libjvm.so library
 # is identical for client and server? Yes. Which is picked at runtime (client or server)?
 # Neither, since the chosen libjvm.so has already been loaded by the launcher, all the following
-# libraries will link to whatever is in memory. Yuck. 
+# libraries will link to whatever is in memory. Yuck.
 #
 # Thus we offer the compiler to find libjvm.so first in server then in client. It works. Ugh.
 if test "x$COMPILER_NAME" = xcl; then
     LDFLAGS_JDK="$LDFLAGS_JDK -nologo -opt:ref -incremental:no"
-    if test "x$OPENJDK_TARGET_CPU" = xx86; then 
+    if test "x$OPENJDK_TARGET_CPU" = xx86; then
         LDFLAGS_JDK="$LDFLAGS_JDK -safeseh"
     fi
     # TODO: make -debug optional "--disable-full-debug-symbols"
@@ -965,7 +965,7 @@
         if test -n "$HAS_GNU_HASH"; then
             LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker --hash-style=both "
         fi
-        if test "x$OPENJDK_TARGET_OS" = xlinux; then 
+        if test "x$OPENJDK_TARGET_OS" = xlinux; then
           # And since we now know that the linker is gnu, then add -z defs, to forbid
           # undefined symbols in object files.
           LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -z -Xlinker defs"
@@ -1006,7 +1006,7 @@
 
 # Adjust flags according to debug level.
 case $DEBUG_LEVEL in
-      fastdebug ) 
+      fastdebug )
               CFLAGS="$CFLAGS $D_FLAG"
               JAVAC_FLAGS="$JAVAC_FLAGS -g"
               ;;
@@ -1018,9 +1018,9 @@
 	      CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE"
               JAVAC_FLAGS="$JAVAC_FLAGS -g"
               ;;
-esac              
+esac
 
-                
+
 AC_SUBST(CFLAGS_JDKLIB)
 AC_SUBST(CFLAGS_JDKEXE)
 
@@ -1092,28 +1092,45 @@
   AC_SUBST(COMPILER_SUPPORTS_TARGET_BITS_FLAG)
 ])
 
-# Setup the JTREG paths 
-AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], 
-[ 
-  AC_ARG_WITH(jtreg, [AS_HELP_STRING([--with-jtreg], 
-  [Regression Test Harness @<:@probed@:>@])]) 
- 
-  AC_MSG_CHECKING([for JTReg Regression Test Harness]) 
- 
-  if test "x$with_jtreg" != x; then 
-    JT_HOME="$with_jtreg"
-    BASIC_FIXUP_PATH([JT_HOME])
-    AC_MSG_RESULT($JT_HOME)
- 
-    # jtreg win32 script works for everybody 
-    JTREGEXE="$JT_HOME/win32/bin/jtreg"
-    if test ! -f "$JTREGEXE"; then
-      AC_MSG_ERROR([JTReg executable does not exist: $JTREGEXE])
+# Setup the JTREG paths
+AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG],
+[
+  AC_ARG_WITH(jtreg, [AS_HELP_STRING([--with-jtreg],
+  [Regression Test Harness @<:@probed@:>@])],
+  [],
+  [with_jtreg=no])
+
+  if test "x$with_jtreg" = xno; then
+    # jtreg disabled
+    AC_MSG_CHECKING([for jtreg])
+    AC_MSG_RESULT(no)
+  else
+    if test "x$with_jtreg" != xyes; then
+      # with path specified.
+      JT_HOME="$with_jtreg"
     fi
-  else 
-    AC_MSG_RESULT(no)
-  fi 
- 
-  AC_SUBST(JT_HOME) 
-  AC_SUBST(JTREGEXE) 
+
+    if test "x$JT_HOME" != x; then
+      AC_MSG_CHECKING([for jtreg])
+
+      # use JT_HOME enviroment var.
+      BASIC_FIXUP_PATH([JT_HOME])
+
+      # jtreg win32 script works for everybody
+      JTREGEXE="$JT_HOME/win32/bin/jtreg"
+
+      if test ! -f "$JTREGEXE"; then
+        AC_MSG_ERROR([JTReg executable does not exist: $JTREGEXE])
+      fi
+
+      AC_MSG_RESULT($JTREGEXE)
+    else
+      # try to find jtreg on path
+      BASIC_REQUIRE_PROG(JTREGEXE, jtreg)
+      JT_HOME="`$DIRNAME $JTREGEXE`"
+    fi
+  fi
+
+  AC_SUBST(JT_HOME)
+  AC_SUBST(JTREGEXE)
 ])
--- a/common/makefiles/Jprt.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/common/makefiles/Jprt.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -127,9 +127,21 @@
   ifdef ALT_JAVAFX_ZIP_DIR
 	@$(ECHO) " --with-javafx-zip-dir=$(call UnixPath,$(ALT_JAVAFX_ZIP_DIR)) " >> $@.tmp
   endif
+  ifdef ALT_JMC_ZIP_DIR
+	@$(ECHO) " --with-jmc-zip-dir=$(call UnixPath,$(ALT_JMC_ZIP_DIR)) " >> $@.tmp
+  endif
   ifdef ALT_WIXDIR
 	@$(ECHO) " --with-wix=$(call UnixPath,$(ALT_WIXDIR)) " >> $@.tmp
   endif
+  ifdef ALT_INSTALL_LZMA_PATH
+	@$(ECHO) " --with-lzma-path=$(call UnixPath,$(ALT_INSTALL_LZMA_PATH)) " >> $@.tmp
+  endif
+  ifdef ALT_INSTALL_UPX_PATH
+	@$(ECHO) " --with-upx-path=$(call UnixPath,$(ALT_INSTALL_UPX_PATH)) " >> $@.tmp
+  endif
+  ifdef ALT_INSTALL_UPX_FILENAME
+	@$(ECHO) " --with-upx-filename=$(call UnixPath,$(ALT_INSTALL_UPX_FILENAME)) " >> $@.tmp
+  endif
   ifdef ALT_CCSS_SIGNING_DIR
 	@$(ECHO) " --with-ccss-signing=$(call UnixPath,$(ALT_CCSS_SIGNING_DIR)) " >> $@.tmp
   endif
--- a/common/makefiles/Main.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/common/makefiles/Main.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -183,7 +183,7 @@
 test: images test-only
 test-only: start-make
 	@$(call TargetEnter)
-	@($(CD) $(SRC_ROOT)/test && $(BUILD_LOG_WRAPPER) $(MAKE) -j1 -k MAKEFLAGS= PRODUCT_HOME=$(JDK_IMAGE_DIR) JPRT_JAVA_HOME=$(JDK_IMAGE_DIR) ALT_OUTPUTDIR=$(OUTPUT_ROOT) $(TEST)) || true
+	@($(CD) $(SRC_ROOT)/test && $(BUILD_LOG_WRAPPER) $(MAKE) -j1 -k JT_HOME=$(JT_HOME) MAKEFLAGS= PRODUCT_HOME=$(JDK_IMAGE_DIR) JPRT_JAVA_HOME=$(JDK_IMAGE_DIR) ALT_OUTPUTDIR=$(OUTPUT_ROOT) $(TEST)) || true
 	@$(call TargetExit)
 
 # Stores the tips for each repository. This file is be used when constructing the jdk image and can be
--- a/common/makefiles/MakeBase.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/common/makefiles/MakeBase.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -361,8 +361,8 @@
 
 # This is to be called by all SetupFoo macros
 define LogSetupMacroEntry
-    $(if $(26),$(error Internal makefile error: Too many arguments to LogSetupMacroEntry, please update MakeBase.gmk))
-    $(if $(findstring $(LOG_LEVEL),debug trace), $(info $1 $(foreach i,2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25,$(if $($i),$(NEWLINE) $(strip [$i] $($i))))))
+    $(if $(27),$(error Internal makefile error: Too many arguments to LogSetupMacroEntry, please update MakeBase.gmk))
+    $(if $(findstring $(LOG_LEVEL),debug trace), $(info $1 $(foreach i,2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26,$(if $($i),$(NEWLINE) $(strip [$i] $($i))))))
 endef
 
 # Make directory without forking mkdir if not needed
--- a/common/makefiles/NativeCompilation.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/common/makefiles/NativeCompilation.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -147,9 +147,9 @@
     #    CC the compiler to use, default is $(CC)
     #    LDEXE the linker to use for linking executables, default is $(LDEXE)
     #    OPTIMIZATION sets optimization level to NONE, LOW, HIGH, HIGHEST
-    $(foreach i,2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25, $(if $($i),$1_$(strip $($i)))$(NEWLINE))
-    $(call LogSetupMacroEntry,SetupNativeCompilation($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15),$(16),$(17),$(18),$(19),$(20),$(21),$(22),$(23),$(24),$(25))
-    $(if $(26),$(error Internal makefile error: Too many arguments to SetupNativeCompilation, please update NativeCompilation.gmk))
+    $(foreach i,2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26, $(if $($i),$1_$(strip $($i)))$(NEWLINE))
+    $(call LogSetupMacroEntry,SetupNativeCompilation($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15),$(16),$(17),$(18),$(19),$(20),$(21),$(22),$(23),$(24),$(25),$(26))
+    $(if $(27),$(error Internal makefile error: Too many arguments to SetupNativeCompilation, please update NativeCompilation.gmk))
 
     ifneq (,$$($1_BIN))
         $$(error BIN has been replaced with OBJECT_DIR)
@@ -567,6 +567,12 @@
         ifneq (,$$($1_GEN_MANIFEST))
 		$(MT) -nologo -manifest $$($1_GEN_MANIFEST) -outputresource:$$@;#1
         endif
-
+        # This only works if the openjdk_codesign identity is present on the system. Let
+        # silently fail otherwise.
+        ifneq (,$(CODESIGN))
+            ifneq (,$$($1_CODESIGN))
+		$(CODESIGN) -s openjdk_codesign $$@
+            endif
+        endif
     endif
 endef
--- a/corba/.hgtags	Thu May 30 10:58:13 2013 -0700
+++ b/corba/.hgtags	Wed Jul 05 18:57:52 2017 +0200
@@ -213,3 +213,4 @@
 fe4150590ee597f4e125fea950aa3b352622cc2d jdk8-b89
 c8286839d0df04aba819ec4bef12b86babccf30e jdk8-b90
 8f7ffb296385f85a4a6d53f9f2d4a7b13a8fa1ff jdk8-b91
+717aa26f8e0a1c0e768aebb3a763aca56db0c83e jdk8-b92
--- a/hotspot/.hgtags	Thu May 30 10:58:13 2013 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 18:57:52 2017 +0200
@@ -345,3 +345,4 @@
 b19517cecc2e91636d7c16ba2f35e3d3dc628099 hs25-b33
 7cbdf0e3725c0c56a2ff7540fc70b6d4b5890d04 jdk8-b91
 38da9f4f67096745f851318d792d6468aa1f6cf8 hs25-b34
+092018493d3bbeb1c24278fd8c40ff3d76e1fed7 jdk8-b92
--- a/jaxp/.hgtags	Thu May 30 10:58:13 2013 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 18:57:52 2017 +0200
@@ -213,3 +213,4 @@
 893d2ba8bbea3a8d090e51d8eaea285b390789ea jdk8-b89
 668acc0e1034bc1bec6d02be92e0dd4a63d0667e jdk8-b90
 e3065fb07877c7e96e8b93416fe2ab9a4c9eb2a5 jdk8-b91
+1ab5d8d6eab81e65c6c3cf21739474cd67a0e7cf jdk8-b92
--- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java	Thu May 30 10:58:13 2013 -0700
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java	Wed Jul 05 18:57:52 2017 +0200
@@ -236,10 +236,6 @@
                 String feature = (String) entry.getKey();
                 boolean value = ((Boolean) entry.getValue()).booleanValue();
                 domParser.setFeature(feature, value);
-                if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
-                    domParser.setProperty(ACCESS_EXTERNAL_DTD, "");
-                    domParser.setProperty(ACCESS_EXTERNAL_SCHEMA, "");
-                }
             }
         }
     }
--- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java	Thu May 30 10:58:13 2013 -0700
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java	Wed Jul 05 18:57:52 2017 +0200
@@ -242,10 +242,6 @@
                 String feature = (String) entry.getKey();
                 boolean value = ((Boolean) entry.getValue()).booleanValue();
                 xmlReader.setFeature0(feature, value);
-                if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING) && value) {
-                    xmlReader.setProperty0(ACCESS_EXTERNAL_DTD, "");
-                    xmlReader.setProperty0(ACCESS_EXTERNAL_SCHEMA, "");
-                }
             }
         }
     }
--- a/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/ObjectFactory.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,553 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2005 The Apache Software Foundation.
- *
- * 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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.xerces.internal.xinclude;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.File;
-import java.io.FileInputStream;
-
-import java.util.Properties;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
-/**
- * This class is duplicated for each JAXP subpackage so keep it in sync.
- * It is package private and therefore is not exposed as part of the JAXP
- * API.
- * <p>
- * This code is designed to implement the JAXP 1.1 spec pluggability
- * feature and is designed to run on JDK version 1.1 and
- * later, and to compile on JDK 1.2 and onward.
- * The code also runs both as part of an unbundled jar file and
- * when bundled as part of the JDK.
- * <p>
- *
- */
-final class ObjectFactory {
-
-    //
-    // Constants
-    //
-
-    // name of default properties file to look for in JDK's jre/lib directory
-    private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties";
-
-    /** Set to true for debugging */
-    private static final boolean DEBUG = false;
-
-    /**
-     * Default columns per line.
-     */
-    private static final int DEFAULT_LINE_LENGTH = 80;
-
-    /** cache the contents of the xerces.properties file.
-     *  Until an attempt has been made to read this file, this will
-     * be null; if the file does not exist or we encounter some other error
-     * during the read, this will be empty.
-     */
-    private static Properties fXercesProperties = null;
-
-    /***
-     * Cache the time stamp of the xerces.properties file so
-     * that we know if it's been modified and can invalidate
-     * the cache when necessary.
-     */
-    private static long fLastModified = -1;
-
-    //
-    // static methods
-    //
-
-    /**
-     * Finds the implementation Class object in the specified order.  The
-     * specified order is the following:
-     * <ol>
-     *  <li>query the system property using <code>System.getProperty</code>
-     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
-     *  <li>use fallback classname
-     * </ol>
-     *
-     * @return Class object of factory, never null
-     *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
-     * @param fallbackClassName     Implementation class name, if nothing else
-     *                              is found.  Use null to mean no fallback.
-     *
-     * @exception ObjectFactory.ConfigurationError
-     */
-    static Object createObject(String factoryId, String fallbackClassName)
-        throws ConfigurationError {
-        return createObject(factoryId, null, fallbackClassName);
-    } // createObject(String,String):Object
-
-    /**
-     * Finds the implementation Class object in the specified order.  The
-     * specified order is the following:
-     * <ol>
-     *  <li>query the system property using <code>System.getProperty</code>
-     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
-     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
-     *  <li>use fallback classname
-     * </ol>
-     *
-     * @return Class object of factory, never null
-     *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
-     * @param propertiesFilename The filename in the $java.home/lib directory
-     *                           of the properties file.  If none specified,
-     *                           ${java.home}/lib/xerces.properties will be used.
-     * @param fallbackClassName     Implementation class name, if nothing else
-     *                              is found.  Use null to mean no fallback.
-     *
-     * @exception ObjectFactory.ConfigurationError
-     */
-    static Object createObject(String factoryId,
-                                      String propertiesFilename,
-                                      String fallbackClassName)
-        throws ConfigurationError
-    {
-        if (DEBUG) debugPrintln("debug is on");
-
-        SecuritySupport ss = SecuritySupport.getInstance();
-        ClassLoader cl = findClassLoader();
-
-        // Use the system property first
-        try {
-            String systemProp = ss.getSystemProperty(factoryId);
-            if (systemProp != null) {
-                if (DEBUG) debugPrintln("found system property, value=" + systemProp);
-                return newInstance(systemProp, cl, true);
-            }
-        } catch (SecurityException se) {
-            // Ignore and continue w/ next location
-        }
-
-        // JAXP specific change
-        // always use fallback class to avoid the expense of constantly
-        // "stat"ing a non-existent "xerces.properties" and jar SPI entry
-        // see CR 6400863: Expensive creating of SAX parser in Mustang
-        if (true) {
-            if (fallbackClassName == null) {
-                throw new ConfigurationError(
-                    "Provider for " + factoryId + " cannot be found", null);
-            }
-
-            if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
-            return newInstance(fallbackClassName, cl, true);
-        }
-
-        // Try to read from propertiesFilename, or $java.home/lib/xerces.properties
-        String factoryClassName = null;
-        // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:
-        if (propertiesFilename == null) {
-            File propertiesFile = null;
-            boolean propertiesFileExists = false;
-            try {
-                String javah = ss.getSystemProperty("java.home");
-                propertiesFilename = javah + File.separator +
-                    "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
-                propertiesFile = new File(propertiesFilename);
-                propertiesFileExists = ss.getFileExists(propertiesFile);
-            } catch (SecurityException e) {
-                // try again...
-                fLastModified = -1;
-                fXercesProperties = null;
-            }
-
-            synchronized (ObjectFactory.class) {
-                boolean loadProperties = false;
-                FileInputStream fis = null;
-                try {
-                    // file existed last time
-                    if(fLastModified >= 0) {
-                        if(propertiesFileExists &&
-                                (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) {
-                            loadProperties = true;
-                        } else {
-                            // file has stopped existing...
-                            if(!propertiesFileExists) {
-                                fLastModified = -1;
-                                fXercesProperties = null;
-                            } // else, file wasn't modified!
-                        }
-                    } else {
-                        // file has started to exist:
-                        if(propertiesFileExists) {
-                            loadProperties = true;
-                            fLastModified = ss.getLastModified(propertiesFile);
-                        } // else, nothing's changed
-                    }
-                    if(loadProperties) {
-                        // must never have attempted to read xerces.properties before (or it's outdeated)
-                        fXercesProperties = new Properties();
-                        fis = ss.getFileInputStream(propertiesFile);
-                        fXercesProperties.load(fis);
-                    }
-                } catch (Exception x) {
-                    fXercesProperties = null;
-                    fLastModified = -1;
-                    // assert(x instanceof FileNotFoundException
-                    //        || x instanceof SecurityException)
-                    // In both cases, ignore and continue w/ next location
-                }
-                finally {
-                    // try to close the input stream if one was opened.
-                    if (fis != null) {
-                        try {
-                            fis.close();
-                        }
-                        // Ignore the exception.
-                        catch (IOException exc) {}
-                    }
-                }
-            }
-            if(fXercesProperties != null) {
-                factoryClassName = fXercesProperties.getProperty(factoryId);
-            }
-        } else {
-            FileInputStream fis = null;
-            try {
-                fis = ss.getFileInputStream(new File(propertiesFilename));
-                Properties props = new Properties();
-                props.load(fis);
-                factoryClassName = props.getProperty(factoryId);
-            } catch (Exception x) {
-                // assert(x instanceof FileNotFoundException
-                //        || x instanceof SecurityException)
-                // In both cases, ignore and continue w/ next location
-            }
-            finally {
-                // try to close the input stream if one was opened.
-                if (fis != null) {
-                    try {
-                        fis.close();
-                    }
-                    // Ignore the exception.
-                    catch (IOException exc) {}
-                }
-            }
-        }
-        if (factoryClassName != null) {
-            if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);
-            return newInstance(factoryClassName, cl, true);
-        }
-
-        // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
-        if (provider != null) {
-            return provider;
-        }
-
-        if (fallbackClassName == null) {
-            throw new ConfigurationError(
-                "Provider for " + factoryId + " cannot be found", null);
-        }
-
-        if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
-        return newInstance(fallbackClassName, cl, true);
-    } // createObject(String,String,String):Object
-
-    //
-    // Private static methods
-    //
-
-    /** Prints a message to standard error if debugging is enabled. */
-    private static void debugPrintln(String msg) {
-        if (DEBUG) {
-            System.err.println("JAXP: " + msg);
-        }
-    } // debugPrintln(String)
-
-    /**
-     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
-     * the context ClassLoader.
-     */
-    static ClassLoader findClassLoader()
-        throws ConfigurationError
-    {
-        SecuritySupport ss = SecuritySupport.getInstance();
-
-        // Figure out which ClassLoader to use for loading the provider
-        // class.  If there is a Context ClassLoader then use it.
-        ClassLoader context = ss.getContextClassLoader();
-        ClassLoader system = ss.getSystemClassLoader();
-
-        ClassLoader chain = system;
-        while (true) {
-            if (context == chain) {
-                // Assert: we are on JDK 1.1 or we have no Context ClassLoader
-                // or any Context ClassLoader in chain of system classloader
-                // (including extension ClassLoader) so extend to widest
-                // ClassLoader (always look in system ClassLoader if Xerces
-                // is in boot/extension/system classpath and in current
-                // ClassLoader otherwise); normal classloaders delegate
-                // back to system ClassLoader first so this widening doesn't
-                // change the fact that context ClassLoader will be consulted
-                ClassLoader current = ObjectFactory.class.getClassLoader();
-
-                chain = system;
-                while (true) {
-                    if (current == chain) {
-                        // Assert: Current ClassLoader in chain of
-                        // boot/extension/system ClassLoaders
-                        return system;
-                    }
-                    if (chain == null) {
-                        break;
-                    }
-                    chain = ss.getParentClassLoader(chain);
-                }
-
-                // Assert: Current ClassLoader not in chain of
-                // boot/extension/system ClassLoaders
-                return current;
-            }
-
-            if (chain == null) {
-                // boot ClassLoader reached
-                break;
-            }
-
-            // Check for any extension ClassLoaders in chain up to
-            // boot ClassLoader
-            chain = ss.getParentClassLoader(chain);
-        };
-
-        // Assert: Context ClassLoader not in chain of
-        // boot/extension/system ClassLoaders
-        return context;
-    } // findClassLoader():ClassLoader
-
-    /**
-     * Create an instance of a class using the specified ClassLoader
-     */
-    static Object newInstance(String className, ClassLoader cl,
-                                      boolean doFallback)
-        throws ConfigurationError
-    {
-        // assert(className != null);
-        try{
-            Class providerClass = findProviderClass(className, cl, doFallback);
-            Object instance = providerClass.newInstance();
-            if (DEBUG) debugPrintln("created new instance of " + providerClass +
-                   " using ClassLoader: " + cl);
-            return instance;
-        } catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
-                "Provider " + className + " not found", x);
-        } catch (Exception x) {
-            throw new ConfigurationError(
-                "Provider " + className + " could not be instantiated: " + x,
-                x);
-        }
-    }
-
-    /**
-     * Find a Class using the specified ClassLoader
-     */
-    static Class findProviderClass(String className, ClassLoader cl,
-                                      boolean doFallback)
-        throws ClassNotFoundException, ConfigurationError
-    {
-        //throw security exception if the calling thread is not allowed to access the package
-        //restrict the access to package as speicified in java.security policy
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            final int lastDot = className.lastIndexOf(".");
-            String packageName = className;
-            if (lastDot != -1) packageName = className.substring(0, lastDot);
-            security.checkPackageAccess(packageName);
-        }
-        Class providerClass;
-        if (cl == null) {
-            // XXX Use the bootstrap ClassLoader.  There is no way to
-            // load a class using the bootstrap ClassLoader that works
-            // in both JDK 1.1 and Java 2.  However, this should still
-            // work b/c the following should be true:
-            //
-            // (cl == null) iff current ClassLoader == null
-            //
-            // Thus Class.forName(String) will use the current
-            // ClassLoader which will be the bootstrap ClassLoader.
-            providerClass = Class.forName(className);
-        } else {
-            try {
-                providerClass = cl.loadClass(className);
-            } catch (ClassNotFoundException x) {
-                if (doFallback) {
-                    // Fall back to current classloader
-                    ClassLoader current = ObjectFactory.class.getClassLoader();
-                    if (current == null) {
-                        providerClass = Class.forName(className);
-                    } else if (cl != current) {
-                        cl = current;
-                        providerClass = cl.loadClass(className);
-                    } else {
-                        throw x;
-                    }
-                } else {
-                    throw x;
-                }
-            }
-        }
-
-        return providerClass;
-    }
-
-    /*
-     * Try to find provider using Jar Service Provider Mechanism
-     *
-     * @return instance of provider class if found or null
-     */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
-    {
-        SecuritySupport ss = SecuritySupport.getInstance();
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = findClassLoader();
-
-        is = ss.getResourceAsStream(cl, serviceId);
-
-        // If no provider found then try the current ClassLoader
-        if (is == null) {
-            ClassLoader current = ObjectFactory.class.getClassLoader();
-            if (cl != current) {
-                cl = current;
-                is = ss.getResourceAsStream(cl, serviceId);
-            }
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (DEBUG) debugPrintln("found jar resource=" + serviceId +
-               " using ClassLoader: " + cl);
-
-        // Read the service provider name in UTF-8 as specified in
-        // the jar spec.  Unfortunately this fails in Microsoft
-        // VJ++, which does not implement the UTF-8
-        // encoding. Theoretically, we should simply let it fail in
-        // that case, since the JVM is obviously broken if it
-        // doesn't support such a basic standard.  But since there
-        // are still some users attempting to use VJ++ for
-        // development, we have dropped in a fallback which makes a
-        // second attempt using the platform's default encoding. In
-        // VJ++ this is apparently ASCII, which is a subset of
-        // UTF-8... and since the strings we'll be reading here are
-        // also primarily limited to the 7-bit ASCII range (at
-        // least, in English versions), this should work well
-        // enough to keep us on the air until we're ready to
-        // officially decommit from VJ++. [Edited comment from
-        // jkesselm]
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
-        } catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
-        }
-
-        String factoryClassName = null;
-        try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-        finally {
-            try {
-                // try to close the reader.
-                rd.close();
-            }
-            // Ignore the exception.
-            catch (IOException exc) {}
-        }
-
-        if (factoryClassName != null &&
-            ! "".equals(factoryClassName)) {
-            if (DEBUG) debugPrintln("found in resource, value="
-                   + factoryClassName);
-
-            // Note: here we do not want to fall back to the current
-            // ClassLoader because we want to avoid the case where the
-            // resource file was found using one ClassLoader and the
-            // provider class was instantiated using a different one.
-            return newInstance(factoryClassName, cl, false);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    //
-    // Classes
-    //
-
-    /**
-     * A configuration error.
-     */
-    static final class ConfigurationError
-        extends Error {
-
-        /** Serialization version. */
-        static final long serialVersionUID = 5061904944269807898L;
-
-        //
-        // Data
-        //
-
-        /** Exception. */
-        private Exception exception;
-
-        //
-        // Constructors
-        //
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        } // <init>(String,Exception)
-
-        //
-        // methods
-        //
-
-        /** Returns the exception associated to this error. */
-        Exception getException() {
-            return exception;
-        } // getException():Exception
-
-    } // class ConfigurationError
-
-} // class ObjectFactory
--- a/jaxp/src/com/sun/org/apache/xml/internal/serialize/ObjectFactory.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,553 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2005 The Apache Software Foundation.
- *
- * 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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.xml.internal.serialize;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.File;
-import java.io.FileInputStream;
-
-import java.util.Properties;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
-/**
- * This class is duplicated for each JAXP subpackage so keep it in sync.
- * It is package private and therefore is not exposed as part of the JAXP
- * API.
- * <p>
- * This code is designed to implement the JAXP 1.1 spec pluggability
- * feature and is designed to run on JDK version 1.1 and
- * later, and to compile on JDK 1.2 and onward.
- * The code also runs both as part of an unbundled jar file and
- * when bundled as part of the JDK.
- * <p>
- *
- */
-final class ObjectFactory {
-
-    //
-    // Constants
-    //
-
-    // name of default properties file to look for in JDK's jre/lib directory
-    private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties";
-
-    /** Set to true for debugging */
-    private static final boolean DEBUG = false;
-
-    /**
-     * Default columns per line.
-     */
-    private static final int DEFAULT_LINE_LENGTH = 80;
-
-    /** cache the contents of the xerces.properties file.
-     *  Until an attempt has been made to read this file, this will
-     * be null; if the file does not exist or we encounter some other error
-     * during the read, this will be empty.
-     */
-    private static Properties fXercesProperties = null;
-
-    /***
-     * Cache the time stamp of the xerces.properties file so
-     * that we know if it's been modified and can invalidate
-     * the cache when necessary.
-     */
-    private static long fLastModified = -1;
-
-    //
-    // static methods
-    //
-
-    /**
-     * Finds the implementation Class object in the specified order.  The
-     * specified order is the following:
-     * <ol>
-     *  <li>query the system property using <code>System.getProperty</code>
-     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
-     *  <li>use fallback classname
-     * </ol>
-     *
-     * @return Class object of factory, never null
-     *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
-     * @param fallbackClassName     Implementation class name, if nothing else
-     *                              is found.  Use null to mean no fallback.
-     *
-     * @exception ObjectFactory.ConfigurationError
-     */
-    static Object createObject(String factoryId, String fallbackClassName)
-        throws ConfigurationError {
-        return createObject(factoryId, null, fallbackClassName);
-    } // createObject(String,String):Object
-
-    /**
-     * Finds the implementation Class object in the specified order.  The
-     * specified order is the following:
-     * <ol>
-     *  <li>query the system property using <code>System.getProperty</code>
-     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
-     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
-     *  <li>use fallback classname
-     * </ol>
-     *
-     * @return Class object of factory, never null
-     *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
-     * @param propertiesFilename The filename in the $java.home/lib directory
-     *                           of the properties file.  If none specified,
-     *                           ${java.home}/lib/xerces.properties will be used.
-     * @param fallbackClassName     Implementation class name, if nothing else
-     *                              is found.  Use null to mean no fallback.
-     *
-     * @exception ObjectFactory.ConfigurationError
-     */
-    static Object createObject(String factoryId,
-                                      String propertiesFilename,
-                                      String fallbackClassName)
-        throws ConfigurationError
-    {
-        if (DEBUG) debugPrintln("debug is on");
-
-        SecuritySupport ss = SecuritySupport.getInstance();
-        ClassLoader cl = findClassLoader();
-
-        // Use the system property first
-        try {
-            String systemProp = ss.getSystemProperty(factoryId);
-            if (systemProp != null) {
-                if (DEBUG) debugPrintln("found system property, value=" + systemProp);
-                return newInstance(systemProp, cl, true);
-            }
-        } catch (SecurityException se) {
-            // Ignore and continue w/ next location
-        }
-
-        // JAXP specific change
-        // always use fallback class to avoid the expense of constantly
-        // "stat"ing a non-existent "xerces.properties" and jar SPI entry
-        // see CR 6400863: Expensive creating of SAX parser in Mustang
-        if (true) {
-            if (fallbackClassName == null) {
-                throw new ConfigurationError(
-                    "Provider for " + factoryId + " cannot be found", null);
-            }
-
-            if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
-            return newInstance(fallbackClassName, cl, true);
-        }
-
-        // Try to read from propertiesFilename, or $java.home/lib/xerces.properties
-        String factoryClassName = null;
-        // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:
-        if (propertiesFilename == null) {
-            File propertiesFile = null;
-            boolean propertiesFileExists = false;
-            try {
-                String javah = ss.getSystemProperty("java.home");
-                propertiesFilename = javah + File.separator +
-                    "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
-                propertiesFile = new File(propertiesFilename);
-                propertiesFileExists = ss.getFileExists(propertiesFile);
-            } catch (SecurityException e) {
-                // try again...
-                fLastModified = -1;
-                fXercesProperties = null;
-            }
-
-            synchronized (ObjectFactory.class) {
-                boolean loadProperties = false;
-                FileInputStream fis = null;
-                try {
-                    // file existed last time
-                    if(fLastModified >= 0) {
-                        if(propertiesFileExists &&
-                                (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) {
-                            loadProperties = true;
-                        } else {
-                            // file has stopped existing...
-                            if(!propertiesFileExists) {
-                                fLastModified = -1;
-                                fXercesProperties = null;
-                            } // else, file wasn't modified!
-                        }
-                    } else {
-                        // file has started to exist:
-                        if(propertiesFileExists) {
-                            loadProperties = true;
-                            fLastModified = ss.getLastModified(propertiesFile);
-                        } // else, nothing's changed
-                    }
-                    if(loadProperties) {
-                        // must never have attempted to read xerces.properties before (or it's outdeated)
-                        fXercesProperties = new Properties();
-                        fis = ss.getFileInputStream(propertiesFile);
-                        fXercesProperties.load(fis);
-                    }
-                } catch (Exception x) {
-                    fXercesProperties = null;
-                    fLastModified = -1;
-                    // assert(x instanceof FileNotFoundException
-                    //        || x instanceof SecurityException)
-                    // In both cases, ignore and continue w/ next location
-                }
-                finally {
-                    // try to close the input stream if one was opened.
-                    if (fis != null) {
-                        try {
-                            fis.close();
-                        }
-                        // Ignore the exception.
-                        catch (IOException exc) {}
-                    }
-                }
-            }
-            if(fXercesProperties != null) {
-                factoryClassName = fXercesProperties.getProperty(factoryId);
-            }
-        } else {
-            FileInputStream fis = null;
-            try {
-                fis = ss.getFileInputStream(new File(propertiesFilename));
-                Properties props = new Properties();
-                props.load(fis);
-                factoryClassName = props.getProperty(factoryId);
-            } catch (Exception x) {
-                // assert(x instanceof FileNotFoundException
-                //        || x instanceof SecurityException)
-                // In both cases, ignore and continue w/ next location
-            }
-            finally {
-                // try to close the input stream if one was opened.
-                if (fis != null) {
-                    try {
-                        fis.close();
-                    }
-                    // Ignore the exception.
-                    catch (IOException exc) {}
-                }
-            }
-        }
-        if (factoryClassName != null) {
-            if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);
-            return newInstance(factoryClassName, cl, true);
-        }
-
-        // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
-        if (provider != null) {
-            return provider;
-        }
-
-        if (fallbackClassName == null) {
-            throw new ConfigurationError(
-                "Provider for " + factoryId + " cannot be found", null);
-        }
-
-        if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
-        return newInstance(fallbackClassName, cl, true);
-    } // createObject(String,String,String):Object
-
-    //
-    // Private static methods
-    //
-
-    /** Prints a message to standard error if debugging is enabled. */
-    private static void debugPrintln(String msg) {
-        if (DEBUG) {
-            System.err.println("JAXP: " + msg);
-        }
-    } // debugPrintln(String)
-
-    /**
-     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
-     * the context ClassLoader.
-     */
-    static ClassLoader findClassLoader()
-        throws ConfigurationError
-    {
-        SecuritySupport ss = SecuritySupport.getInstance();
-
-        // Figure out which ClassLoader to use for loading the provider
-        // class.  If there is a Context ClassLoader then use it.
-        ClassLoader context = ss.getContextClassLoader();
-        ClassLoader system = ss.getSystemClassLoader();
-
-        ClassLoader chain = system;
-        while (true) {
-            if (context == chain) {
-                // Assert: we are on JDK 1.1 or we have no Context ClassLoader
-                // or any Context ClassLoader in chain of system classloader
-                // (including extension ClassLoader) so extend to widest
-                // ClassLoader (always look in system ClassLoader if Xerces
-                // is in boot/extension/system classpath and in current
-                // ClassLoader otherwise); normal classloaders delegate
-                // back to system ClassLoader first so this widening doesn't
-                // change the fact that context ClassLoader will be consulted
-                ClassLoader current = ObjectFactory.class.getClassLoader();
-
-                chain = system;
-                while (true) {
-                    if (current == chain) {
-                        // Assert: Current ClassLoader in chain of
-                        // boot/extension/system ClassLoaders
-                        return system;
-                    }
-                    if (chain == null) {
-                        break;
-                    }
-                    chain = ss.getParentClassLoader(chain);
-                }
-
-                // Assert: Current ClassLoader not in chain of
-                // boot/extension/system ClassLoaders
-                return current;
-            }
-
-            if (chain == null) {
-                // boot ClassLoader reached
-                break;
-            }
-
-            // Check for any extension ClassLoaders in chain up to
-            // boot ClassLoader
-            chain = ss.getParentClassLoader(chain);
-        };
-
-        // Assert: Context ClassLoader not in chain of
-        // boot/extension/system ClassLoaders
-        return context;
-    } // findClassLoader():ClassLoader
-
-    /**
-     * Create an instance of a class using the specified ClassLoader
-     */
-    static Object newInstance(String className, ClassLoader cl,
-                                      boolean doFallback)
-        throws ConfigurationError
-    {
-        // assert(className != null);
-        try{
-            Class providerClass = findProviderClass(className, cl, doFallback);
-            Object instance = providerClass.newInstance();
-            if (DEBUG) debugPrintln("created new instance of " + providerClass +
-                   " using ClassLoader: " + cl);
-            return instance;
-        } catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
-                "Provider " + className + " not found", x);
-        } catch (Exception x) {
-            throw new ConfigurationError(
-                "Provider " + className + " could not be instantiated: " + x,
-                x);
-        }
-    }
-
-    /**
-     * Find a Class using the specified ClassLoader
-     */
-    static Class findProviderClass(String className, ClassLoader cl,
-                                      boolean doFallback)
-        throws ClassNotFoundException, ConfigurationError
-    {
-        //throw security exception if the calling thread is not allowed to access the package
-        //restrict the access to package as speicified in java.security policy
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            final int lastDot = className.lastIndexOf(".");
-            String packageName = className;
-            if (lastDot != -1) packageName = className.substring(0, lastDot);
-            security.checkPackageAccess(packageName);
-        }
-        Class providerClass;
-        if (cl == null) {
-            // XXX Use the bootstrap ClassLoader.  There is no way to
-            // load a class using the bootstrap ClassLoader that works
-            // in both JDK 1.1 and Java 2.  However, this should still
-            // work b/c the following should be true:
-            //
-            // (cl == null) iff current ClassLoader == null
-            //
-            // Thus Class.forName(String) will use the current
-            // ClassLoader which will be the bootstrap ClassLoader.
-            providerClass = Class.forName(className);
-        } else {
-            try {
-                providerClass = cl.loadClass(className);
-            } catch (ClassNotFoundException x) {
-                if (doFallback) {
-                    // Fall back to current classloader
-                    ClassLoader current = ObjectFactory.class.getClassLoader();
-                    if (current == null) {
-                        providerClass = Class.forName(className);
-                    } else if (cl != current) {
-                        cl = current;
-                        providerClass = cl.loadClass(className);
-                    } else {
-                        throw x;
-                    }
-                } else {
-                    throw x;
-                }
-            }
-        }
-
-        return providerClass;
-    }
-
-    /*
-     * Try to find provider using Jar Service Provider Mechanism
-     *
-     * @return instance of provider class if found or null
-     */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
-    {
-        SecuritySupport ss = SecuritySupport.getInstance();
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = findClassLoader();
-
-        is = ss.getResourceAsStream(cl, serviceId);
-
-        // If no provider found then try the current ClassLoader
-        if (is == null) {
-            ClassLoader current = ObjectFactory.class.getClassLoader();
-            if (cl != current) {
-                cl = current;
-                is = ss.getResourceAsStream(cl, serviceId);
-            }
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (DEBUG) debugPrintln("found jar resource=" + serviceId +
-               " using ClassLoader: " + cl);
-
-        // Read the service provider name in UTF-8 as specified in
-        // the jar spec.  Unfortunately this fails in Microsoft
-        // VJ++, which does not implement the UTF-8
-        // encoding. Theoretically, we should simply let it fail in
-        // that case, since the JVM is obviously broken if it
-        // doesn't support such a basic standard.  But since there
-        // are still some users attempting to use VJ++ for
-        // development, we have dropped in a fallback which makes a
-        // second attempt using the platform's default encoding. In
-        // VJ++ this is apparently ASCII, which is a subset of
-        // UTF-8... and since the strings we'll be reading here are
-        // also primarily limited to the 7-bit ASCII range (at
-        // least, in English versions), this should work well
-        // enough to keep us on the air until we're ready to
-        // officially decommit from VJ++. [Edited comment from
-        // jkesselm]
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
-        } catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
-        }
-
-        String factoryClassName = null;
-        try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-        finally {
-            try {
-                // try to close the reader.
-                rd.close();
-            }
-            // Ignore the exception.
-            catch (IOException exc) {}
-        }
-
-        if (factoryClassName != null &&
-            ! "".equals(factoryClassName)) {
-            if (DEBUG) debugPrintln("found in resource, value="
-                   + factoryClassName);
-
-            // Note: here we do not want to fall back to the current
-            // ClassLoader because we want to avoid the case where the
-            // resource file was found using one ClassLoader and the
-            // provider class was instantiated using a different one.
-            return newInstance(factoryClassName, cl, false);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    //
-    // Classes
-    //
-
-    /**
-     * A configuration error.
-     */
-    static final class ConfigurationError
-        extends Error {
-
-        /** Serialization version. */
-        static final long serialVersionUID = 937647395548533254L;
-
-        //
-        // Data
-        //
-
-        /** Exception. */
-        private Exception exception;
-
-        //
-        // Constructors
-        //
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        } // <init>(String,Exception)
-
-        //
-        // methods
-        //
-
-        /** Returns the exception associated to this error. */
-        Exception getException() {
-            return exception;
-        } // getException():Exception
-
-    } // class ConfigurationError
-
-} // class ObjectFactory
--- a/jdk/.hgtags	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/.hgtags	Wed Jul 05 18:57:52 2017 +0200
@@ -213,3 +213,4 @@
 845025546e35519fbb8970e79fc2a834063a5e19 jdk8-b89
 c63eda8f63008a4398d2c22ac8d72f7fef6f9238 jdk8-b90
 169451cf0cc53bde5af24f9820ea3f35ec4b4df4 jdk8-b91
+a2a2a91075ad85becbe10a39d7fd04ef9bea8df5 jdk8-b92
--- a/jdk/make/common/Defs-windows.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/make/common/Defs-windows.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 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
@@ -432,40 +432,3 @@
             -d "JDK_COPYRIGHT=$(JDK_RC_COPYRIGHT)" \
             -d "JDK_NAME=$(JDK_RC_NAME)" \
             -d "JDK_FVER=$(JDK_RC_FVER)"
-
-# Enable 7-Zip LZMA file (de)compression for Java Kernel if it is available
-ifeq ($(ARCH_DATA_MODEL), 32)
-  ifneq ($(KERNEL), off)
-    # This is a hack to use until  7-Zip (and UPX) bundles can be put
-    # under /java/devtools.
-    ifndef DEPLOY_TOPDIR
-      DEPLOY_TOPDIR=$(JDK_TOPDIR)/../deploy
-    endif
-    # Uncomment this block to cause build failure if above assumption false
-    #DCHK = $(shell if [ ! -d $(DEPLOY_TOPDIR) ] ; then \
-    #  $(ECHO) deploy_not_a_peer_of_j2se ; \
-    #fi )
-    #ifeq ($(DCHK), deploy_not_a_peer_of_j2se)
-    #  If a build failure points to control coming here it means
-    #  it means deploy is not in the same directory
-    #  as j2se. Java Kernel can't tolerate that for the time being.
-    #endif
-    EC_TMP = $(shell if [ -d $(DEPLOY_TOPDIR)/make/lzma ] ; then \
-      $(ECHO) true ; \
-    else \
-      $(ECHO) false ; \
-    fi )
-    ifeq ($(EC_TMP), true)
-      EXTRA_COMP_INSTALL_PATH = lib\\\\deploy\\\\lzma.dll
-      # Crazy but true: deploy/make/plugin/jinstall/Makefile.jkernel does
-      # not include deploy/make/common/Defs-windows.gmk, either directly
-      # or indirectly. But it does include this file, so redundantly declare
-      # these variables that are in deploy/make/common/Defs-windows.gmk for
-      # the sake of the Java Kernel part of the deploy build. Whew!
-      EXTRA_COMP_LIB_NAME = lzma.dll
-      EXTRA_COMP_PATH = $(OUTPUTDIR)/tmp/deploy/lzma/win32/obj
-      EXTRA_COMP_CMD_PATH = $(EXTRA_COMP_PATH)/lzma.exe
-      EXTRA_COMP_LIB_PATH = $(EXTRA_COMP_PATH)/$(EXTRA_COMP_LIB_NAME)
-    endif
-  endif
-endif
--- a/jdk/make/jpda/back/Makefile	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/make/jpda/back/Makefile	Wed Jul 05 18:57:52 2017 +0200
@@ -31,6 +31,8 @@
 LIBRARY = jdwp
 PRODUCT = jpda
 
+LIBRARY_SUPPORTS_FULL_DEBUG_SYMBOLS=1
+
 FILES_m = mapfile-vers
 
 include $(BUILDDIR)/common/Defs.gmk
--- a/jdk/make/sun/awt/FILES_c_unix.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/make/sun/awt/FILES_c_unix.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -171,3 +171,13 @@
         GLXSurfaceData.c \
         AccelGlyphCache.c \
 	CUPSfuncs.c
+
+ifeq ($(PLATFORM), macosx)
+FILES_NO_MOTIF_objc = \
+		AWTFont.m \
+		AWTStrike.m \
+		CCharToGlyphMapper.m \
+		CGGlyphImages.m \
+		CGGlyphOutlines.m \
+		CoreTextSupport.m
+endif # PLATFORM
--- a/jdk/make/sun/awt/FILES_export_unix.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/make/sun/awt/FILES_export_unix.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -187,3 +187,14 @@
 	java/awt/dnd/DnDConstants.java \
 	sun/awt/CausedFocusEvent.java
 
+ifeq ($(PLATFORM), macosx)
+ifeq ($(HEADLESS), true)
+FILES_export += \
+	sun/awt/SunHints.java \
+	sun/font/CCharToGlyphMapper.java \
+	sun/font/CFont.java \
+	sun/font/CFontManager.java \
+	sun/font/CStrike.java \
+	sun/font/CStrikeDisposer.java
+endif # HEADLESS
+endif # PLATFORM
--- a/jdk/make/sun/awt/mawt.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/make/sun/awt/mawt.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -43,6 +43,10 @@
 # compiled based on the motif version.
 FILES_c = $(FILES_NO_MOTIF_c)
 
+ifeq ($(PLATFORM), macosx)
+FILES_objc = $(FILES_NO_MOTIF_objc)
+endif # PLATFORM
+
 ifeq ($(PLATFORM), solaris)
   ifneq ($(ARCH), amd64)
     FILES_reorder += reorder-$(ARCH)
@@ -97,6 +101,10 @@
 vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)/image
 vpath %.c   $(PLATFORM_SRC)/native/$(PKGDIR)/robot_child
 
+ifeq ($(PLATFORM), macosx)
+vpath %.m   $(call NativeSrcDirList,,native/sun/font)
+endif # PLATFORM
+
 #
 # Libraries to link in.
 #
@@ -192,13 +200,21 @@
         $(EVENT_MODEL)
 
 ifeq ($(PLATFORM), macosx)
-CPPFLAGS += -I$(CUPS_HEADERS_PATH)
+CPPFLAGS += -I$(CUPS_HEADERS_PATH) \
+			$(call NativeSrcDirList,-I,native/sun/awt) \
+			$(call NativeSrcDirList,-I,native/sun/font)
 
 ifndef HEADLESS
 CPPFLAGS += -I$(MOTIF_DIR)/include \
             -I$(OPENWIN_HOME)/include 
 LDFLAGS  += -L$(MOTIF_LIB) -L$(OPENWIN_LIB)
-
+else
+LDFLAGS  += -framework Accelerate \
+			-framework ApplicationServices \
+			-framework Cocoa \
+			-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+			-framework JavaNativeFoundation \
+			-framework JavaRuntimeSupport
 endif # !HEADLESS
 endif # PLATFORM
 
--- a/jdk/makefiles/CompileLaunchers.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/makefiles/CompileLaunchers.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -95,6 +95,9 @@
         $1_PLIST_FILE:=Info-cmdline.plist
         ifneq ($(11),)
             $1_PLIST_FILE:=$(11)
+            ifneq ($$(findstring privileged,$$($1_PLIST_FILE)),)
+                $1_CODESIGN:=true
+            endif
         endif
 
         $1_LDFLAGS += -Wl,-all_load $(JDK_OUTPUTDIR)/objs/libjli_static.a \
@@ -174,7 +177,8 @@
 		  -D "JDK_INTERNAL_NAME=$1" \
 		  -D "JDK_FTYPE=0x1L" \
 		  $7,\
-	MANIFEST:=$(JDK_TOPDIR)/src/windows/resource/java.manifest)
+	MANIFEST:=$(JDK_TOPDIR)/src/windows/resource/java.manifest,\
+	CODESIGN:=$$($1_CODESIGN))
 
     BUILD_LAUNCHERS += $$(BUILD_LAUNCHER_$1)
 
--- a/jdk/makefiles/CompileNativeLibraries.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/makefiles/CompileNativeLibraries.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -1143,7 +1143,7 @@
 			  -D "JDK_INTERNAL_NAME=jdwp" \
 			  -D "JDK_FTYPE=0x2L",\
 		OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libjdwp,\
-		DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES)))
+		DEBUG_SYMBOLS:=true))
 
 $(BUILD_LIBJDWP) : $(BUILD_LIBJAVA)
 
@@ -2314,6 +2314,10 @@
 			$(JDK_TOPDIR)/src/solaris/native/sun/java2d/opengl \
 			$(JDK_TOPDIR)/src/solaris/native/sun/java2d/x11
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_DIRS+=$(JDK_TOPDIR)/src/macosx/native/sun/font
+endif
+
 LIBAWT_HEADLESS_CFLAGS:=-DHEADLESS=true \
                           -DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
 			  $(CUPS_CFLAGS) \
@@ -2328,6 +2332,12 @@
 			  -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/jdga \
                           $(foreach dir,$(LIBAWT_HEADLESS_DIRS),-I$(dir))
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_CFLAGS+=\
+		-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+		-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
+endif
+
 LIBAWT_HEADLESS_FILES:=\
 	awt_Font.c \
 	HeadlessToolkit.c \
@@ -2356,6 +2366,16 @@
         AccelGlyphCache.c \
 	CUPSfuncs.c
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_FILES+=\
+		AWTFont.m \
+		AWTStrike.m \
+		CCharToGlyphMapper.m \
+		CGGlyphImages.m \
+		CGGlyphOutlines.m \
+		CoreTextSupport.m
+endif
+
 LIBAWT_HEADLESS_REORDER:=
 ifeq ($(OPENJDK_TARGET_OS), solaris)
 	ifneq ($(OPENJDK_TARGET_CPU), x86_64)
@@ -2382,7 +2402,13 @@
 		REORDER:=$(LIBAWT_HEADLESS_REORDER), \
 		LDFLAGS_SUFFIX_linux:=-ljvm -lawt -lm $(LIBDL) -ljava,\
 		LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc,\
-		LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava,\
+		LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava \
+				 -framework Accelerate \
+				 -framework ApplicationServices \
+				 -framework Cocoa \
+				 -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+				 -framework JavaNativeFoundation \
+				 -framework JavaRuntimeSupport,\
 		OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libawt_headless,\
 		DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES)))
 
--- a/jdk/makefiles/Images.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/makefiles/Images.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -50,8 +50,6 @@
 overlay-images: jre-overlay-image jdk-overlay-image
 
 
--include $(CUSTOM_MAKE_DIR)/Images.gmk
-
 
 # Processing license files from source area to image area
 # These will be modified to have the platform specific EOL chars.
@@ -774,3 +772,5 @@
 ################################################################################
 
 .PHONY: default images jre-image jdk-image
+
+-include $(CUSTOM_MAKE_DIR)/Images.gmk
--- a/jdk/src/macosx/bin/java_md_macosx.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/bin/java_md_macosx.c	Wed Jul 05 18:57:52 2017 +0200
@@ -44,7 +44,6 @@
 #include <Cocoa/Cocoa.h>
 #include <objc/objc-runtime.h>
 #include <objc/objc-auto.h>
-#include <dispatch/dispatch.h>
 
 #include <errno.h>
 #include <spawn.h>
@@ -1001,6 +1000,32 @@
     setenv(envVar, "1", 1);
 }
 
+/* This class is made for performSelectorOnMainThread when java main
+ * should be launched on main thread.
+ * We cannot use dispatch_sync here, because it blocks the main dispatch queue
+ * which is used inside Cocoa
+ */
+@interface JavaLaunchHelper : NSObject {
+    int _returnValue;
+}
+- (void) launchJava:(NSValue*)argsValue;
+- (int) getReturnValue;
+@end
+
+@implementation JavaLaunchHelper
+
+- (void) launchJava:(NSValue*)argsValue
+{
+    _returnValue = JavaMain([argsValue pointerValue]);
+}
+
+- (int) getReturnValue
+{
+    return _returnValue;
+}
+
+@end
+
 // MacOSX we may continue in the same thread
 int
 JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
@@ -1010,16 +1035,22 @@
         JLI_TraceLauncher("In same thread\n");
         // need to block this thread against the main thread
         // so signals get caught correctly
-        __block int rslt;
-        dispatch_sync(dispatch_get_main_queue(), ^(void) {
-            JavaMainArgs args;
-            args.argc = argc;
-            args.argv = argv;
-            args.mode = mode;
-            args.what = what;
-            args.ifn  = *ifn;
-            rslt = JavaMain((void*)&args);
-        });
+        JavaMainArgs args;
+        args.argc = argc;
+        args.argv = argv;
+        args.mode = mode;
+        args.what = what;
+        args.ifn  = *ifn;
+        int rslt;
+        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+        {
+            JavaLaunchHelper* launcher = [[[JavaLaunchHelper alloc] init] autorelease];
+            [launcher performSelectorOnMainThread:@selector(launchJava:)
+                                       withObject:[NSValue valueWithPointer:(void*)&args]
+                                    waitUntilDone:YES];
+            rslt = [launcher getReturnValue];
+        }
+        [pool drain];
         return rslt;
     } else {
         return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -38,7 +38,7 @@
     private long    fNativeDropTransfer = 0;
     private long    fNativeDataAvailable = 0;
     private Object  fNativeData    = null;
-    private boolean insideTarget = false;
+    private boolean insideTarget = true;
 
     Object awtLockAccess = new Object();
 
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -115,6 +115,8 @@
 
     static final int RESIZABLE = 1 << 9; // both a style bit and prop bit
     static final int NONACTIVATING = 1 << 24;
+    static final int IS_DIALOG = 1 << 25;
+    static final int IS_MODAL = 1 << 26;
 
     static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
 
@@ -374,6 +376,13 @@
             }
         }
 
+        if (isDialog) {
+            styleBits = SET(styleBits, IS_DIALOG, true);
+            if (((Dialog) target).isModal()) {
+                styleBits = SET(styleBits, IS_MODAL, true);
+            }
+        }
+
         peer.setTextured(IS(TEXTURED, styleBits));
 
         return styleBits;
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,6 +36,7 @@
 import javax.print.*;
 import javax.print.attribute.PrintRequestAttributeSet;
 import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.PageRanges;
 
 import sun.java2d.*;
 import sun.print.*;
@@ -173,6 +174,19 @@
         if (nsPrintInfo != null) {
             fNSPrintInfo = nsPrintInfo.getValue();
         }
+
+        PageRanges pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
+        if (isSupportedValue(pageRangesAttr, attributes)) {
+            SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
+            // If rangeSelect is not null, we are using AWT's print dialog that has
+            // All, Selection, and Range radio buttons
+            if (rangeSelect == null || rangeSelect == SunPageSelection.RANGE) {
+                int[][] range = pageRangesAttr.getMembers();
+                // setPageRange will set firstPage and lastPage as called in getFirstPage
+                // and getLastPage
+                setPageRange(range[0][0] - 1, range[0][1] - 1);
+            }
+        }
     }
 
     volatile boolean onEventThread;
@@ -225,7 +239,6 @@
          * the end of the document. Note that firstPage
          * and lastPage are 0 based page indices.
          */
-        int numPages = mDocument.getNumberOfPages();
 
         int firstPage = getFirstPage();
         int lastPage = getLastPage();
@@ -242,42 +255,53 @@
                 userCancelled = false;
             }
 
-            if (EventQueue.isDispatchThread()) {
-                // This is an AWT EventQueue, and this print rendering loop needs to block it.
-
-                onEventThread = true;
+            //Add support for PageRange
+            PageRanges pr = (attributes == null) ?  null
+                                                 : (PageRanges)attributes.get(PageRanges.class);
+            int[][] prMembers = (pr == null) ? new int[0][0] : pr.getMembers();
+            int loopi = 0;
+            do {
+                if (EventQueue.isDispatchThread()) {
+                    // This is an AWT EventQueue, and this print rendering loop needs to block it.
 
-                printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
-                    @Override
-                    public SecondaryLoop run() {
-                        return Toolkit.getDefaultToolkit()
-                                .getSystemEventQueue()
-                                .createSecondaryLoop();
-                    }
-                });
+                    onEventThread = true;
+
+                    printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
+                        @Override
+                        public SecondaryLoop run() {
+                            return Toolkit.getDefaultToolkit()
+                                    .getSystemEventQueue()
+                                    .createSecondaryLoop();
+                        }
+                    });
 
-                try {
-                    // Fire off the print rendering loop on the AppKit thread, and don't have
-                    //  it wait and block this thread.
-                    if (printLoop(false, firstPage, lastPage)) {
-                        // Start a secondary loop on EDT until printing operation is finished or cancelled
-                        printingLoop.enter();
+                    try {
+                        // Fire off the print rendering loop on the AppKit thread, and don't have
+                        //  it wait and block this thread.
+                        if (printLoop(false, firstPage, lastPage)) {
+                            // Start a secondary loop on EDT until printing operation is finished or cancelled
+                            printingLoop.enter();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
                     }
-                } catch (Exception e) {
-                    e.printStackTrace();
+              } else {
+                    // Fire off the print rendering loop on the AppKit, and block this thread
+                    //  until it is done.
+                    // But don't actually block... we need to come back here!
+                    onEventThread = false;
+
+                    try {
+                        printLoop(true, firstPage, lastPage);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
                 }
-            } else {
-                // Fire off the print rendering loop on the AppKit, and block this thread
-                //  until it is done.
-                // But don't actually block... we need to come back here!
-                onEventThread = false;
-
-                try {
-                    printLoop(true, firstPage, lastPage);
-                } catch (Exception e) {
-                    e.printStackTrace();
+                if (++loopi < prMembers.length) {
+                     firstPage = prMembers[loopi][0]-1;
+                     lastPage = prMembers[loopi][1] -1;
                 }
-            }
+            }  while (loopi < prMembers.length);
         } finally {
             synchronized (this) {
                 // NOTE: Native code shouldn't allow exceptions out while
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -536,8 +536,12 @@
 - (void) windowDidBecomeKey: (NSNotification *) notification {
 AWT_ASSERT_APPKIT_THREAD;
     [AWTToolkit eventCountPlusPlus];
-    [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
     AWTWindow *opposite = [AWTWindow lastKeyWindow];
+    if (!IS(self.styleBits, IS_DIALOG)) {
+        [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
+    } else if (IS(self.styleBits, IS_MODAL)) {
+        [CMenuBar activate:opposite->javaMenuBar modallyDisabled:YES];        
+    }
     [AWTWindow setLastKeyWindow:nil];
 
     [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
--- a/jdk/src/macosx/native/sun/font/AWTFont.m	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/macosx/native/sun/font/AWTFont.m	Wed Jul 05 18:57:52 2017 +0200
@@ -395,6 +395,7 @@
 
 #pragma mark --- Miscellaneous JNI ---
 
+#ifndef HEADLESS
 /*
  * Class:     sun_awt_PlatformFont
  * Method:    initIDs
@@ -416,3 +417,4 @@
     (JNIEnv *env, jclass cls)
 {
 }
+#endif
--- a/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -24,6 +24,9 @@
  */
 package com.sun.beans.finder;
 
+import java.lang.reflect.Executable;
+import java.lang.reflect.Modifier;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -37,7 +40,7 @@
  *
  * @author Sergey A. Malenkov
  */
-abstract class AbstractFinder<T> {
+abstract class AbstractFinder<T extends Executable> {
     private final Class<?>[] args;
 
     /**
@@ -53,27 +56,6 @@
     }
 
     /**
-     * Returns an array of {@code Class} objects
-     * that represent the formal parameter types of the method.
-     * Returns an empty array if the method takes no parameters.
-     *
-     * @param method  the object that represents method
-     * @return the parameter types of the method
-     */
-    protected abstract Class<?>[] getParameters(T method);
-
-    /**
-     * Returns {@code true} if and only if the method
-     * was declared to take a variable number of arguments.
-     *
-     * @param method  the object that represents method
-     * @return {@code true} if the method was declared
-     *         to take a variable number of arguments;
-     *         {@code false} otherwise
-     */
-    protected abstract boolean isVarArgs(T method);
-
-    /**
      * Checks validness of the method.
      * At least the valid method should be public.
      *
@@ -81,7 +63,9 @@
      * @return {@code true} if the method is valid,
      *         {@code false} otherwise
      */
-    protected abstract boolean isValid(T method);
+    protected boolean isValid(T method) {
+        return Modifier.isPublic(method.getModifiers());
+    }
 
     /**
      * Performs a search in the {@code methods} array.
@@ -109,7 +93,7 @@
 
         for (T newMethod : methods) {
             if (isValid(newMethod)) {
-                Class<?>[] newParams = getParameters(newMethod);
+                Class<?>[] newParams = newMethod.getParameterTypes();
                 if (newParams.length == this.args.length) {
                     PrimitiveWrapperMap.replacePrimitivesWithWrappers(newParams);
                     if (isAssignable(newParams, this.args)) {
@@ -120,6 +104,11 @@
                             boolean useNew = isAssignable(oldParams, newParams);
                             boolean useOld = isAssignable(newParams, oldParams);
 
+                            if (useOld && useNew) {
+                                // only if parameters are equal
+                                useNew = !newMethod.isSynthetic();
+                                useOld = !oldMethod.isSynthetic();
+                            }
                             if (useOld == useNew) {
                                 ambiguous = true;
                             } else if (useNew) {
@@ -130,7 +119,7 @@
                         }
                     }
                 }
-                if (isVarArgs(newMethod)) {
+                if (newMethod.isVarArgs()) {
                     int length = newParams.length - 1;
                     if (length <= this.args.length) {
                         Class<?>[] array = new Class<?>[this.args.length];
@@ -160,6 +149,11 @@
                         boolean useNew = isAssignable(oldParams, newParams);
                         boolean useOld = isAssignable(newParams, oldParams);
 
+                        if (useOld && useNew) {
+                            // only if parameters are equal
+                            useNew = !newMethod.isSynthetic();
+                            useOld = !oldMethod.isSynthetic();
+                        }
                         if (useOld == useNew) {
                             if (oldParams == map.get(oldMethod)) {
                                 ambiguous = true;
--- a/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -86,44 +86,4 @@
     private ConstructorFinder(Class<?>[] args) {
         super(args);
     }
-
-    /**
-     * Returns an array of {@code Class} objects
-     * that represent the formal parameter types of the constructor.
-     * Returns an empty array if the constructor takes no parameters.
-     *
-     * @param constructor  the object that represents constructor
-     * @return the parameter types of the constructor
-     */
-    @Override
-    protected Class<?>[] getParameters(Constructor<?> constructor) {
-        return constructor.getParameterTypes();
-    }
-
-    /**
-     * Returns {@code true} if and only if the constructor
-     * was declared to take a variable number of arguments.
-     *
-     * @param constructor  the object that represents constructor
-     * @return {@code true} if the constructor was declared
-     *         to take a variable number of arguments;
-     *         {@code false} otherwise
-     */
-    @Override
-    protected boolean isVarArgs(Constructor<?> constructor) {
-        return constructor.isVarArgs();
-    }
-
-    /**
-     * Checks validness of the constructor.
-     * The valid constructor should be public.
-     *
-     * @param constructor  the object that represents constructor
-     * @return {@code true} if the constructor is valid,
-     *         {@code false} otherwise
-     */
-    @Override
-    protected boolean isValid(Constructor<?> constructor) {
-        return Modifier.isPublic(constructor.getModifiers());
-    }
 }
--- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -196,33 +196,6 @@
     }
 
     /**
-     * Returns an array of {@code Class} objects
-     * that represent the formal parameter types of the method.
-     * Returns an empty array if the method takes no parameters.
-     *
-     * @param method  the object that represents method
-     * @return the parameter types of the method
-     */
-    @Override
-    protected Class<?>[] getParameters(Method method) {
-        return method.getParameterTypes();
-    }
-
-    /**
-     * Returns {@code true} if and only if the method
-     * was declared to take a variable number of arguments.
-     *
-     * @param method  the object that represents method
-     * @return {@code true} if the method was declared
-     *         to take a variable number of arguments;
-     *         {@code false} otherwise
-     */
-    @Override
-    protected boolean isVarArgs(Method method) {
-        return method.isVarArgs();
-    }
-
-    /**
      * Checks validness of the method.
      * The valid method should be public and
      * should have the specified name.
@@ -233,6 +206,6 @@
      */
     @Override
     protected boolean isValid(Method method) {
-        return !method.isBridge() && Modifier.isPublic(method.getModifiers()) && method.getName().equals(this.name);
+        return super.isValid(method) && method.getName().equals(this.name);
     }
 }
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -90,14 +90,16 @@
      * Constructs a new instance of Continuation.
      * @param top The name of the object that is to be resolved/operated upon.
      *          This becomes the Continuation's 'starter' and is used to
-     *          calculate the "resolved name" when filling  in a NamingException.
+     *          calculate the "resolved name" when filling in a NamingException.
      * @param environment The environment used by the caller. It is used
-     * when setting the "environment" of a CannotProceedException.
+     *          when setting the "environment" of a CannotProceedException.
      */
+    @SuppressWarnings("unchecked")  // For Hashtable clone: environment.clone()
     public Continuation(Name top, Hashtable<?,?> environment) {
         super();
         starter = top;
-        this.environment = environment;
+        this.environment = (Hashtable<?,?>)
+                ((environment == null) ? null : environment.clone());
     }
 
     /**
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -69,6 +69,7 @@
             }
     }
 
+    @SuppressWarnings("unchecked")      // For Hashtable clone: env.clone()
     public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
         AttrFilter filter, SearchControls cons,
         Context ctx, Hashtable<String, Object> env, boolean useFactory)
@@ -76,7 +77,8 @@
 
             this.candidates = candidates;
             this.filter = filter;
-            this.env = env;
+            this.env = (Hashtable<String, Object>)
+                    ((env == null) ? null : env.clone());
             this.context = ctx;
             this.useFactory = useFactory;
 
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -53,7 +53,8 @@
     @SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
     public GenericURLContext(Hashtable<?,?> env) {
         // context that is not tied to any specific URL
-        myEnv = (Hashtable<String, Object>)env;  // copied on write
+        myEnv =
+            (Hashtable<String, Object>)(env == null ? null : env.clone());
     }
 
     public void close() throws NamingException {
@@ -488,22 +489,19 @@
         return result;
     }
 
-    @SuppressWarnings("unchecked") // clone()
     public Object removeFromEnvironment(String propName)
         throws NamingException {
             if (myEnv == null) {
                 return null;
             }
-            myEnv = (Hashtable<String, Object>)myEnv.clone();
             return myEnv.remove(propName);
     }
 
-    @SuppressWarnings("unchecked") // clone()
     public Object addToEnvironment(String propName, Object propVal)
         throws NamingException {
-            myEnv = (myEnv == null)
-                    ? new Hashtable<String, Object>(11, 0.75f)
-                    : (Hashtable<String, Object>)myEnv.clone();
+            if (myEnv == null) {
+                myEnv = new Hashtable<String, Object>(11, 0.75f);
+            }
             return myEnv.put(propName, propVal);
     }
 
--- a/jdk/src/share/classes/java/io/FileInputStream.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/io/FileInputStream.java	Wed Jul 05 18:57:52 2017 +0200
@@ -240,13 +240,15 @@
      *
      * <p>The <code>skip</code> method may, for a variety of
      * reasons, end up skipping over some smaller number of bytes,
-     * possibly <code>0</code>. If <code>n</code> is negative, an
-     * <code>IOException</code> is thrown, even though the <code>skip</code>
-     * method of the {@link InputStream} superclass does nothing in this case.
-     * The actual number of bytes skipped is returned.
+     * possibly <code>0</code>. If <code>n</code> is negative, the method
+     * will try to skip backwards. In case the backing file does not support
+     * backward skip at its current position, an <code>IOException</code> is
+     * thrown. The actual number of bytes skipped is returned. If it skips
+     * forwards, it returns a positive value. If it skips backwards, it
+     * returns a negative value.
      *
-     * <p>This method may skip more bytes than are remaining in the backing
-     * file. This produces no exception and the number of bytes skipped
+     * <p>This method may skip more bytes than what are remaining in the
+     * backing file. This produces no exception and the number of bytes skipped
      * may include some number of bytes that were beyond the EOF of the
      * backing file. Attempting to read from the stream after skipping past
      * the end will result in -1 indicating the end of the file.
@@ -261,9 +263,10 @@
     /**
      * Returns an estimate of the number of remaining bytes that can be read (or
      * skipped over) from this input stream without blocking by the next
-     * invocation of a method for this input stream. The next invocation might be
-     * the same thread or another thread.  A single read or skip of this
-     * many bytes will not block, but may read or skip fewer bytes.
+     * invocation of a method for this input stream. Returns 0 when the file
+     * position is beyond EOF. The next invocation might be the same thread
+     * or another thread. A single read or skip of this many bytes will not
+     * block, but may read or skip fewer bytes.
      *
      * <p> In some cases, a non-blocking read (or skip) may appear to be
      * blocked when it is merely slow, for example when reading large
--- a/jdk/src/share/classes/java/io/InputStream.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/io/InputStream.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -193,8 +193,10 @@
      * up skipping over some smaller number of bytes, possibly <code>0</code>.
      * This may result from any of a number of conditions; reaching end of file
      * before <code>n</code> bytes have been skipped is only one possibility.
-     * The actual number of bytes skipped is returned.  If <code>n</code> is
-     * negative, no bytes are skipped.
+     * The actual number of bytes skipped is returned. If {@code n} is
+     * negative, the {@code skip} method for class {@code InputStream} always
+     * returns 0, and no bytes are skipped. Subclasses may handle the negative
+     * value differently.
      *
      * <p> The <code>skip</code> method of this class creates a
      * byte array and then repeatedly reads into it until <code>n</code> bytes
--- a/jdk/src/share/classes/java/lang/Class.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,6 +28,7 @@
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Member;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
@@ -115,9 +116,9 @@
  * @since   JDK1.0
  */
 public final class Class<T> implements java.io.Serializable,
-                              java.lang.reflect.GenericDeclaration,
-                              java.lang.reflect.Type,
-                              java.lang.reflect.AnnotatedElement {
+                              GenericDeclaration,
+                              Type,
+                              AnnotatedElement {
     private static final int ANNOTATION= 0x00002000;
     private static final int ENUM      = 0x00004000;
     private static final int SYNTHETIC = 0x00001000;
@@ -3182,7 +3183,7 @@
      */
     @Override
     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
-        return AnnotatedElement.super.isAnnotationPresent(annotationClass);
+        return GenericDeclaration.super.isAnnotationPresent(annotationClass);
     }
 
     /**
--- a/jdk/src/share/classes/java/lang/String.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/String.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1010,13 +1010,14 @@
     private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
         char v1[] = value;
         char v2[] = sb.getValue();
-        int i = 0;
-        int n = value.length;
-        while (n-- != 0) {
+        int n = v1.length;
+        if (n != sb.length()) {
+            return false;
+        }
+        for (int i = 0; i < n; i++) {
             if (v1[i] != v2[i]) {
                 return false;
             }
-            i++;
         }
         return true;
     }
@@ -1038,8 +1039,6 @@
      * @since  1.5
      */
     public boolean contentEquals(CharSequence cs) {
-        if (value.length != cs.length())
-            return false;
         // Argument is a StringBuffer, StringBuilder
         if (cs instanceof AbstractStringBuilder) {
             if (cs instanceof StringBuffer) {
@@ -1055,12 +1054,14 @@
             return true;
         // Argument is a generic CharSequence
         char v1[] = value;
-        int i = 0;
-        int n = value.length;
-        while (n-- != 0) {
-            if (v1[i] != cs.charAt(i))
+        int n = v1.length;
+        if (n != cs.length()) {
+            return false;
+        }
+        for (int i = 0; i < n; i++) {
+            if (v1[i] != cs.charAt(i)) {
                 return false;
-            i++;
+            }
         }
         return true;
     }
--- a/jdk/src/share/classes/java/lang/StringBuffer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -335,10 +335,8 @@
      * @since 1.5
      */
     @Override
-    public StringBuffer append(CharSequence s) {
-        // Note, synchronization achieved via invocations of other StringBuffer methods after
-        // narrowing of s to specific type
-        // Ditto for toStringCache clearing
+    public synchronized StringBuffer append(CharSequence s) {
+        toStringCache = null;
         super.append(s);
         return this;
     }
--- a/jdk/src/share/classes/java/lang/Thread.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java	Wed Jul 05 18:57:52 2017 +0200
@@ -145,10 +145,10 @@
         registerNatives();
     }
 
-    private char        name[];
-    private int         priority;
-    private Thread      threadQ;
-    private long        eetop;
+    private volatile char  name[];
+    private int            priority;
+    private Thread         threadQ;
+    private long           eetop;
 
     /* Whether or not to single_step this thread. */
     private boolean     single_step;
@@ -1135,7 +1135,7 @@
      * @see        #getName
      * @see        #checkAccess()
      */
-    public final void setName(String name) {
+    public final synchronized void setName(String name) {
         checkAccess();
         this.name = name.toCharArray();
         if (threadStatus != 0) {
@@ -1150,7 +1150,7 @@
      * @see     #setName(String)
      */
     public final String getName() {
-        return String.valueOf(name);
+        return new String(name, true);
     }
 
     /**
--- a/jdk/src/share/classes/java/lang/ref/Reference.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ref/Reference.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -138,8 +138,23 @@
                         pending = r.discovered;
                         r.discovered = null;
                     } else {
+                        // The waiting on the lock may cause an OOME because it may try to allocate
+                        // exception objects, so also catch OOME here to avoid silent exit of the
+                        // reference handler thread.
+                        //
+                        // Explicitly define the order of the two exceptions we catch here
+                        // when waiting for the lock.
+                        //
+                        // We do not want to try to potentially load the InterruptedException class
+                        // (which would be done if this was its first use, and InterruptedException
+                        // were checked first) in this situation.
+                        //
+                        // This may lead to the VM not ever trying to load the InterruptedException
+                        // class again.
                         try {
-                            lock.wait();
+                            try {
+                                lock.wait();
+                            } catch (OutOfMemoryError x) { }
                         } catch (InterruptedException x) { }
                         continue;
                     }
--- a/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -30,7 +30,7 @@
  *
  * @since 1.5
  */
-public interface GenericDeclaration {
+public interface GenericDeclaration extends AnnotatedElement {
     /**
      * Returns an array of {@code TypeVariable} objects that
      * represent the type variables declared by the generic
--- a/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Wed Jul 05 18:57:52 2017 +0200
@@ -34,6 +34,7 @@
 import java.nio.BufferUnderflowException;
 import java.lang.ref.WeakReference;
 import java.nio.charset.CoderMalfunctionError;                  // javadoc
+import java.util.Arrays;
 
 
 /**
@@ -244,7 +245,12 @@
      *          which is never <tt>null</tt> and is never empty
      */
     public final $replType$ replacement() {
+#if[decoder]
         return replacement;
+#end[decoder]
+#if[encoder]
+        return Arrays.copyOf(replacement, replacement.$replLength$);
+#end[encoder]
     }
 
     /**
@@ -280,12 +286,15 @@
             throw new IllegalArgumentException("Empty replacement");
         if (len > max$ItypesPerOtype$)
             throw new IllegalArgumentException("Replacement too long");
+#if[decoder]
+        this.replacement = newReplacement;
+#end[decoder]
 #if[encoder]
         if (!isLegalReplacement(newReplacement))
             throw new IllegalArgumentException("Illegal replacement");
+        this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
 #end[encoder]
-        this.replacement = newReplacement;
-        implReplaceWith(newReplacement);
+        implReplaceWith(this.replacement);
         return this;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/file/FileTreeIterator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * 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.  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.nio.file;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.nio.file.FileTreeWalker.Event;
+
+/**
+ * An {@code Iterator to iterate over the nodes of a file tree.
+ *
+ * <pre>{@code
+ *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
+ *         while (iterator.hasNext()) {
+ *             Event ev = iterator.next();
+ *             Path path = ev.file();
+ *             BasicFileAttributes attrs = ev.attributes();
+ *         }
+ *     }
+ * }</pre>
+ */
+
+class FileTreeIterator implements Iterator<Event>, Closeable {
+    private final FileTreeWalker walker;
+    private Event next;
+
+    /**
+     * Creates a new iterator to walk the file tree starting at the given file.
+     *
+     * @throws  IllegalArgumentException
+     *          if {@code maxDepth} is negative
+     * @throws  IOException
+     *          if an I/O errors occurs opening the starting file
+     * @throws  SecurityException
+     *          if the security manager denies access to the starting file
+     * @throws  NullPointerException
+     *          if {@code start} or {@code options} is {@ocde null} or
+     *          the options array contains a {@code null} element
+     */
+    FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
+        throws IOException
+    {
+        this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
+        this.next = walker.walk(start);
+        assert next.type() == FileTreeWalker.EventType.ENTRY ||
+               next.type() == FileTreeWalker.EventType.START_DIRECTORY;
+
+        // IOException if there a problem accessing the starting file
+        IOException ioe = next.ioeException();
+        if (ioe != null)
+            throw ioe;
+    }
+
+    private void fetchNextIfNeeded() {
+        if (next == null) {
+            FileTreeWalker.Event ev = walker.next();
+            while (ev != null) {
+                IOException ioe = ev.ioeException();
+                if (ioe != null)
+                    throw new UncheckedIOException(ioe);
+
+                // END_DIRECTORY events are ignored
+                if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
+                    next = ev;
+                    return;
+                }
+                ev = walker.next();
+            }
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (!walker.isOpen())
+            throw new IllegalStateException();
+        fetchNextIfNeeded();
+        return next != null;
+    }
+
+    @Override
+    public Event next() {
+        if (!walker.isOpen())
+            throw new IllegalStateException();
+        fetchNextIfNeeded();
+        if (next == null)
+            throw new NoSuchElementException();
+        Event result = next;
+        next = null;
+        return result;
+    }
+
+    @Override
+    public void close() {
+        walker.close();
+    }
+}
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,8 +29,8 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayDeque;
+import java.util.Collection;
 import java.util.Iterator;
-import java.util.Set;
 import sun.nio.fs.BasicFileAttributesHolder;
 
 /**
@@ -164,8 +164,17 @@
 
     /**
      * Creates a {@code FileTreeWalker}.
+     *
+     * @throws  IllegalArgumentException
+     *          if {@code maxDepth} is negative
+     * @throws  ClassCastException
+     *          if (@code options} contains an element that is not a
+     *          {@code FileVisitOption}
+     * @throws  NullPointerException
+     *          if {@code options} is {@ocde null} or the options
+     *          array contains a {@code null} element
      */
-    FileTreeWalker(Set<FileVisitOption> options, int maxDepth) {
+    FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
         boolean fl = false;
         for (FileVisitOption option: options) {
             // will throw NPE if options contains null
@@ -175,6 +184,9 @@
                     throw new AssertionError("Should not get here");
             }
         }
+        if (maxDepth < 0)
+            throw new IllegalArgumentException("'maxDepth' is negative");
+
         this.followLinks = fl;
         this.linkOptions = (fl) ? new LinkOption[0] :
             new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
--- a/jdk/src/share/classes/java/nio/file/Files.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,10 +25,13 @@
 
 package java.nio.file;
 
+import java.nio.ByteBuffer;
 import java.nio.file.attribute.*;
 import java.nio.file.spi.FileSystemProvider;
 import java.nio.file.spi.FileTypeDetector;
+import java.nio.channels.FileChannel;
 import java.nio.channels.SeekableByteChannel;
+import java.io.Closeable;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
@@ -38,7 +41,13 @@
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.util.*;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.DelegatingStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.nio.charset.Charset;
@@ -2587,9 +2596,6 @@
                                     FileVisitor<? super Path> visitor)
         throws IOException
     {
-        if (maxDepth < 0)
-            throw new IllegalArgumentException("'maxDepth' is negative");
-
         /**
          * Create a FileTreeWalker to walk the file tree, invoking the visitor
          * for each event.
@@ -2941,40 +2947,6 @@
     }
 
     /**
-     * Read all the bytes from an input stream. The {@code initialSize}
-     * parameter indicates the initial size of the byte[] to allocate.
-     */
-    private static byte[] read(InputStream source, int initialSize)
-        throws IOException
-    {
-        int capacity = initialSize;
-        byte[] buf = new byte[capacity];
-        int nread = 0;
-        int rem = buf.length;
-        int n;
-        // read to EOF which may read more or less than initialSize (eg: file
-        // is truncated while we are reading)
-        while ((n = source.read(buf, nread, rem)) > 0) {
-            nread += n;
-            rem -= n;
-            assert rem >= 0;
-            if (rem == 0) {
-                // need larger buffer
-                int newCapacity = capacity << 1;
-                if (newCapacity < 0) {
-                    if (capacity == Integer.MAX_VALUE)
-                        throw new OutOfMemoryError("Required array size too large");
-                    newCapacity = Integer.MAX_VALUE;
-                }
-                rem = newCapacity - capacity;
-                buf = Arrays.copyOf(buf, newCapacity);
-                capacity = newCapacity;
-            }
-        }
-        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
-    }
-
-    /**
      * Read all the bytes from a file. The method ensures that the file is
      * closed when all bytes have been read or an I/O error, or other runtime
      * exception, is thrown.
@@ -2999,12 +2971,22 @@
      *          method is invoked to check read access to the file.
      */
     public static byte[] readAllBytes(Path path) throws IOException {
-        long size = size(path);
-        if (size > (long)Integer.MAX_VALUE)
-            throw new OutOfMemoryError("Required array size too large");
+        try (FileChannel fc = FileChannel.open(path)) {
+            long size = fc.size();
+            if (size > (long)Integer.MAX_VALUE)
+                throw new OutOfMemoryError("Required array size too large");
 
-        try (InputStream in = newInputStream(path)) {
-             return read(in, (int)size);
+            byte[] arr = new byte[(int)size];
+            ByteBuffer bb = ByteBuffer.wrap(arr);
+            while (bb.hasRemaining()) {
+                if (fc.read(bb) < 0) {
+                    // truncated
+                    break;
+                }
+            }
+
+            int nread = bb.position();
+            return (nread == size) ? arr : Arrays.copyOf(arr, nread);
         }
     }
 
@@ -3177,4 +3159,336 @@
         }
         return path;
     }
+
+    // -- Stream APIs --
+
+    /**
+     * Implementation of CloseableStream
+     */
+    private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
+        implements CloseableStream<T>
+    {
+        private final Closeable closeable;
+
+        DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
+            super(delegate);
+            this.closeable = c;
+        }
+
+        public void close() {
+            try {
+                closeable.close();
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+    }
+
+    /**
+     * Return a lazily populated {@code CloseableStream}, the elements of
+     * which are the entries in the directory.  The listing is not recursive.
+     *
+     * <p> The elements of the stream are {@link Path} objects that are
+     * obtained as if by {@link Path#resolve(Path) resolving} the name of the
+     * directory entry against {@code dir}. Some file systems maintain special
+     * links to the directory itself and the directory's parent directory.
+     * Entries representing these links are not included.
+     *
+     * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
+     * not freeze the directory while iterating, so it may (or may not)
+     * reflect updates to the directory that occur after returning from this
+     * method.
+     *
+     * <p> When not using the try-with-resources construct, then the stream's
+     * {@link CloseableStream#close close} method should be invoked after the
+     * operation is completed so as to free any resources held for the open
+     * directory. Operating on a closed stream behaves as if the end of stream
+     * has been reached. Due to read-ahead, one or more elements may be
+     * returned after the stream has been closed.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after this method has returned, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   dir  The path to the directory
+     *
+     * @return  The {@code CloseableStream} describing the content of the
+     *          directory
+     *
+     * @throws  NotDirectoryException
+     *          if the file could not otherwise be opened because it is not
+     *          a directory <i>(optional specific exception)</i>
+     * @throws  IOException
+     *          if an I/O error occurs when opening the directory
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the directory.
+     *
+     * @see     #newDirectoryStream(Path)
+     * @since   1.8
+     */
+    public static CloseableStream<Path> list(Path dir) throws IOException {
+        DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
+        final Iterator<Path> delegate = ds.iterator();
+
+        // Re-wrap DirectoryIteratorException to UncheckedIOException
+        Iterator<Path> it = new Iterator<Path>() {
+            public boolean hasNext() {
+                try {
+                    return delegate.hasNext();
+                } catch (DirectoryIteratorException e) {
+                    throw new UncheckedIOException(e.getCause());
+                }
+            }
+            public Path next() {
+                try {
+                    return delegate.next();
+                } catch (DirectoryIteratorException e) {
+                    throw new UncheckedIOException(e.getCause());
+                }
+            }
+        };
+
+        return new DelegatingCloseableStream<>(ds,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
+                                                                     Spliterator.DISTINCT)));
+    }
+
+    /**
+     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Path} by walking the file tree rooted at a given starting file.  The
+     * file tree is traversed <em>depth-first</em>, the elements in the stream
+     * are {@link Path} objects that are obtained as if by {@link
+     * Path#resolve(Path) resolving} the relative path against {@code start}.
+     *
+     * <p> The {@code stream} walks the file tree as elements are consumed.
+     * The {@code CloseableStream} returned is guaranteed to have at least one
+     * element, the starting file itself. For each file visited, the stream
+     * attempts to read its {@link BasicFileAttributes}. If the file is a
+     * directory and can be opened successfully, entries in the directory, and
+     * their <em>descendants</em> will follow the directory in the stream as
+     * they are encountered. When all entries have been visited, then the
+     * directory is closed. The file tree walk then continues at the next
+     * <em>sibling</em> of the directory.
+     *
+     * <p> The stream is <i>weakly consistent</i>. It does not freeze the
+     * file tree while iterating, so it may (or may not) reflect updates to
+     * the file tree that occur after returned from this method.
+     *
+     * <p> By default, symbolic links are not automatically followed by this
+     * method. If the {@code options} parameter contains the {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
+     * followed. When following links, and the attributes of the target cannot
+     * be read, then this method attempts to get the {@code BasicFileAttributes}
+     * of the link.
+     *
+     * <p> If the {@code options} parameter contains the {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
+     * track of directories visited so that cycles can be detected. A cycle
+     * arises when there is an entry in a directory that is an ancestor of the
+     * directory. Cycle detection is done by recording the {@link
+     * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
+     * or if file keys are not available, by invoking the {@link #isSameFile
+     * isSameFile} method to test if a directory is the same file as an
+     * ancestor. When a cycle is detected it is treated as an I/O error with
+     * an instance of {@link FileSystemLoopException}.
+     *
+     * <p> The {@code maxDepth} parameter is the maximum number of levels of
+     * directories to visit. A value of {@code 0} means that only the starting
+     * file is visited, unless denied by the security manager. A value of
+     * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
+     * levels should be visited.
+     *
+     * <p> When a security manager is installed and it denies access to a file
+     * (or directory), then it is ignored and not included in the stream.
+     *
+     * <p> When not using the try-with-resources construct, then the stream's
+     * {@link CloseableStream#close close} method should be invoked after the
+     * operation is completed so as to free any resources held for the open
+     * directory. Operate the stream after it is closed will throw an
+     * {@link java.lang.IllegalStateException}.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after this method has returned, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   start
+     *          the starting file
+     * @param   maxDepth
+     *          the maximum number of directory levels to visit
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  IllegalArgumentException
+     *          if the {@code maxDepth} parameter is negative
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          if an I/O error is thrown when accessing the starting file.
+     * @since   1.8
+     */
+    public static CloseableStream<Path> walk(Path start, int maxDepth,
+                                             FileVisitOption... options)
+        throws IOException
+    {
+        FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+        return new DelegatingCloseableStream<>(iterator,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+                   .map(entry -> entry.file()));
+    }
+
+    /**
+     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Path} by walking the file tree rooted at a given starting file.  The
+     * file tree is traversed <em>depth-first</em>, the elements in the stream
+     * are {@link Path} objects that are obtained as if by {@link
+     * Path#resolve(Path) resolving} the relative path against {@code start}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * walk(start, Integer.MAX_VALUE, options)
+     * </pre></blockquote>
+     * In other words, it visits all levels of the file tree.
+     *
+     * @param   start
+     *          the starting file
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          if an I/O error is thrown when accessing the starting file.
+     *
+     * @see     #walk(Path, int, FileVisitOption...)
+     * @since   1.8
+     */
+    public static CloseableStream<Path> walk(Path start,
+                                             FileVisitOption... options)
+        throws IOException
+    {
+        return walk(start, Integer.MAX_VALUE, options);
+    }
+
+    /**
+     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Path} by searching for files in a file tree rooted at a given starting
+     * file.
+     *
+     * <p> This method walks the file tree in exactly the manner specified by
+     * the {@link #walk walk} method. For each file encountered, the given
+     * {@link BiPredicate} is invoked with its {@link Path} and {@link
+     * BasicFileAttributes}. The {@code Path} object is obtained as if by
+     * {@link Path#resolve(Path) resolving} the relative path against {@code
+     * start} and is only included in the returned {@link CloseableStream} if
+     * the {@code BiPredicate} returns true. Compare to calling {@link
+     * java.util.stream.Stream#filter filter} on the {@code Stream}
+     * returned by {@code walk} method, this method may be more efficient by
+     * avoiding redundant retrieval of the {@code BasicFileAttributes}.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after returned from this method, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   start
+     *          the starting file
+     * @param   maxDepth
+     *          the maximum number of directory levels to search
+     * @param   matcher
+     *          the function used to decide whether a file should be included
+     *          in the returned stream
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  IllegalArgumentException
+     *          if the {@code maxDepth} parameter is negative
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          if an I/O error is thrown when accessing the starting file.
+     *
+     * @see     #walk(Path, int, FileVisitOption...)
+     * @since   1.8
+     */
+    public static CloseableStream<Path> find(Path start,
+                                             int maxDepth,
+                                             BiPredicate<Path, BasicFileAttributes> matcher,
+                                             FileVisitOption... options)
+        throws IOException
+    {
+        FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+        return new DelegatingCloseableStream<>(iterator,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+                   .filter(entry -> matcher.test(entry.file(), entry.attributes()))
+                   .map(entry -> entry.file()));
+    }
+
+    /**
+     * Read all lines from a file as a {@code CloseableStream}.  Unlike {@link
+     * #readAllLines(Path, Charset) readAllLines}, this method does not read
+     * all lines into a {@code List}, but instead populates lazily as the stream
+     * is consumed.
+     *
+     * <p> Bytes from the file are decoded into characters using the specified
+     * charset and the same line terminators as specified by {@code
+     * readAllLines} are supported.
+     *
+     * <p> After this method returns, then any subsequent I/O exception that
+     * occurs while reading from the file or when a malformed or unmappable byte
+     * sequence is read, is wrapped in an {@link UncheckedIOException} that will
+     * be thrown form the
+     * {@link java.util.stream.Stream} method that caused the read to take
+     * place. In case an {@code IOException} is thrown when closing the file,
+     * it is also wrapped as an {@code UncheckedIOException}.
+     *
+     * <p> When not using the try-with-resources construct, then stream's
+     * {@link CloseableStream#close close} method should be invoked after
+     * operation is completed so as to free any resources held for the open
+     * file.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   cs
+     *          the charset to use for decoding
+     *
+     * @return  the lines from the file as a {@code CloseableStream}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs opening the file
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     *
+     * @see     #readAllLines(Path, Charset)
+     * @see     #newBufferedReader(Path, Charset)
+     * @see     java.io.BufferedReader#lines()
+     * @since   1.8
+     */
+    public static CloseableStream<String> lines(Path path, Charset cs)
+        throws IOException
+    {
+        BufferedReader br = Files.newBufferedReader(path, cs);
+        return new DelegatingCloseableStream<>(br, br.lines());
+    }
 }
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 18:57:52 2017 +0200
@@ -59,7 +59,7 @@
  * <code>DateFormatSymbols</code> is a public class for encapsulating
  * localizable date-time formatting data, such as the names of the
  * months, the names of the days of the week, and the time zone data.
- * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
+ * <code>SimpleDateFormat</code> uses
  * <code>DateFormatSymbols</code> to encapsulate this information.
  *
  * <p>
--- a/jdk/src/share/classes/java/util/Arrays.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/Arrays.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,7 +40,6 @@
 import java.util.stream.LongStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
-import static java.util.ArraysParallelSortHelpers.*;
 
 /**
  * This class contains various methods for manipulating arrays (such as
@@ -70,17 +69,62 @@
 public class Arrays {
 
     /**
-     * The minimum array length below which the sorting algorithm will not
-     * further partition the sorting task.
+     * The minimum array length below which a parallel sorting
+     * algorithm will not further partition the sorting task. Using
+     * smaller sizes typically results in memory contention across
+     * tasks that makes parallel speedups unlikely.
      */
-    // reasonable default so that we don't overcreate tasks
-    private static final int MIN_ARRAY_SORT_GRAN = 256;
+    private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
 
     // Suppresses default constructor, ensuring non-instantiability.
     private Arrays() {}
 
+    /**
+     * A comparator that implements the natural ordering of a group of
+     * mutually comparable elements. May be used when a supplied
+     * comparator is null. To simplify code-sharing within underlying
+     * implementations, the compare method only declares type Object
+     * for its second argument.
+     *
+     * Arrays class implementor's note: It is an empirical matter
+     * whether ComparableTimSort offers any performance benefit over
+     * TimSort used with this comparator.  If not, you are better off
+     * deleting or bypassing ComparableTimSort.  There is currently no
+     * empirical case for separating them for parallel sorting, so all
+     * public Object parallelSort methods use the same comparator
+     * based implementation.
+     */
+    static final class NaturalOrder implements Comparator<Object> {
+        @SuppressWarnings("unchecked")
+        public int compare(Object first, Object second) {
+            return ((Comparable<Object>)first).compareTo(second);
+        }
+        static final NaturalOrder INSTANCE = new NaturalOrder();
+    }
+
+    /**
+     * Checks that {@code fromIndex} and {@code toIndex} are in
+     * the range and throws an exception if they aren't.
+     */
+    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException(
+                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex < 0) {
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        }
+        if (toIndex > arrayLength) {
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+        }
+    }
+
     /*
-     * Sorting of primitive type arrays.
+     * Sorting methods. Note that all public "sort" methods take the
+     * same form: Performing argument checks if necessary, and then
+     * expanding arguments into those required for the internal
+     * implementation methods residing in other package-private
+     * classes (except for legacyMergeSort, included in this class).
      */
 
     /**
@@ -95,7 +139,7 @@
      * @param a the array to be sorted
      */
     public static void sort(int[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -120,7 +164,7 @@
      */
     public static void sort(int[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -135,7 +179,7 @@
      * @param a the array to be sorted
      */
     public static void sort(long[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -160,7 +204,7 @@
      */
     public static void sort(long[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -175,7 +219,7 @@
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -200,7 +244,7 @@
      */
     public static void sort(short[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -215,7 +259,7 @@
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -240,7 +284,7 @@
      */
     public static void sort(char[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -255,7 +299,7 @@
      * @param a the array to be sorted
      */
     public static void sort(byte[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1);
     }
 
     /**
@@ -303,7 +347,7 @@
      * @param a the array to be sorted
      */
     public static void sort(float[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -336,7 +380,7 @@
      */
     public static void sort(float[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -359,7 +403,7 @@
      * @param a the array to be sorted
      */
     public static void sort(double[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -392,7 +436,742 @@
      */
     public static void sort(double[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(byte[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1);
+        else
+            new ArraysParallelSortHelpers.FJByte.Sorter
+                (null, a, new byte[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        else
+            new ArraysParallelSortHelpers.FJByte.Sorter
+                (null, a, new byte[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(char[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJChar.Sorter
+                (null, a, new char[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+      @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(char[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJChar.Sorter
+                (null, a, new char[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(short[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJShort.Sorter
+                (null, a, new short[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(short[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJShort.Sorter
+                (null, a, new short[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(int[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJInt.Sorter
+                (null, a, new int[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(int[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJInt.Sorter
+                (null, a, new int[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(long[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJLong.Sorter
+                (null, a, new long[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(long[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJLong.Sorter
+                (null, a, new long[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(float[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJFloat.Sorter
+                (null, a, new float[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(float[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJFloat.Sorter
+                (null, a, new float[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(double[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJDouble.Sorter
+                (null, a, new double[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(double[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJDouble.Sorter
+                (null, a, new double[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array of objects into ascending order, according
+     * to the {@linkplain Comparable natural ordering} of its elements.
+     * All elements in the array must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in the array must be
+     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
+     * not throw a {@code ClassCastException} for any elements {@code e1}
+     * and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @throws ClassCastException if the array contains elements that are not
+     *         <i>mutually comparable</i> (for example, strings and integers)
+     * @throws IllegalArgumentException (optional) if the natural
+     *         ordering of the array elements is found to violate the
+     *         {@link Comparable} contract
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the specified array of objects into
+     * ascending order, according to the
+     * {@linkplain Comparable natural ordering} of its
+     * elements.  The range to be sorted extends from index
+     * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
+     * (If {@code fromIndex==toIndex}, the range to be sorted is empty.)  All
+     * elements in this range must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in this range must be <i>mutually
+     * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
+     * {@code ClassCastException} for any elements {@code e1} and
+     * {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element (inclusive) to be
+     *        sorted
+     * @param toIndex the index of the last element (exclusive) to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the natural ordering of the array elements is
+     *         found to violate the {@link Comparable} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> (for example, strings and
+     *         integers).
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Comparable<? super T>>
+    void parallelSort(T[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, fromIndex, toIndex, NaturalOrder.INSTANCE, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+    }
+
+    /**
+     * Sorts the specified array of objects according to the order induced by
+     * the specified comparator.  All elements in the array must be
+     * <i>mutually comparable</i> by the specified comparator (that is,
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param cmp the comparator to determine the order of the array.  A
+     *        {@code null} value indicates that the elements'
+     *        {@linkplain Comparable natural ordering} should be used.
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> using the specified comparator
+     * @throws IllegalArgumentException (optional) if the comparator is
+     *         found to violate the {@link java.util.Comparator} contract
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) {
+        if (cmp == null)
+            cmp = NaturalOrder.INSTANCE;
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, 0, n, cmp, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the specified array of objects according
+     * to the order induced by the specified comparator.  The range to be
+     * sorted extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
+     * range to be sorted is empty.)  All elements in the range must be
+     * <i>mutually comparable</i> by the specified comparator (that is,
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the range).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element (inclusive) to be
+     *        sorted
+     * @param toIndex the index of the last element (exclusive) to be sorted
+     * @param cmp the comparator to determine the order of the array.  A
+     *        {@code null} value indicates that the elements'
+     *        {@linkplain Comparable natural ordering} should be used.
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the natural ordering of the array elements is
+     *         found to violate the {@link Comparable} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> (for example, strings and
+     *         integers).
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
+                                        Comparator<? super T> cmp) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        if (cmp == null)
+            cmp = NaturalOrder.INSTANCE;
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
     }
 
     /*
@@ -412,39 +1191,6 @@
                     "java.util.Arrays.useLegacyMergeSort")).booleanValue();
     }
 
-    /*
-     * If this platform has an optimizing VM, check whether ComparableTimSort
-     * offers any performance benefit over TimSort in conjunction with a
-     * comparator that returns:
-     *    {@code ((Comparable)first).compareTo(Second)}.
-     * If not, you are better off deleting ComparableTimSort to
-     * eliminate the code duplication.  In other words, the commented
-     * out code below is the preferable implementation for sorting
-     * arrays of Comparables if it offers sufficient performance.
-     */
-
-//    /**
-//     * A comparator that implements the natural ordering of a group of
-//     * mutually comparable elements.  Using this comparator saves us
-//     * from duplicating most of the code in this file (one version for
-//     * Comparables, one for explicit Comparators).
-//     */
-//    private static final Comparator<Object> NATURAL_ORDER =
-//            new Comparator<Object>() {
-//        @SuppressWarnings("unchecked")
-//        public int compare(Object first, Object second) {
-//            return ((Comparable<Object>)first).compareTo(second);
-//        }
-//    };
-//
-//    public static void sort(Object[] a) {
-//        sort(a, 0, a.length, NATURAL_ORDER);
-//    }
-//
-//    public static void sort(Object[] a, int fromIndex, int toIndex) {
-//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
-//    }
-
     /**
      * Sorts the specified array of objects into ascending order, according
      * to the {@linkplain Comparable natural ordering} of its elements.
@@ -491,7 +1237,7 @@
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a);
         else
-            ComparableTimSort.sort(a);
+            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
     }
 
     /** To be removed in a future release. */
@@ -553,16 +1299,16 @@
      *         integers).
      */
     public static void sort(Object[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, fromIndex, toIndex);
         else
-            ComparableTimSort.sort(a, fromIndex, toIndex);
+            ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
     }
 
     /** To be removed in a future release. */
     private static void legacyMergeSort(Object[] a,
                                         int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
         Object[] aux = copyOfRange(a, fromIndex, toIndex);
         mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
     }
@@ -676,10 +1422,12 @@
      *         found to violate the {@link Comparator} contract
      */
     public static <T> void sort(T[] a, Comparator<? super T> c) {
+        if (c == null)
+            c = NaturalOrder.INSTANCE;
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, c);
         else
-            TimSort.sort(a, c);
+            TimSort.sort(a, 0, a.length, c, null, 0, 0);
     }
 
     /** To be removed in a future release. */
@@ -744,16 +1492,18 @@
      */
     public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                 Comparator<? super T> c) {
+        if (c == null)
+            c = NaturalOrder.INSTANCE;
+        rangeCheck(a.length, fromIndex, toIndex);
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, fromIndex, toIndex, c);
         else
-            TimSort.sort(a, fromIndex, toIndex, c);
+            TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
     }
 
     /** To be removed in a future release. */
     private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
                                             Comparator<? super T> c) {
-        rangeCheck(a.length, fromIndex, toIndex);
         T[] aux = copyOfRange(a, fromIndex, toIndex);
         if (c==null)
             mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
@@ -809,630 +1559,6 @@
         }
     }
 
-    /*
-     * Parallel sorting of primitive type arrays.
-     */
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(byte[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJByte.Sorter task = new FJByte.Sorter(a, new byte[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(char[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(char[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJChar.Sorter task = new FJChar.Sorter(a, new char[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(short[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(short[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJShort.Sorter task = new FJShort.Sorter(a, new short[a.length], fromIndex,
-                                                 nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(int[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(int[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJInt.Sorter task = new FJInt.Sorter(a, new int[a.length], fromIndex,
-                                             nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(long[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(long[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJLong.Sorter task = new FJLong.Sorter(a, new long[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(float[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(float[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJFloat.Sorter task = new FJFloat.Sorter(a, new float[a.length], fromIndex,
-                                                 nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(double[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(double[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJDouble.Sorter task = new FJDouble.Sorter(a, new double[a.length],
-                                                   fromIndex, nelements, gran);
-        task.invoke();
-    }
-
-    /*
-     * Parallel sorting of complex type arrays.
-     */
-
-    /**
-     * Sorts the specified array of objects into ascending order, according
-     * to the {@linkplain Comparable natural ordering} of its elements.
-     * All elements in the array must implement the {@link Comparable}
-     * interface.  Furthermore, all elements in the array must be
-     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
-     * not throw a {@code ClassCastException} for any elements {@code e1}
-     * and {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @throws ClassCastException if the array contains elements that are not
-     *         <i>mutually comparable</i> (for example, strings and integers)
-     * @throws IllegalArgumentException (optional) if the natural
-     *         ordering of the array elements is found to violate the
-     *         {@link Comparable} contract
-     *
-     * @since 1.8
-     */
-    public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the specified array of objects into
-     * ascending order, according to the
-     * {@linkplain Comparable natural ordering} of its
-     * elements.  The range to be sorted extends from index
-     * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
-     * (If {@code fromIndex==toIndex}, the range to be sorted is empty.)  All
-     * elements in this range must implement the {@link Comparable}
-     * interface.  Furthermore, all elements in this range must be <i>mutually
-     * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
-     * {@code ClassCastException} for any elements {@code e1} and
-     * {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element (inclusive) to be
-     *        sorted
-     * @param toIndex the index of the last element (exclusive) to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
-     *         (optional) if the natural ordering of the array elements is
-     *         found to violate the {@link Comparable} contract
-     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
-     *         {@code toIndex > a.length}
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> (for example, strings and
-     *         integers).
-     *
-     * @since 1.8
-     */
-    public static <T extends Comparable<? super T>>
-            void parallelSort(T[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        Class<?> tc = a.getClass().getComponentType();
-        @SuppressWarnings("unchecked")
-        T[] workspace = (T[])Array.newInstance(tc, a.length);
-        int gran = getSplitThreshold(nelements);
-        FJComparable.Sorter<T> task = new FJComparable.Sorter<>(a, workspace,
-                                                                fromIndex,
-                                                                nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array of objects according to the order induced by
-     * the specified comparator.  All elements in the array must be
-     * <i>mutually comparable</i> by the specified comparator (that is,
-     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
-     * for any elements {@code e1} and {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param c the comparator to determine the order of the array.  A
-     *        {@code null} value indicates that the elements'
-     *        {@linkplain Comparable natural ordering} should be used.
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> using the specified comparator
-     * @throws IllegalArgumentException (optional) if the comparator is
-     *         found to violate the {@link java.util.Comparator} contract
-     *
-     * @since 1.8
-     */
-    public static <T> void parallelSort(T[] a, Comparator<? super T> c) {
-        parallelSort(a, 0, a.length, c);
-    }
-
-    /**
-     * Sorts the specified range of the specified array of objects according
-     * to the order induced by the specified comparator.  The range to be
-     * sorted extends from index {@code fromIndex}, inclusive, to index
-     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
-     * range to be sorted is empty.)  All elements in the range must be
-     * <i>mutually comparable</i> by the specified comparator (that is,
-     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
-     * for any elements {@code e1} and {@code e2} in the range).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element (inclusive) to be
-     *        sorted
-     * @param toIndex the index of the last element (exclusive) to be sorted
-     * @param c the comparator to determine the order of the array.  A
-     *        {@code null} value indicates that the elements'
-     *        {@linkplain Comparable natural ordering} should be used.
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
-     *         (optional) if the natural ordering of the array elements is
-     *         found to violate the {@link Comparable} contract
-     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
-     *         {@code toIndex > a.length}
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> (for example, strings and
-     *         integers).
-     *
-     * @since 1.8
-     */
-    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
-                                        Comparator<? super T> c) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        Class<?> tc = a.getClass().getComponentType();
-        @SuppressWarnings("unchecked")
-        T[] workspace = (T[])Array.newInstance(tc, a.length);
-        int gran = getSplitThreshold(nelements);
-        FJComparator.Sorter<T> task = new FJComparator.Sorter<>(a, workspace,
-                                                                fromIndex,
-                                                                nelements, gran, c);
-        task.invoke();
-    }
-
-    /**
-     * Returns the size threshold for splitting into subtasks.
-     * By default, uses about 8 times as many tasks as threads
-     *
-     * @param n number of elements in the array to be processed
-     */
-    private static int getSplitThreshold(int n) {
-        int p = java.util.concurrent.ForkJoinPool.getCommonPoolParallelism();
-        int t = (p > 1) ? (1 + n / (p << 3)) : n;
-        return t < MIN_ARRAY_SORT_GRAN ? MIN_ARRAY_SORT_GRAN : t;
-    }
-
-    /**
-     * Checks that {@code fromIndex} and {@code toIndex} are in
-     * the range and throws an appropriate exception, if they aren't.
-     */
-    private static void rangeCheck(int length, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException(
-                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-        if (fromIndex < 0) {
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        }
-        if (toIndex > length) {
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-        }
-    }
-
     // Searching
 
     /**
--- a/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,6 +25,7 @@
 package java.util;
 
 import java.util.concurrent.RecursiveAction;
+import java.util.concurrent.CountedCompleter;
 
 /**
  * Helper utilities for the parallel sort methods in Arrays.parallelSort.
@@ -44,1180 +45,966 @@
  *             c. merge them together
  *         3. merge together the two halves.
  *
- * One reason for splitting in quarters is that this guarantees
- * that the final sort is in the main array, not the workspace
- * array.  (workspace and main swap roles on each subsort step.)
- * Leaf-level sorts use a Sequential quicksort, that in turn uses
- * insertion sort if under threshold.  Otherwise it uses median of
- * three to pick pivot, and loops rather than recurses along left
- * path.
- *
+ * One reason for splitting in quarters is that this guarantees that
+ * the final sort is in the main array, not the workspace array.
+ * (workspace and main swap roles on each subsort step.)  Leaf-level
+ * sorts use the associated sequential sort.
  *
- * Merger classes perform merging for Sorter. If big enough, splits Left
- * partition in half; finds the greatest point in Right partition
- * less than the beginning of the second half of Left via binary
- * search; and then, in parallel, merges left half of Left with
- * elements of Right up to split point, and merges right half of
- * Left with elements of R past split point. At leaf, it just
- * sequentially merges. This is all messy to code; sadly we need
- * distinct versions for each type.
+ * Merger classes perform merging for Sorter.  They are structured
+ * such that if the underlying sort is stable (as is true for
+ * TimSort), then so is the full sort.  If big enough, they split the
+ * largest of the two partitions in half, find the greatest point in
+ * smaller partition less than the beginning of the second half of
+ * larger via binary search; and then merge in parallel the two
+ * partitions.  In part to ensure tasks are triggered in
+ * stability-preserving order, the current CountedCompleter design
+ * requires some little tasks to serve as place holders for triggering
+ * completion tasks.  These classes (EmptyCompleter and Relay) don't
+ * need to keep track of the arrays, and are never themselves forked,
+ * so don't hold any task state.
  *
+ * The primitive class versions (FJByte... FJDouble) are
+ * identical to each other except for type declarations.
+ *
+ * The base sequential sorts rely on non-public versions of TimSort,
+ * ComparableTimSort, and DualPivotQuicksort sort methods that accept
+ * temp workspace array slices that we will have already allocated, so
+ * avoids redundant allocation. (Except for DualPivotQuicksort byte[]
+ * sort, that does not ever use a workspace array.)
  */
 /*package*/ class ArraysParallelSortHelpers {
 
-    // RFE: we should only need a working array as large as the subarray
-    //      to be sorted, but the logic assumes that indices in the two
-    //      arrays always line-up
+    /*
+     * Style note: The task classes have a lot of parameters, that are
+     * stored as task fields and copied to local variables and used in
+     * compute() methods, We pack these into as few lines as possible,
+     * and hoist consistency checks among them before main loops, to
+     * reduce distraction.
+     */
 
-    /** byte support class */
-    static final class FJByte {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 749471161188027634L;
-            final byte[] a;     // array to be sorted.
-            final byte[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
+    /**
+     * A placeholder task for Sorters, used for the lowest
+     * quartile task, that does not need to maintain array state.
+     */
+    static final class EmptyCompleter extends CountedCompleter<Void> {
+        static final long serialVersionUID = 2446542900576103244L;
+        EmptyCompleter(CountedCompleter<?> p) { super(p); }
+        public final void compute() { }
+    }
 
-            Sorter(byte[] a, byte[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
-            }
+    /**
+     * A trigger for secondary merge of two merges
+     */
+    static final class Relay extends CountedCompleter<Void> {
+        static final long serialVersionUID = 2446542900576103244L;
+        final CountedCompleter<?> task;
+        Relay(CountedCompleter<?> task) {
+            super(null, 1);
+            this.task = task;
+        }
+        public final void compute() { }
+        public final void onCompletion(CountedCompleter<?> t) {
+            task.compute();
+        }
+    }
 
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final byte[] a = this.a;
-                final byte[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,  g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l+h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h,
-                               l+h, n-h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   //skip rangeCheck
+    /** Object + Comparator support class */
+    static final class FJObject {
+        static final class Sorter<T> extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final T[] a, w;
+            final int base, size, wbase, gran;
+            Comparator<? super T> comparator;
+            Sorter(CountedCompleter<?> par, T[] a, T[] w, int base, int size,
+                   int wbase, int gran,
+                   Comparator<? super T> comparator) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
+                this.comparator = comparator;
+            }
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                Comparator<? super T> c = this.comparator;
+                T[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger<T>(s, w, a, wb, h,
+                                                       wb+h, n-h, b, g, c));
+                    Relay rc = new Relay(new Merger<T>(fc, a, w, b+h, q,
+                                                       b+u, n-u, wb+h, g, c));
+                    new Sorter<T>(rc, a, w, b+u, n-u, wb+u, g, c).fork();
+                    new Sorter<T>(rc, a, w, b+h, q, wb+h, g, c).fork();;
+                    Relay bc = new Relay(new Merger<T>(fc, a, w, b, q,
+                                                       b+q, h-q, wb, g, c));
+                    new Sorter<T>(bc, a, w, b+q, h-q, wb+q, g, c).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                TimSort.sort(a, b, b + n, c, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -9090258248781844470L;
-            final byte[] a;
-            final byte[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
+        static final class Merger<T> extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final T[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Comparator<? super T> comparator;
+            Merger(CountedCompleter<?> par, T[] a, T[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran,
+                   Comparator<? super T> comparator) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
+                this.comparator = comparator;
+            }
 
-            Merger(byte[] a, byte[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+            public final void compute() {
+                Comparator<? super T> c = this.comparator;
+                T[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0 ||
+                    c == null)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        T split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (c.compare(split, a[rm + rb]) <= 0)
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
+                    }
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        T split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (c.compare(split, a[lm + lb]) <= 0)
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger<T> m = new Merger<T>(this, a, w, lb + lh, ln - lh,
+                                                rb + rh, rn - rh,
+                                                k + lh + rh, g, c);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
+                }
+
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    T t, al, ar;
+                    if (c.compare((al = a[lb]), (ar = a[rb])) <= 0) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
+                    w[k++] = t;
+                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+
+                tryComplete();
             }
 
-            public void compute() {
-                final byte[] a = this.a;
-                final byte[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    byte split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+        }
+    } // FJObject
+
+    /** byte support class */
+    static final class FJByte {
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final byte[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, byte[] a, byte[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
+            }
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                byte[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
+                }
+                DualPivotQuicksort.sort(a, b, b + n - 1);
+                s.tryComplete();
+            }
+        }
+
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final byte[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, byte[] a, byte[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
+            }
+
+            public final void compute() {
+                byte[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        byte split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        byte split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    byte al = a[l];
-                    byte ar = a[r];
-                    byte t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    byte t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJByte
 
     /** char support class */
     static final class FJChar {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 8723376019074596641L;
-            final char[] a;     // array to be sorted.
-            final char[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(char[] a, char[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final char[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, char[] a, char[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final char[] a = this.a;
-                final char[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                char[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -1383975444621698926L;
-            final char[] a;
-            final char[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(char[] a, char[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final char[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, char[] a, char[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final char[] a = this.a;
-                final char[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    char split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                char[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        char split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        char split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    char al = a[l];
-                    char ar = a[r];
-                    char t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    char t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJChar
 
     /** short support class */
     static final class FJShort {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = -7886754793730583084L;
-            final short[] a;    // array to be sorted.
-            final short[] w;    // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(short[] a, short[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final short[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, short[] a, short[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final short[] a = this.a;
-                final short[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                short[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 3895749408536700048L;
-            final short[] a;
-            final short[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(short[] a, short[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final short[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, short[] a, short[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final short[] a = this.a;
-                final short[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    short split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                short[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        short split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        short split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    short al = a[l];
-                    short ar = a[r];
-                    short t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    short t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJShort
 
     /** int support class */
     static final class FJInt {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 4263311808957292729L;
-            final int[] a;     // array to be sorted.
-            final int[] w;     // workspace for merge
-            final int origin;  // origin of the part of array we deal with
-            final int n;       // Number of elements in (sub)arrays.
-            final int gran;    // split control
-
-            Sorter(int[] a, int[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final int[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, int[] a, int[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final int[] a = this.a;
-                final int[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                int[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -8727507284219982792L;
-            final int[] a;
-            final int[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(int[] a, int[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final int[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, int[] a, int[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final int[] a = this.a;
-                final int[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    int split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                int[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        int split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        int split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    int al = a[l];
-                    int ar = a[r];
-                    int t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    int t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJInt
 
     /** long support class */
     static final class FJLong {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 6553695007444392455L;
-            final long[] a;     // array to be sorted.
-            final long[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(long[] a, long[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final long[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, long[] a, long[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final long[] a = this.a;
-                final long[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                long[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 8843567516333283861L;
-            final long[] a;
-            final long[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(long[] a, long[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final long[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, long[] a, long[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final long[] a = this.a;
-                final long[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    long split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                long[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        long split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                      nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        long split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    long al = a[l];
-                    long ar = a[r];
-                    long t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    long t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJLong
 
     /** float support class */
     static final class FJFloat {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 1602600178202763377L;
-            final float[] a;    // array to be sorted.
-            final float[] w;    // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(float[] a, float[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final float[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, float[] a, float[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final float[] a = this.a;
-                final float[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                float[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 1518176433845397426L;
-            final float[] a;
-            final float[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(float[] a, float[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final float[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, float[] a, float[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final float[] a = this.a;
-                final float[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    float split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (Float.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                float[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        float split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        float split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    float al = a[l];
-                    float ar = a[r];
-                    float t;
-                    if (Float.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    float t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
                     }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJFloat
 
     /** double support class */
     static final class FJDouble {
-        static final class Sorter extends RecursiveAction {
+        static final class Sorter extends CountedCompleter<Void> {
             static final long serialVersionUID = 2446542900576103244L;
-            final double[] a;    // array to be sorted.
-            final double[] w;    // workspace for merge
-            final int origin;    // origin of the part of array we deal with
-            final int n;         // Number of elements in (sub)arrays.
-            final int gran;      // split control
-
-            Sorter(double[] a, double[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+            final double[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, double[] a, double[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final double[] a = this.a;
-                final double[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                double[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 8076242187166127592L;
-            final double[] a;
-            final double[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(double[] a, double[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final double[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, double[] a, double[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final double[] a = this.a;
-                final double[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    double split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (Double.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                double[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        double split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        double split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    double al = a[l];
-                    double ar = a[r];
-                    double t;
-                    if (Double.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    double t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
                     }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJDouble
 
-    /** Comparable support class */
-    static final class FJComparable {
-        static final class Sorter<T extends Comparable<? super T>> extends RecursiveAction {
-            static final long serialVersionUID = -1024003289463302522L;
-            final T[] a;
-            final T[] w;
-            final int origin;
-            final int n;
-            final int gran;
-
-            Sorter(T[] a, T[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
-            }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final T[] a = this.a;
-                final T[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1;
-                    int q = n >>> 2;
-                    int u = h + q;
-                    FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q,   g),
-                                                     new Sorter<>(a, w, l+q, h-q, g),
-                                                     new Merger<>(a, w, l,   q,
-                                                                  l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l+h, q,   g),
-                                                     new Sorter<>(a, w, l+u, n-u, g),
-                                                     new Merger<>(a, w, l+h, q,
-                                                                  l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger<>(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    Arrays.sort(a, l, l+n);
-                }
-            }
-        }
-
-        static final class Merger<T extends Comparable<? super T>> extends RecursiveAction {
-            static final long serialVersionUID = -3989771675258379302L;
-            final T[] a;
-            final T[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger<T> next;
-
-            Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger<T> next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
-            }
-
-            public void compute() {
-                final T[] a = this.a;
-                final T[] w = this.w;
-                Merger<T> rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    T split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split.compareTo(a[ro + mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
-                    }
-                    (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
-                                           nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
-                }
-
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    T al = a[l];
-                    T ar = a[r];
-                    T t;
-                    if (al.compareTo(ar) <= 0) {++l; t=al;} else {++r; t=ar; }
-                    w[k++] = t;
-                }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
-            }
-        }
-    } // FJComparable
-
-    /** Object + Comparator support class */
-    static final class FJComparator {
-        static final class Sorter<T> extends RecursiveAction {
-            static final long serialVersionUID = 9191600840025808581L;
-            final T[] a;       // array to be sorted.
-            final T[] w;       // workspace for merge
-            final int origin;  // origin of the part of array we deal with
-            final int n;       // Number of elements in (sub)arrays.
-            final int gran;    // split control
-            final Comparator<? super T> cmp; // Comparator to use
-
-            Sorter(T[] a, T[] w, int origin, int n, int gran, Comparator<? super T> cmp) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.cmp = cmp;
-                this.gran = gran;
-            }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final T[] a = this.a;
-                final T[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q,   g, cmp),
-                                                     new Sorter<>(a, w, l+q, h-q, g, cmp),
-                                                     new Merger<>(a, w, l,   q,
-                                                                  l+q, h-q, l, g, null, cmp));
-                    FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l + h, q,   g, cmp),
-                                                     new Sorter<>(a, w, l+u, n-u, g, cmp),
-                                                     new Merger<>(a, w, l+h, q,
-                                                                  l+u, n-u, l+h, g, null, cmp));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger<>(w, a, l, h, l + h, n - h, l, g, null, cmp).compute();
-                } else {
-                    Arrays.sort(a, l, l+n, cmp);
-                }
-            }
-        }
-
-        static final class Merger<T> extends RecursiveAction {
-            static final long serialVersionUID = -2679539040379156203L;
-            final T[] a;
-            final T[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger<T> next;
-            final Comparator<? super T> cmp;
-
-            Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger<T> next, Comparator<? super T> cmp) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
-                this.cmp = cmp;
-            }
-
-            public void compute() {
-                final T[] a = this.a;
-                final T[] w = this.w;
-                Merger<T> rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    T split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (cmp.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
-                    }
-                    (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
-                                           nright-rh, wo+lh+rh, gran, rights, cmp)).fork();
-                    nleft = lh;
-                    nright = rh;
-                }
-
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    T al = a[l];
-                    T ar = a[r];
-                    T t;
-                    if (cmp.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
-                    }
-                    w[k++] = t;
-                }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
-            }
-        }
-    } // FJComparator
-
-    /** Utility class to sort half a partitioned array */
-    private static final class FJSubSorter extends RecursiveAction {
-        static final long serialVersionUID = 9159249695527935512L;
-        final RecursiveAction left;
-        final RecursiveAction right;
-        final RecursiveAction merger;
-
-        FJSubSorter(RecursiveAction left, RecursiveAction right,
-                    RecursiveAction merger) {
-            this.left = left;
-            this.right = right;
-            this.merger = merger;
-        }
-
-        public void compute() {
-            right.fork();
-            left.invoke();
-            right.join();
-            merger.invoke();
-        }
-    }
 }
--- a/jdk/src/share/classes/java/util/ComparableTimSort.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/ComparableTimSort.java	Wed Jul 05 18:57:52 2017 +0200
@@ -86,9 +86,13 @@
     private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
 
     /**
-     * Temp storage for merges.
+     * Temp storage for merges. A workspace array may optionally be
+     * provided in constructor, and if so will be used as long as it
+     * is big enough.
      */
     private Object[] tmp;
+    private int tmpBase; // base of tmp array slice
+    private int tmpLen;  // length of tmp array slice
 
     /**
      * A stack of pending runs yet to be merged.  Run i starts at
@@ -108,15 +112,27 @@
      * Creates a TimSort instance to maintain the state of an ongoing sort.
      *
      * @param a the array to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private ComparableTimSort(Object[] a) {
+    private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
         this.a = a;
 
         // Allocate temp storage (which may be increased later if necessary)
         int len = a.length;
-        Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
-                                       len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
-        tmp = newArray;
+        int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+            len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+        if (work == null || workLen < tlen || workBase + tlen > work.length) {
+            tmp = new Object[tlen];
+            tmpBase = 0;
+            tmpLen = tlen;
+        }
+        else {
+            tmp = work;
+            tmpBase = workBase;
+            tmpLen = workLen;
+        }
 
         /*
          * Allocate runs-to-be-merged stack (which cannot be expanded).  The
@@ -136,17 +152,28 @@
     }
 
     /*
-     * The next two methods (which are package private and static) constitute
-     * the entire API of this class.  Each of these methods obeys the contract
-     * of the public method with the same signature in java.util.Arrays.
+     * The next method (package private and static) constitutes the
+     * entire API of this class.
      */
 
-    static void sort(Object[] a) {
-          sort(a, 0, a.length);
-    }
+    /**
+     * Sorts the given range, using the given workspace array slice
+     * for temp storage when possible. This method is designed to be
+     * invoked from public methods (in class Arrays) after performing
+     * any necessary array bounds checks and expanding parameters into
+     * the required forms.
+     *
+     * @param a the array to be sorted
+     * @param lo the index of the first element, inclusive, to be sorted
+     * @param hi the index of the last element, exclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
+     * @since 1.8
+     */
+    static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
+        assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
 
-    static void sort(Object[] a, int lo, int hi) {
-        rangeCheck(a.length, lo, hi);
         int nRemaining  = hi - lo;
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
@@ -163,7 +190,7 @@
          * extending short natural runs to minRun elements, and merging runs
          * to maintain stack invariant.
          */
-        ComparableTimSort ts = new ComparableTimSort(a);
+        ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
         int minRun = minRunLength(nRemaining);
         do {
             // Identify next run
@@ -619,11 +646,11 @@
         // Copy first run into temp array
         Object[] a = this.a; // For performance
         Object[] tmp = ensureCapacity(len1);
-        System.arraycopy(a, base1, tmp, 0, len1);
 
-        int cursor1 = 0;       // Indexes into tmp array
+        int cursor1 = tmpBase; // Indexes into tmp array
         int cursor2 = base2;   // Indexes int a
         int dest = base1;      // Indexes int a
+        System.arraycopy(a, base1, tmp, cursor1, len1);
 
         // Move first element of second run and deal with degenerate cases
         a[dest++] = a[cursor2++];
@@ -736,16 +763,17 @@
         // Copy second run into temp array
         Object[] a = this.a; // For performance
         Object[] tmp = ensureCapacity(len2);
-        System.arraycopy(a, base2, tmp, 0, len2);
+        int tmpBase = this.tmpBase;
+        System.arraycopy(a, base2, tmp, tmpBase, len2);
 
         int cursor1 = base1 + len1 - 1;  // Indexes into a
-        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
         int dest = base2 + len2 - 1;     // Indexes into a
 
         // Move last element of first run and deal with degenerate cases
         a[dest--] = a[cursor1--];
         if (--len1 == 0) {
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
             return;
         }
         if (len2 == 1) {
@@ -803,7 +831,7 @@
                 if (--len2 == 1)
                     break outer;
 
-                count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
+                count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
                 if (count2 != 0) {
                     dest -= count2;
                     cursor2 -= count2;
@@ -835,7 +863,7 @@
         } else {
             assert len1 == 0;
             assert len2 > 0;
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
         }
     }
 
@@ -848,7 +876,7 @@
      * @return tmp, whether or not it grew
      */
     private Object[]  ensureCapacity(int minCapacity) {
-        if (tmp.length < minCapacity) {
+        if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
             int newSize = minCapacity;
             newSize |= newSize >> 1;
@@ -863,30 +891,13 @@
             else
                 newSize = Math.min(newSize, a.length >>> 1);
 
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
             Object[] newArray = new Object[newSize];
             tmp = newArray;
+            tmpLen = newSize;
+            tmpBase = 0;
         }
         return tmp;
     }
 
-    /**
-     * Checks that fromIndex and toIndex are in range, and throws an
-     * appropriate exception if they aren't.
-     *
-     * @param arrayLen the length of the array
-     * @param fromIndex the index of the first element of the range
-     * @param toIndex the index after the last element of the range
-     * @throws IllegalArgumentException if fromIndex > toIndex
-     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-     *         or toIndex > arrayLen
-     */
-    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                       ") > toIndex(" + toIndex+")");
-        if (fromIndex < 0)
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        if (toIndex > arrayLen)
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-    }
 }
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Wed Jul 05 18:57:52 2017 +0200
@@ -32,6 +32,11 @@
  * quicksorts to degrade to quadratic performance, and is typically
  * faster than traditional (one-pivot) Quicksort implementations.
  *
+ * All exposed methods are package-private, designed to be invoked
+ * from public methods (in class Arrays) after performing any
+ * necessary array bounds checks and expanding parameters into the
+ * required forms.
+ *
  * @author Vladimir Yaroslavskiy
  * @author Jon Bentley
  * @author Josh Bloch
@@ -89,22 +94,18 @@
      */
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(int[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(int[] a, int left, int right) {
+    static void sort(int[] a, int left, int right,
+                     int[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -147,24 +148,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        int[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        int[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new int[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new int[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new int[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -172,21 +184,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             int[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -529,22 +542,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(long[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(long[] a, int left, int right) {
+    static void sort(long[] a, int left, int right,
+                     long[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -587,24 +596,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        long[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        long[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new long[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new long[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new long[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -612,21 +632,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             long[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -969,22 +990,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(short[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(short[] a, int left, int right) {
+    static void sort(short[] a, int left, int right,
+                     short[] work, int workBase, int workLen) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             int[] count = new int[NUM_SHORT_VALUES];
@@ -1002,7 +1019,7 @@
                 } while (--s > 0);
             }
         } else { // Use Dual-Pivot Quicksort on small arrays
-            doSort(a, left, right);
+            doSort(a, left, right, work, workBase, workLen);
         }
     }
 
@@ -1015,8 +1032,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(short[] a, int left, int right) {
+    private static void doSort(short[] a, int left, int right,
+                               short[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -1059,24 +1080,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        short[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        short[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new short[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new short[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new short[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -1084,21 +1116,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             short[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -1441,22 +1474,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(char[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(char[] a, int left, int right) {
+    static void sort(char[] a, int left, int right,
+                     char[] work, int workBase, int workLen) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             int[] count = new int[NUM_CHAR_VALUES];
@@ -1474,7 +1503,7 @@
                 } while (--s > 0);
             }
         } else { // Use Dual-Pivot Quicksort on small arrays
-            doSort(a, left, right);
+            doSort(a, left, right, work, workBase, workLen);
         }
     }
 
@@ -1487,8 +1516,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(char[] a, int left, int right) {
+    private static void doSort(char[] a, int left, int right,
+                               char[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -1531,24 +1564,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        char[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        char[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new char[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new char[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new char[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -1556,21 +1600,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             char[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -1916,22 +1961,13 @@
     private static final int NUM_BYTE_VALUES = 1 << 8;
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(byte[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
      * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(byte[] a, int left, int right) {
+    static void sort(byte[] a, int left, int right) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
             int[] count = new int[NUM_BYTE_VALUES];
@@ -1963,22 +1999,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(float[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(float[] a, int left, int right) {
+    static void sort(float[] a, int left, int right,
+                     float[] work, int workBase, int workLen) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
@@ -1997,7 +2029,7 @@
         /*
          * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, right);
+        doSort(a, left, right, work, workBase, workLen);
 
         /*
          * Phase 3: Place negative zeros before positive zeros.
@@ -2064,8 +2096,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(float[] a, int left, int right) {
+    private static void doSort(float[] a, int left, int right,
+                               float[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -2108,24 +2144,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        float[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        float[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new float[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new float[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new float[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -2133,21 +2180,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             float[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -2490,22 +2538,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(double[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(double[] a, int left, int right) {
+    static void sort(double[] a, int left, int right,
+                     double[] work, int workBase, int workLen) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
@@ -2524,7 +2568,7 @@
         /*
          * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, right);
+        doSort(a, left, right, work, workBase, workLen);
 
         /*
          * Phase 3: Place negative zeros before positive zeros.
@@ -2591,8 +2635,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(double[] a, int left, int right) {
+    private static void doSort(double[] a, int left, int right,
+                               double[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -2635,24 +2683,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        double[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        double[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new double[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new double[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new double[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -2660,21 +2719,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             double[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
--- a/jdk/src/share/classes/java/util/ListResourceBundle.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/ListResourceBundle.java	Wed Jul 05 18:57:52 2017 +0200
@@ -89,7 +89,7 @@
  *
  * public class MyResources_fr extends ListResourceBundle {
  *     protected Object[][] getContents() {
- *         return new Object[][] = {
+ *         return new Object[][] {
  *         // LOCALIZE THIS
  *             {"s1", "Le disque \"{1}\" {0}."},          // MessageFormat pattern
  *             {"s2", "1"},                               // location of {0} in pattern
--- a/jdk/src/share/classes/java/util/PropertyResourceBundle.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/PropertyResourceBundle.java	Wed Jul 05 18:57:52 2017 +0200
@@ -124,6 +124,8 @@
      *        to read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>stream</code> is null
+     * @throws IllegalArgumentException if {@code stream} contains a
+     *     malformed Unicode escape sequence.
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
     public PropertyResourceBundle (InputStream stream) throws IOException {
@@ -142,6 +144,8 @@
      *        read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>reader</code> is null
+     * @throws IllegalArgumentException if a malformed Unicode escape sequence appears
+     *     from {@code reader}.
      * @since 1.6
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
--- a/jdk/src/share/classes/java/util/Spliterator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -140,32 +140,32 @@
  * (in approximate order of decreasing desirability):
  * <ul>
  * <li>The source cannot be structurally interfered with.
- * </br>For example, an instance of
+ * <br>For example, an instance of
  * {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
  * A Spliterator created from the source reports a characteristic of
  * {@code IMMUTABLE}.</li>
  * <li>The source manages concurrent modifications.
- * </br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
+ * <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
  * is a concurrent source.  A Spliterator created from the source reports a
  * characteristic of {@code CONCURRENT}.</li>
  * <li>The mutable source provides a late-binding and fail-fast Spliterator.
- * </br>Late binding narrows the window during which interference can affect
+ * <br>Late binding narrows the window during which interference can affect
  * the calculation; fail-fast detects, on a best-effort basis, that structural
  * interference has occurred after traversal has commenced and throws
  * {@link ConcurrentModificationException}.  For example, {@link ArrayList},
  * and many other non-concurrent {@code Collection} classes in the JDK, provide
  * a late-binding, fail-fast spliterator.</li>
  * <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
- * </br>The source increases the likelihood of throwing
+ * <br>The source increases the likelihood of throwing
  * {@code ConcurrentModificationException} since the window of potential
  * interference is larger.</li>
  * <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
- * </br>The source risks arbitrary, non-deterministic behavior after traversal
+ * <br>The source risks arbitrary, non-deterministic behavior after traversal
  * has commenced since interference is not detected.
  * </li>
  * <li>The mutable source provides a non-late-binding and non-fail-fast
  * Spliterator.
- * </br>The source increases the risk of arbitrary, non-deterministic behavior
+ * <br>The source increases the risk of arbitrary, non-deterministic behavior
  * since non-detected interference may occur after construction.
  * </li>
  * </ul>
@@ -284,6 +284,8 @@
  * is set to {@code true} then diagnostic warnings are reported if boxing of
  * primitive values occur when operating on primitive subtype specializations.
  *
+ * @param <T> the type of elements returned by this Spliterator
+ *
  * @see Collection
  * @since 1.8
  */
@@ -333,9 +335,8 @@
      * Upon non-null return:
      * <ul>
      * <li>the value reported for {@code estimateSize()} before splitting,
-     * if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
-     * greater than {@code estimateSize()} for this and the returned
-     * Spliterator; and</li>
+     * must, after splitting, be greater than or equal to {@code estimateSize()}
+     * for this and the returned Spliterator; and</li>
      * <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
      * for this spliterator before splitting must be equal to the sum of
      * {@code estimateSize()} for this and the returned Spliterator after
@@ -566,13 +567,28 @@
     public static final int SUBSIZED = 0x00004000;
 
     /**
-     * A Spliterator specialized for {@code int} values.
+     * A Spliterator specialized for primitive values.
+     *
+     * @param <T> the type of elements returned by this Spliterator.  The
+     * type must be a wrapper type for a primitive type, such as {@code Integer}
+     * for the primitive {@code int} type.
+     * @param <T_CONS> the type of primitive consumer.  The type must be a
+     * primitive specialization of {@link java.util.function.Consumer} for
+     * {@code T}, such as {@link java.util.function.IntConsumer} for
+     * {@code Integer}.
+     * @param <T_SPLITR> the type of primitive Spliterator.  The type must be
+     * a primitive specialization of Spliterator for {@code T}, such as
+     * {@link Spliterator.OfInt} for {@code Integer}.
+     *
+     * @see Spliterator.OfInt
+     * @see Spliterator.OfLong
+     * @see Spliterator.OfDouble
      * @since 1.8
      */
-    public interface OfInt extends Spliterator<Integer> {
-
+    public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
+            extends Spliterator<T> {
         @Override
-        OfInt trySplit();
+        T_SPLITR trySplit();
 
         /**
          * If a remaining element exists, performs the given action on it,
@@ -586,7 +602,7 @@
          * upon entry to this method, else {@code true}.
          * @throws NullPointerException if the specified action is null
          */
-        boolean tryAdvance(IntConsumer action);
+        boolean tryAdvance(T_CONS action);
 
         /**
          * Performs the given action for each remaining element, sequentially in
@@ -603,6 +619,24 @@
          * @param action The action
          * @throws NullPointerException if the specified action is null
          */
+        default void forEachRemaining(T_CONS action) {
+            do { } while (tryAdvance(action));
+        }
+    }
+
+    /**
+     * A Spliterator specialized for {@code int} values.
+     * @since 1.8
+     */
+    public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
+
+        @Override
+        OfInt trySplit();
+
+        @Override
+        boolean tryAdvance(IntConsumer action);
+
+        @Override
         default void forEachRemaining(IntConsumer action) {
             do { } while (tryAdvance(action));
         }
@@ -658,40 +692,15 @@
      * A Spliterator specialized for {@code long} values.
      * @since 1.8
      */
-    public interface OfLong extends Spliterator<Long> {
+    public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
 
         @Override
         OfLong trySplit();
 
-        /**
-         * If a remaining element exists, performs the given action on it,
-         * returning {@code true}; else returns {@code false}.  If this
-         * Spliterator is {@link #ORDERED} the action is performed on the
-         * next element in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @param action The action
-         * @return {@code false} if no remaining elements existed
-         * upon entry to this method, else {@code true}.
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         boolean tryAdvance(LongConsumer action);
 
-        /**
-         * Performs the given action for each remaining element, sequentially in
-         * the current thread, until all elements have been processed or the
-         * action throws an exception.  If this Spliterator is {@link #ORDERED},
-         * actions are performed in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @implSpec
-         * The default implementation repeatedly invokes {@link #tryAdvance}
-         * until it returns {@code false}.  It should be overridden whenever
-         * possible.
-         *
-         * @param action The action
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         default void forEachRemaining(LongConsumer action) {
             do { } while (tryAdvance(action));
         }
@@ -747,40 +756,15 @@
      * A Spliterator specialized for {@code double} values.
      * @since 1.8
      */
-    public interface OfDouble extends Spliterator<Double> {
+    public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
 
         @Override
         OfDouble trySplit();
 
-        /**
-         * If a remaining element exists, performs the given action on it,
-         * returning {@code true}; else returns {@code false}.  If this
-         * Spliterator is {@link #ORDERED} the action is performed on the
-         * next element in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @param action The action
-         * @return {@code false} if no remaining elements existed
-         * upon entry to this method, else {@code true}.
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         boolean tryAdvance(DoubleConsumer action);
 
-        /**
-         * Performs the given action for each remaining element, sequentially in
-         * the current thread, until all elements have been processed or the
-         * action throws an exception.  If this Spliterator is {@link #ORDERED},
-         * actions are performed in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @implSpec
-         * The default implementation repeatedly invokes {@link #tryAdvance}
-         * until it returns {@code false}.  It should be overridden whenever
-         * possible.
-         *
-         * @param action The action
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         default void forEachRemaining(DoubleConsumer action) {
             do { } while (tryAdvance(action));
         }
--- a/jdk/src/share/classes/java/util/TimSort.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/TimSort.java	Wed Jul 05 18:57:52 2017 +0200
@@ -111,9 +111,13 @@
     private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
 
     /**
-     * Temp storage for merges.
+     * Temp storage for merges. A workspace array may optionally be
+     * provided in constructor, and if so will be used as long as it
+     * is big enough.
      */
-    private T[] tmp; // Actual runtime type will be Object[], regardless of T
+    private T[] tmp;
+    private int tmpBase; // base of tmp array slice
+    private int tmpLen;  // length of tmp array slice
 
     /**
      * A stack of pending runs yet to be merged.  Run i starts at
@@ -134,17 +138,31 @@
      *
      * @param a the array to be sorted
      * @param c the comparator to determine the order of the sort
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private TimSort(T[] a, Comparator<? super T> c) {
+    private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
         this.a = a;
         this.c = c;
 
         // Allocate temp storage (which may be increased later if necessary)
         int len = a.length;
-        @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
-        T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
-                                        len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
-        tmp = newArray;
+        int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+            len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+        if (work == null || workLen < tlen || workBase + tlen > work.length) {
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+            T[] newArray = (T[])java.lang.reflect.Array.newInstance
+                (a.getClass().getComponentType(), tlen);
+            tmp = newArray;
+            tmpBase = 0;
+            tmpLen = tlen;
+        }
+        else {
+            tmp = work;
+            tmpBase = workBase;
+            tmpLen = workLen;
+        }
 
         /*
          * Allocate runs-to-be-merged stack (which cannot be expanded).  The
@@ -164,22 +182,30 @@
     }
 
     /*
-     * The next two methods (which are package private and static) constitute
-     * the entire API of this class.  Each of these methods obeys the contract
-     * of the public method with the same signature in java.util.Arrays.
+     * The next method (package private and static) constitutes the
+     * entire API of this class.
      */
 
-    static <T> void sort(T[] a, Comparator<? super T> c) {
-        sort(a, 0, a.length, c);
-    }
+    /**
+     * Sorts the given range, using the given workspace array slice
+     * for temp storage when possible. This method is designed to be
+     * invoked from public methods (in class Arrays) after performing
+     * any necessary array bounds checks and expanding parameters into
+     * the required forms.
+     *
+     * @param a the array to be sorted
+     * @param lo the index of the first element, inclusive, to be sorted
+     * @param hi the index of the last element, exclusive, to be sorted
+     * @param c the comparator to use
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
+     * @since 1.8
+     */
+    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
+                         T[] work, int workBase, int workLen) {
+        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
 
-    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
-        if (c == null) {
-            Arrays.sort(a, lo, hi);
-            return;
-        }
-
-        rangeCheck(a.length, lo, hi);
         int nRemaining  = hi - lo;
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
@@ -196,7 +222,7 @@
          * extending short natural runs to minRun elements, and merging runs
          * to maintain stack invariant.
          */
-        TimSort<T> ts = new TimSort<>(a, c);
+        TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
         int minRun = minRunLength(nRemaining);
         do {
             // Identify next run
@@ -653,11 +679,10 @@
         // Copy first run into temp array
         T[] a = this.a; // For performance
         T[] tmp = ensureCapacity(len1);
-        System.arraycopy(a, base1, tmp, 0, len1);
-
-        int cursor1 = 0;       // Indexes into tmp array
+        int cursor1 = tmpBase; // Indexes into tmp array
         int cursor2 = base2;   // Indexes int a
         int dest = base1;      // Indexes int a
+        System.arraycopy(a, base1, tmp, cursor1, len1);
 
         // Move first element of second run and deal with degenerate cases
         a[dest++] = a[cursor2++];
@@ -770,16 +795,17 @@
         // Copy second run into temp array
         T[] a = this.a; // For performance
         T[] tmp = ensureCapacity(len2);
-        System.arraycopy(a, base2, tmp, 0, len2);
+        int tmpBase = this.tmpBase;
+        System.arraycopy(a, base2, tmp, tmpBase, len2);
 
         int cursor1 = base1 + len1 - 1;  // Indexes into a
-        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
         int dest = base2 + len2 - 1;     // Indexes into a
 
         // Move last element of first run and deal with degenerate cases
         a[dest--] = a[cursor1--];
         if (--len1 == 0) {
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
             return;
         }
         if (len2 == 1) {
@@ -838,7 +864,7 @@
                 if (--len2 == 1)
                     break outer;
 
-                count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
+                count2 = len2 - gallopLeft(a[cursor1], tmp, tmpBase, len2, len2 - 1, c);
                 if (count2 != 0) {
                     dest -= count2;
                     cursor2 -= count2;
@@ -870,7 +896,7 @@
         } else {
             assert len1 == 0;
             assert len2 > 0;
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
         }
     }
 
@@ -883,7 +909,7 @@
      * @return tmp, whether or not it grew
      */
     private T[] ensureCapacity(int minCapacity) {
-        if (tmp.length < minCapacity) {
+        if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
             int newSize = minCapacity;
             newSize |= newSize >> 1;
@@ -899,30 +925,12 @@
                 newSize = Math.min(newSize, a.length >>> 1);
 
             @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
-            T[] newArray = (T[]) new Object[newSize];
+            T[] newArray = (T[])java.lang.reflect.Array.newInstance
+                (a.getClass().getComponentType(), newSize);
             tmp = newArray;
+            tmpLen = newSize;
+            tmpBase = 0;
         }
         return tmp;
     }
-
-    /**
-     * Checks that fromIndex and toIndex are in range, and throws an
-     * appropriate exception if they aren't.
-     *
-     * @param arrayLen the length of the array
-     * @param fromIndex the index of the first element of the range
-     * @param toIndex the index after the last element of the range
-     * @throws IllegalArgumentException if fromIndex > toIndex
-     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-     *         or toIndex > arrayLen
-     */
-    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                       ") > toIndex(" + toIndex+")");
-        if (fromIndex < 0)
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        if (toIndex > arrayLen)
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-    }
 }
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 05 18:57:52 2017 +0200
@@ -44,19 +44,19 @@
  * adjustable expected concurrency for updates. This class obeys the
  * same functional specification as {@link java.util.Hashtable}, and
  * includes versions of methods corresponding to each method of
- * <tt>Hashtable</tt>. However, even though all operations are
+ * {@code Hashtable}. However, even though all operations are
  * thread-safe, retrieval operations do <em>not</em> entail locking,
  * and there is <em>not</em> any support for locking the entire table
  * in a way that prevents all access.  This class is fully
- * interoperable with <tt>Hashtable</tt> in programs that rely on its
+ * interoperable with {@code Hashtable} in programs that rely on its
  * thread safety but not on its synchronization details.
  *
- * <p> Retrieval operations (including <tt>get</tt>) generally do not
+ * <p> Retrieval operations (including {@code get}) generally do not
  * block, so may overlap with update operations (including
- * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
+ * {@code put} and {@code remove}). Retrievals reflect the results
  * of the most recently <em>completed</em> update operations holding
- * upon their onset.  For aggregate operations such as <tt>putAll</tt>
- * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
+ * upon their onset.  For aggregate operations such as {@code putAll}
+ * and {@code clear}, concurrent retrievals may reflect insertion or
  * removal of only some entries.  Similarly, Iterators and
  * Enumerations return elements reflecting the state of the hash table
  * at some point at or since the creation of the iterator/enumeration.
@@ -64,8 +64,8 @@
  * However, iterators are designed to be used by only one thread at a time.
  *
  * <p> The allowed concurrency among update operations is guided by
- * the optional <tt>concurrencyLevel</tt> constructor argument
- * (default <tt>16</tt>), which is used as a hint for internal sizing.  The
+ * the optional {@code concurrencyLevel} constructor argument
+ * (default {@code 16}), which is used as a hint for internal sizing.  The
  * table is internally partitioned to try to permit the indicated
  * number of concurrent updates without contention. Because placement
  * in hash tables is essentially random, the actual concurrency will
@@ -85,8 +85,8 @@
  * <em>optional</em> methods of the {@link Map} and {@link Iterator}
  * interfaces.
  *
- * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
- * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ * <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow {@code null} to be used as a key or value.
  *
  * <p>This class is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -353,8 +353,8 @@
 
         /**
          * The table is rehashed when its size exceeds this threshold.
-         * (The value of this field is always <tt>(int)(capacity *
-         * loadFactor)</tt>.)
+         * (The value of this field is always {@code (int)(capacity *
+         * loadFactor)}.)
          */
         transient int threshold;
 
@@ -829,9 +829,9 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains no key-value mappings.
+     * Returns {@code true} if this map contains no key-value mappings.
      *
-     * @return <tt>true</tt> if this map contains no key-value mappings
+     * @return {@code true} if this map contains no key-value mappings
      */
     public boolean isEmpty() {
         /*
@@ -870,8 +870,8 @@
 
     /**
      * Returns the number of key-value mappings in this map.  If the
-     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
-     * <tt>Integer.MAX_VALUE</tt>.
+     * map contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
      *
      * @return the number of key-value mappings in this map
      */
@@ -948,10 +948,10 @@
     /**
      * Tests if the specified object is a key in this table.
      *
-     * @param  key   possible key
-     * @return <tt>true</tt> if and only if the specified object
+     * @param  key possible key
+     * @return {@code true} if and only if the specified object
      *         is a key in this table, as determined by the
-     *         <tt>equals</tt> method; <tt>false</tt> otherwise.
+     *         {@code equals} method; {@code false} otherwise
      * @throws NullPointerException if the specified key is null
      */
     @SuppressWarnings("unchecked")
@@ -974,13 +974,12 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map maps one or more keys to the
-     * specified value. Note: This method requires a full internal
-     * traversal of the hash table, and so is much slower than
-     * method <tt>containsKey</tt>.
+     * Returns {@code true} if this map maps one or more keys to the
+     * specified value. Note: This method requires a full traversal
+     * of the map, and so is much slower than method {@code containsKey}.
      *
      * @param value value whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map maps one or more keys to the
+     * @return {@code true} if this map maps one or more keys to the
      *         specified value
      * @throws NullPointerException if the specified value is null
      */
@@ -1033,16 +1032,16 @@
     /**
      * Legacy method testing if some key maps into the specified value
      * in this table.  This method is identical in functionality to
-     * {@link #containsValue}, and exists solely to ensure
+     * {@link #containsValue(Object)}, and exists solely to ensure
      * full compatibility with class {@link java.util.Hashtable},
      * which supported this method prior to introduction of the
      * Java Collections framework.
      *
      * @param  value a value to search for
-     * @return <tt>true</tt> if and only if some key maps to the
-     *         <tt>value</tt> argument in this table as
-     *         determined by the <tt>equals</tt> method;
-     *         <tt>false</tt> otherwise
+     * @return {@code true} if and only if some key maps to the
+     *         {@code value} argument in this table as
+     *         determined by the {@code equals} method;
+     *         {@code false} otherwise
      * @throws NullPointerException if the specified value is null
      */
     public boolean contains(Object value) {
@@ -1053,13 +1052,13 @@
      * Maps the specified key to the specified value in this table.
      * Neither the key nor the value can be null.
      *
-     * <p> The value can be retrieved by calling the <tt>get</tt> method
+     * <p>The value can be retrieved by calling the {@code get} method
      * with a key that is equal to the original key.
      *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
-     * @return the previous value associated with <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}
      * @throws NullPointerException if the specified key or value is null
      */
     @SuppressWarnings("unchecked")
@@ -1079,7 +1078,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws NullPointerException if the specified key or value is null
      */
     @SuppressWarnings("unchecked")
@@ -1112,8 +1111,8 @@
      * This method does nothing if the key is not in the map.
      *
      * @param  key the key that needs to be removed
-     * @return the previous value associated with <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}
      * @throws NullPointerException if the specified key is null
      */
     public V remove(Object key) {
@@ -1151,7 +1150,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
@@ -1177,14 +1176,14 @@
     /**
      * Returns a {@link Set} view of the keys contained in this map.
      * The set is backed by the map, so changes to the map are
-     * reflected in the set, and vice-versa.  The set supports element
+     * reflected in the set, and vice-versa. The set supports element
      * removal, which removes the corresponding mapping from this map,
-     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
-     * operations.  It does not support the <tt>add</tt> or
-     * <tt>addAll</tt> operations.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll}, and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1200,12 +1199,12 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  The collection
      * supports element removal, which removes the corresponding
-     * mapping from this map, via the <tt>Iterator.remove</tt>,
-     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
-     * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not
-     * support the <tt>add</tt> or <tt>addAll</tt> operations.
+     * mapping from this map, via the {@code Iterator.remove},
+     * {@code Collection.remove}, {@code removeAll},
+     * {@code retainAll}, and {@code clear} operations.  It does not
+     * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1221,12 +1220,12 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  The set supports element
      * removal, which removes the corresponding mapping from the map,
-     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
-     * operations.  It does not support the <tt>add</tt> or
-     * <tt>addAll</tt> operations.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll}, and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1440,7 +1439,7 @@
     /* ---------------- Serialization Support -------------- */
 
     /**
-     * Saves the state of the <tt>ConcurrentHashMap</tt> instance to a
+     * Saves the state of the {@code ConcurrentHashMap} instance to a
      * stream (i.e., serializes it).
      * @param s the stream
      * @serialData
@@ -1477,8 +1476,7 @@
     }
 
     /**
-     * Reconstitutes the <tt>ConcurrentHashMap</tt> instance from a
-     * stream (i.e., deserializes it).
+     * Reconstitutes the instance from a stream (that is, deserializes it).
      * @param s the stream
      */
     @SuppressWarnings("unchecked")
--- a/jdk/src/share/classes/java/util/function/BiConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,14 +24,16 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts two input arguments and returns no result. This is
  * the two-arity specialization of {@link Consumer}. Unlike most other
  * functional interfaces, {@code BiConsumer} is expected to operate via
  * side-effects.
  *
- * @param <T> the type of the first argument to the {@code accept} operation.
- * @param <U> the type of the second argument to the {@code accept} operation.
+ * @param <T> the type of the first argument to the {@code accept} operation
+ * @param <U> the type of the second argument to the {@code accept} operation
  *
  * @see Consumer
  * @since 1.8
@@ -47,4 +49,28 @@
      * @param u an input object
      */
     void accept(T t, U u);
+
+    /**
+     * Returns a {@code BiConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * the other {@code BiConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a BiConsumer which will be chained after this BiConsumer
+     * @return a BiConsumer which performs in sequence the {@code accept} method
+     * of this BiConsumer and the {@code accept} method of the specified
+     * BiConsumer operation
+     * @throws NullPointerException if other is null
+     */
+    default BiConsumer<T, U> chain(BiConsumer<? super T, ? super U> other) {
+        Objects.requireNonNull(other);
+
+        return (l, r) -> {
+            accept(l, r);
+            other.accept(l, r);
+        };
+    }
 }
--- a/jdk/src/share/classes/java/util/function/BiFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,15 +24,17 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * Apply a function to the input arguments, yielding an appropriate result. This
  * is the two-arity specialization of {@link Function}. A function may
  * variously provide a mapping between types, object instances or keys and
  * values or any other form of transformation upon the input.
  *
- * @param <T> the type of the first argument to the {@code apply} operation.
- * @param <U> the type of the second argument to the {@code apply} operation.
- * @param <R> the type of results returned by the {@code apply} operation.
+ * @param <T> the type of the first argument to the {@code apply} operation
+ * @param <U> the type of the second argument to the {@code apply} operation
+ * @param <R> the type of results returned by the {@code apply} operation
  *
  * @see Function
  * @since 1.8
@@ -48,4 +50,22 @@
      * @return the function result
      */
     R apply(T t, U u);
+
+    /**
+     * Returns a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> Type of output objects to the combined function. May be the
+     * same type as {@code <T>}, {@code <U>} or {@code <R>}
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function
+     * @throws NullPointerException if after is null
+     */
+    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
+        Objects.requireNonNull(after);
+        return (T t, U u) -> after.apply(apply(t, u));
+    }
 }
--- a/jdk/src/share/classes/java/util/function/BiPredicate.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiPredicate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,8 +30,8 @@
  * Determines if the input objects match some criteria. This is the two-arity
  * specialization of {@link Predicate}.
  *
- * @param <T> the type of the first argument to {@code test}.
- * @param <U> the type of the second argument to {@code test}.
+ * @param <T> the type of the first argument to {@code test}
+ * @param <U> the type of the second argument to {@code test}
  *
  * @see Predicate
  * @since 1.8
@@ -42,9 +42,9 @@
     /**
      * Return {@code true} if the inputs match some criteria.
      *
-     * @param t an input object.
-     * @param u an input object.
-     * @return {@code true} if the inputs match some criteria.
+     * @param t an input object
+     * @param u an input object
+     * @return {@code true} if the inputs match some criteria
      */
     boolean test(T t, U u);
 
@@ -54,11 +54,12 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
+    default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
         Objects.requireNonNull(p);
         return (T t, U u) -> test(t, u) && p.test(t, u);
     }
@@ -67,9 +68,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default BiPredicate<T, U> negate() {
+    default BiPredicate<T, U> negate() {
         return (T t, U u) -> !test(t, u);
     }
 
@@ -79,25 +80,13 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
+    default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
         Objects.requireNonNull(p);
         return (T t, U u) -> test(t, u) || p.test(t, u);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     */
-    public default BiPredicate<T, U> xor(BiPredicate<? super T, ? super U> p) {
-        Objects.requireNonNull(p);
-        return (T t, U u) -> test(t, u) ^ p.test(t, u);
-    }
 }
--- a/jdk/src/share/classes/java/util/function/BooleanSupplier.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BooleanSupplier.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,5 +40,5 @@
      *
      * @return a {@code boolean} value
      */
-    public boolean getAsBoolean();
+    boolean getAsBoolean();
 }
--- a/jdk/src/share/classes/java/util/function/Consumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Consumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single input argument and returns no result.
  * Unlike most other functional interfaces, {@code Consumer} is expected to
@@ -41,5 +43,25 @@
      *
      * @param t the input object
      */
-    public void accept(T t);
+    void accept(T t);
+
+    /**
+     * Returns a {@code Consumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * the other {@code Consumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a Consumer which will be chained after this Consumer
+     * @return a Consumer which performs in sequence the {@code accept} method
+     * of this Consumer and the {@code accept} method of the specified Consumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default Consumer<T> chain(Consumer<? super T> other) {
+        Objects.requireNonNull(other);
+        return (T t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,5 +43,5 @@
      * @param right the right operand value
      * @return the result of the operation
      */
-    public double applyAsDouble(double left, double right);
+    double applyAsDouble(double left, double right);
 }
--- a/jdk/src/share/classes/java/util/function/DoubleConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single double argument and returns no result.
  * This is the primitive type specialization of {@link Consumer} for
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(double value);
+    void accept(double value);
+
+    /**
+     * Returns a {@code DoubleConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code DoubleConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a DoubleConsumer which will be chained after this
+     * DoubleConsumer
+     * @return an DoubleConsumer which performs in sequence the {@code accept} method
+     * of this DoubleConsumer and the {@code accept} method of the specified IntConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default DoubleConsumer chain(DoubleConsumer other) {
+        Objects.requireNonNull(other);
+        return (double t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/jdk/src/share/classes/java/util/function/DoubleFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(double value);
+    R apply(double value);
 }
--- a/jdk/src/share/classes/java/util/function/DoublePredicate.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoublePredicate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,11 +40,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
-     * {@code false}.
+     * {@code false}
      */
-    public boolean test(double value);
+    boolean test(double value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -52,11 +52,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default DoublePredicate and(DoublePredicate p) {
+    default DoublePredicate and(DoublePredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -65,9 +70,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default DoublePredicate negate() {
+    default DoublePredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -77,25 +82,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default DoublePredicate or(DoublePredicate p) {
+    default DoublePredicate or(DoublePredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if all or none of the
-     * component predicates evaluate to {@code true}.
-     */
-    public default DoublePredicate xor(DoublePredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/jdk/src/share/classes/java/util/function/DoubleSupplier.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,5 +39,5 @@
      *
      * @return a {@code double} value
      */
-    public double getAsDouble();
+    double getAsDouble();
 }
--- a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a {@code double} operand yielding a {@code double}
  * result. This is the primitive type specialization of {@link UnaryOperator}
@@ -42,5 +44,46 @@
      * @param operand the operand value
      * @return the operation result value
      */
-    public double applyAsDouble(double operand);
+    double applyAsDouble(double operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before An additional function to be applied before this function
+     * is applied
+     * @return A function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default DoubleUnaryOperator compose(DoubleUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (double v) -> applyAsDouble(before.applyAsDouble(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default DoubleUnaryOperator andThen(DoubleUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (double t) -> after.applyAsDouble(applyAsDouble(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static DoubleUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/jdk/src/share/classes/java/util/function/Function.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Function.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,14 +24,15 @@
  */
 package java.util.function;
 
+import java.util.Objects;
 
 /**
  * Apply a function to the input argument, yielding an appropriate result.  A
  * function may variously provide a mapping between types, object instances or
  * keys and values or any other form of transformation upon the input.
  *
- * @param <T> the type of the input to the {@code apply} operation.
- * @param <R> the type of the result of the {@code apply} operation.
+ * @param <T> the type of the input to the {@code apply} operation
+ * @param <R> the type of the result of the {@code apply} operation
  *
  * @since 1.8
  */
@@ -44,5 +45,50 @@
      * @param t the input object
      * @return the function result
      */
-    public R apply(T t);
+    R apply(T t);
+
+    /**
+     * Returns a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> type of input objects to the combined function. May be the
+     * same type as {@code <T>} or {@code <R>}
+     * @param before an additional function to be applied before this function
+     * is applied
+     * @return a function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
+        Objects.requireNonNull(before);
+        return (V v) -> apply(before.apply(v));
+    }
+
+    /**
+     * Returns a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> type of output objects to the combined function. May be the
+     * same type as {@code <T>} or {@code <R>}
+     * @param after an additional function to be applied after this function is
+     * applied
+     * @return a function which performs this function followed by the provided
+     * function
+     * @throws NullPointerException if after is null
+     */
+    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
+        Objects.requireNonNull(after);
+        return (T t) -> after.apply(apply(t));
+    }
+
+    /**
+     * Returns a {@code Function} whose {@code apply} method returns its input.
+     *
+     * @param <T> the type of the input and output objects to the function
+     */
+    static <T> Function<T, T> identity() {
+        return t -> t;
+    }
 }
--- a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -44,5 +44,5 @@
      * @param right  the right operand value
      * @return the result of the operation
      */
-    public int applyAsInt(int left, int right);
+    int applyAsInt(int left, int right);
 }
--- a/jdk/src/share/classes/java/util/function/IntConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single integer argument and returns no result.
  * This is the primitive type specialization of {@link Consumer} for {@code int}.
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(int value);
+    void accept(int value);
+
+    /**
+     * Returns an {@code IntConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code IntConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other an IntConsumer which will be chained after this
+     * IntConsumer
+     * @return an IntConsumer which performs in sequence the {@code accept} method
+     * of this IntConsumer and the {@code accept} method of the specified IntConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default IntConsumer chain(IntConsumer other) {
+        Objects.requireNonNull(other);
+        return (int t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/jdk/src/share/classes/java/util/function/IntFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(int value);
+    R apply(int value);
 }
--- a/jdk/src/share/classes/java/util/function/IntPredicate.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntPredicate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,11 +39,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
      * {@code false}
      */
-    public boolean test(int value);
+    boolean test(int value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default IntPredicate and(IntPredicate p) {
+    default IntPredicate and(IntPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -64,9 +69,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default IntPredicate negate() {
+    default IntPredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -76,25 +81,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default IntPredicate or(IntPredicate p) {
+    default IntPredicate or(IntPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}
-     */
-    public default IntPredicate xor(IntPredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/jdk/src/share/classes/java/util/function/IntSupplier.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntSupplier.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,5 +39,5 @@
      *
      * @return an {@code int} value
      */
-    public int getAsInt();
+    int getAsInt();
 }
--- a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a single {@code int} operand yielding an {@code int} result.
  * This is the primitive type specialization of {@link UnaryOperator} for
@@ -37,10 +39,51 @@
 
     /**
      * Returns the {@code int} value result of the operation upon the
-     * {@code int}  operand.
+     * {@code int} operand.
      *
      * @param operand the operand value
      * @return the operation result value
      */
-    public int applyAsInt(int operand);
+    int applyAsInt(int operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before an additional function to be applied before this function
+     * is applied
+     * @return a function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default IntUnaryOperator compose(IntUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (int v) -> applyAsInt(before.applyAsInt(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after an additional function to be applied after this function is
+     * applied
+     * @return a function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default IntUnaryOperator andThen(IntUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (int t) -> after.applyAsInt(applyAsInt(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static IntUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -44,5 +44,5 @@
      * @param right  the right operand value
      * @return the result of the operation
      */
-    public long applyAsLong(long left, long right);
+    long applyAsLong(long left, long right);
 }
--- a/jdk/src/share/classes/java/util/function/LongConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single long argument and returns no result.
  * This is the {@code long}-consuming primitive type specialization of
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(long value);
+    void accept(long value);
+
+    /**
+     * Returns a {@code LongConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code LongConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a LongConsumer which will be chained after this
+     * LongConsumer
+     * @return a LongConsumer which performs in sequence the {@code accept} method
+     * of this LongConsumer and the {@code accept} method of the specified LongConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default LongConsumer chain(LongConsumer other) {
+        Objects.requireNonNull(other);
+        return (long t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/jdk/src/share/classes/java/util/function/LongFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(long value);
+    R apply(long value);
 }
--- a/jdk/src/share/classes/java/util/function/LongPredicate.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongPredicate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,11 +39,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
-     * {@code false}.
+     * {@code false}
      */
-    public boolean test(long value);
+    boolean test(long value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,15 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
      */
-    public default LongPredicate and(LongPredicate p) {
+    default LongPredicate and(LongPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -64,9 +68,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default LongPredicate negate() {
+    default LongPredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -76,25 +80,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default LongPredicate or(LongPredicate p) {
+    default LongPredicate or(LongPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     */
-    public default LongPredicate xor(LongPredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/jdk/src/share/classes/java/util/function/LongSupplier.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongSupplier.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,5 +39,5 @@
      *
      * @return a {@code long} value
      */
-    public long getAsLong();
+    long getAsLong();
 }
--- a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a single {@code long} operand yielding a {@code long} result.
  * This is the primitive type specialization of {@link UnaryOperator} for
@@ -42,5 +44,46 @@
      * @param operand the operand value
      * @return the operation result value
      */
-    public long applyAsLong(long operand);
+    long applyAsLong(long operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before An additional function to be applied before this function
+     * is applied
+     * @return A function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default LongUnaryOperator compose(LongUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (long v) -> applyAsLong(before.applyAsLong(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default LongUnaryOperator andThen(LongUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (long t) -> after.applyAsLong(applyAsLong(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static LongUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, double value);
+    void accept(T t, double value);
 }
--- a/jdk/src/share/classes/java/util/function/ObjIntConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,7 +30,7 @@
  * {@link BiConsumer}. Unlike most other functional interfaces,
  * {@code ObjIntConsumer} is expected to operate via side-effects.
  *
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
  *
  * @see BiConsumer
  * @since 1.8
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, int value);
+    void accept(T t, int value);
 }
--- a/jdk/src/share/classes/java/util/function/ObjLongConsumer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,7 +30,7 @@
  * {@link BiConsumer}. Unlike most other functional interfaces,
  * {@code ObjLongConsumer} is expected to operate via side-effects.
  *
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
  *
  * @see BiConsumer
  * @since 1.8
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, long value);
+    void accept(T t, long value);
 }
--- a/jdk/src/share/classes/java/util/function/Predicate.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Predicate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,7 +43,7 @@
      * @return {@code true} if the input object matches some criteria, otherwise
      * {@code false}
      */
-    public boolean test(T t);
+    boolean test(T t);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default Predicate<T> and(Predicate<? super T> p) {
+    default Predicate<T> and(Predicate<? super T> p) {
         Objects.requireNonNull(p);
         return (t) -> test(t) && p.test(t);
     }
@@ -66,7 +71,7 @@
      * @return a new predicate who's result is always the opposite of this
      * predicate.
      */
-    public default Predicate<T> negate() {
+    default Predicate<T> negate() {
         return (t) -> !test(t);
     }
 
@@ -76,25 +81,32 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default Predicate<T> or(Predicate<? super T> p) {
+    default Predicate<T> or(Predicate<? super T> p) {
         Objects.requireNonNull(p);
         return (t) -> test(t) || p.test(t);
     }
 
     /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
+     * Returns a predicate who's result matches
+     * {@code Objects.equals(target, t)}.
      *
-     * @param p a predicate which will be logically-XORed with this predicte.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
+     * @param <T> the type of values evaluated by the predicate
+     * @param target the target value to be compared for equality
+     * @return a predicate who's result matches
+     * {@code Objects.equals(target, t)}
      */
-    public default Predicate<T> xor(Predicate<? super T> p) {
-        Objects.requireNonNull(p);
-        return (t) -> test(t) ^ p.test(t);
+    static <T> Predicate<T> isEqual(Object target) {
+        return (null == target)
+                ? Objects::isNull
+                : object -> target.equals(object);
     }
 }
--- a/jdk/src/share/classes/java/util/function/Supplier.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Supplier.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,5 +40,5 @@
      *
      * @return an object
      */
-    public T get();
+    T get();
 }
--- a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public double applyAsDouble(T t, U u);
+    double applyAsDouble(T t, U u);
 }
--- a/jdk/src/share/classes/java/util/function/ToDoubleFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public double applyAsDouble(T t);
+    double applyAsDouble(T t);
 }
--- a/jdk/src/share/classes/java/util/function/ToIntBiFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,10 +28,10 @@
  * Apply a function to the input arguments, yielding an appropriate result.
  * This is the {@code int}-bearing specialization for {@link BiFunction}.
  *
- * @param <T> the type of the first argument to the {@code applyAsLong}
- * operation.
- * @param <U> the type of the second argument to the {@code applyAsLong}
- * operation.
+ * @param <T> the type of the first argument to the {@code applyAsInt}
+ * operation
+ * @param <U> the type of the second argument to the {@code applyAsInt}
+ * operation
  *
  * @see BiFunction
  * @since 1.8
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public int applyAsInt(T t, U u);
+    int applyAsInt(T t, U u);
 }
--- a/jdk/src/share/classes/java/util/function/ToIntFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public int applyAsInt(T t);
+    int applyAsInt(T t);
 }
--- a/jdk/src/share/classes/java/util/function/ToLongBiFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public long applyAsLong(T t, U u);
+    long applyAsLong(T t, U u);
 }
--- a/jdk/src/share/classes/java/util/function/ToLongFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public long applyAsLong(T t);
+    long applyAsLong(T t);
 }
--- a/jdk/src/share/classes/java/util/function/UnaryOperator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,4 +36,13 @@
  */
 @FunctionalInterface
 public interface UnaryOperator<T> extends Function<T, T> {
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static <T> UnaryOperator<T> identity() {
+        return t -> t;
+    }
 }
--- a/jdk/src/share/classes/javax/swing/JToolTip.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/JToolTip.java	Wed Jul 05 18:57:52 2017 +0200
@@ -31,6 +31,7 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectInputStream;
 import java.io.IOException;
+import java.util.Objects;
 
 
 /**
@@ -128,6 +129,11 @@
         String oldValue = this.tipText;
         this.tipText = tipText;
         firePropertyChange("tiptext", oldValue, tipText);
+
+        if (!Objects.equals(oldValue, tipText)) {
+            revalidate();
+            repaint();
+        }
     }
 
     /**
--- a/jdk/src/share/classes/javax/swing/text/View.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/View.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1174,6 +1174,7 @@
         // formed by added elements (i.e. they will be updated
         // by initialization.
         index0 = Math.max(index0, 0);
+        index1 = getViewIndex(elem.getDocument().getLength(), Position.Bias.Forward);
         for (int i = index0; i <= index1; i++) {
             if (! ((i >= hole0) && (i <= hole1))) {
                 v = getView(i);
--- a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -1980,11 +1980,12 @@
 
     void parseScript() throws IOException {
         char[] charsToAdd = new char[SCRIPT_END_TAG.length];
+        boolean insideComment = false;
 
         /* Here, ch should be the first character after <script> */
         while (true) {
             int i = 0;
-            while (i < SCRIPT_END_TAG.length
+            while (!insideComment && i < SCRIPT_END_TAG.length
                        && (SCRIPT_END_TAG[i] == ch
                            || SCRIPT_END_TAG_UPPER_CASE[i] == ch)) {
                 charsToAdd[i] = (char) ch;
@@ -2025,6 +2026,13 @@
                     break;
                 default:
                     addString(ch);
+                    String str = new String(getChars(0, strpos));
+                    if (!insideComment && str.endsWith(START_COMMENT)) {
+                        insideComment = true;
+                    }
+                    if (insideComment && str.endsWith(END_COMMENT)) {
+                        insideComment = false;
+                    }
                     ch = readCh();
                     break;
                 } // switch
--- a/jdk/src/share/classes/sun/management/Agent.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/management/Agent.java	Wed Jul 05 18:57:52 2017 +0200
@@ -77,7 +77,7 @@
     private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
             "sun.management.snmp.AdaptorBootstrap";
 
-    private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
+    private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
     private static final int JDP_DEFAULT_PORT = 7095;
 
     // The only active agent allowed
--- a/jdk/src/share/classes/sun/management/jdp/package-info.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/management/jdp/package-info.java	Wed Jul 05 18:57:52 2017 +0200
@@ -60,7 +60,7 @@
  *
  * - `INSTANCE_NAME` -- The user-provided name of the running instance
  *
- * The protocol sends packets to 239.255.255.225:7095 by default.
+ * The protocol sends packets to 224.0.23.178:7095 by default.
  *
  * The protocol uses system properties to control it's behaviour:
  * - `com.sun.management.jdp.port` -- override default port
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Wed Jul 05 18:57:52 2017 +0200
@@ -682,6 +682,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        private byte repl = (byte)'?';
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement[0];
+        }
+
         // returns -1 if there is malformed char(s) and the
         // "action" for malformed input is not REPLACE.
         public int encode(char[] sa, int sp, int len, byte[] da) {
@@ -709,7 +714,7 @@
                     if (uc < 0) {
                         if (malformedInputAction() != CodingErrorAction.REPLACE)
                             return -1;
-                        da[dp++] = replacement()[0];
+                        da[dp++] = repl;
                     } else {
                         da[dp++] = (byte)(0xf0 | ((uc >> 18)));
                         da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
--- a/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java	Wed Jul 05 18:57:52 2017 +0200
@@ -610,6 +610,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        protected byte[] repl = replacement();
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement;
+        }
+
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -622,7 +627,6 @@
                         Character.isLowSurrogate(src[sp])) {
                         sp++;
                     }
-                    byte[] repl = replacement();
                     dst[dp++] = repl[0];
                     if (repl.length > 1)
                         dst[dp++] = repl[1];
@@ -877,7 +881,6 @@
                         Character.isLowSurrogate(src[sp])) {
                         sp++;
                     }
-                    byte[] repl = replacement();
                     dst[dp++] = repl[0];
                     if (repl.length > 1)
                         dst[dp++] = repl[1];
--- a/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java	Wed Jul 05 18:57:52 2017 +0200
@@ -356,6 +356,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        private byte[] repl = replacement();
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement;
+        }
+
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -367,7 +372,6 @@
                         !Character.isLowSurrogate(src[sp]) ||
                         (bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
                         == UNMAPPABLE_ENCODING) {
-                        byte[] repl = replacement();
                         dst[dp++] = repl[0];
                         if (repl.length > 1)
                             dst[dp++] = repl[1];
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 18:57:52 2017 +0200
@@ -78,7 +78,7 @@
 
     private final String tabName;
     private long lastModified;
-    private int kt_vno;
+    private int kt_vno = KRB5_KT_VNO;
 
     private Vector<KeyTabEntry> entries = new Vector<>();
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jul 05 18:57:52 2017 +0200
@@ -552,7 +552,7 @@
 
         try {
             Signature respSignature = Signature.getInstance(sigAlgId.getName());
-            respSignature.initVerify(cert);
+            respSignature.initVerify(cert.getPublicKey());
             respSignature.update(tbsResponseData);
 
             if (respSignature.verify(signature)) {
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1447,6 +1447,7 @@
         PERM_ARRAY.add(new AWTPerm());
         PERM_ARRAY.add(new DelegationPerm());
         PERM_ARRAY.add(new FilePerm());
+        PERM_ARRAY.add(new HttpURLPerm());
         PERM_ARRAY.add(new InqSecContextPerm());
         PERM_ARRAY.add(new LogPerm());
         PERM_ARRAY.add(new MgmtPerm());
@@ -3842,6 +3843,20 @@
     }
 }
 
+class HttpURLPerm extends Perm {
+    public HttpURLPerm() {
+        super("HttpURLPermission",
+                "java.net.HttpURLPermission",
+                new String[]    {
+                    "<"+ PolicyTool.rb.getString("url") + ">",
+                },
+                new String[]    {
+                    "<" + PolicyTool.rb.getString("method.list") + ">:<"
+                        + PolicyTool.rb.getString("request.headers.list") + ">",
+                });
+    }
+}
+
 class InqSecContextPerm extends Perm {
     public InqSecContextPerm() {
     super("InquireSecContextPermission",
--- a/jdk/src/share/classes/sun/security/tools/policytool/Resources.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/Resources.java	Wed Jul 05 18:57:52 2017 +0200
@@ -139,6 +139,9 @@
         {"policy.type", "policy type"},
         {"property.name", "property name"},
         {"provider.name", "provider name"},
+        {"url", "url"},
+        {"method.list", "method list"},
+        {"request.headers.list", "request headers list"},
         {"Principal.List", "Principal List"},
         {"Permission.List", "Permission List"},
         {"Code.Base", "Code Base"},
--- a/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java	Wed Jul 05 18:57:52 2017 +0200
@@ -54,7 +54,7 @@
                     "Mejju",
                     "\u0120unju",
                     "Lulju",
-                    "Awissu",
+                    "Awwissu",
                     "Settembru",
                     "Ottubru",
                     "Novembru",
@@ -71,7 +71,7 @@
                     "Mej",
                     "\u0120un",
                     "Lul",
-                    "Awi",
+                    "Aww",
                     "Set",
                     "Ott",
                     "Nov",
--- a/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java	Wed Jul 05 18:57:52 2017 +0200
@@ -34,6 +34,7 @@
 import javax.swing.border.*;
 import javax.swing.event.*;
 
+import static sun.misc.Version.jdkMinorVersion;
 
 import static java.awt.BorderLayout.*;
 import static sun.tools.jconsole.Utilities.*;
@@ -73,7 +74,7 @@
         String jConsoleVersion = Version.getVersion();
         String vmName = System.getProperty("java.vm.name");
         String vmVersion = System.getProperty("java.vm.version");
-        String urlStr = Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
+        String urlStr = getOnlineDocUrl();
         if (isBrowseSupported()) {
             urlStr = "<a style='color:#35556b' href=\"" + urlStr + "\">" + urlStr + "</a>";
         }
@@ -86,8 +87,7 @@
                                 "<html><font color=#"+ colorStr + ">" +
                         Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
                 "<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_JAVA_VERSION, (vmName +", "+ vmVersion)) +
-                "<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK, urlStr) +
-                                                 "</html>");
+                "<p>" + urlStr + "</html>");
         helpLink.setOpaque(false);
         helpLink.setEditable(false);
         helpLink.setForeground(textColor);
@@ -153,7 +153,7 @@
     }
 
     static void browseUserGuide(JConsole jConsole) {
-        getAboutDialog(jConsole).browse(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL);
+        getAboutDialog(jConsole).browse(getOnlineDocUrl());
     }
 
     static boolean isBrowseSupported() {
@@ -182,6 +182,12 @@
         };
     }
 
+    private static String getOnlineDocUrl() {
+        String version = Integer.toString(jdkMinorVersion());
+        return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL,
+                                version);
+    }
+
     private static class TPanel extends JPanel {
         TPanel(int hgap, int vgap) {
             super(new BorderLayout(hgap, vgap));
--- a/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java	Wed Jul 05 18:57:52 2017 +0200
@@ -55,6 +55,7 @@
     private VMInternalFrame vmIF = null;
     private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
     private boolean wasConnected = false;
+    private boolean userDisconnected = false;
 
     // The everConnected flag keeps track of whether the window can be
     // closed if the user clicks Cancel after a failed connection attempt.
@@ -125,6 +126,7 @@
                 if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
 
                     if (isConnected()) {
+                        userDisconnected = true;
                         disconnect();
                         wasConnected = false;
                     } else {
@@ -452,6 +454,11 @@
     private void vmPanelDied() {
         disconnect();
 
+        if (userDisconnected) {
+            userDisconnected = false;
+            return;
+        }
+
         JOptionPane optionPane;
         String msgTitle, msgExplanation, buttonStr;
 
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole
 HELP_ABOUT_DIALOG_TITLE=JConsole: About
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=&About JConsole
 HELP_MENU_USER_GUIDE_TITLE=Online &User Guide
 HELP_MENU_TITLE=&Help
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066
 HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=JConsole\u306B\u3064\u3044\u3066(&A)
 HELP_MENU_USER_GUIDE_TITLE=\u30AA\u30F3\u30E9\u30A4\u30F3\u30FB\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U)
 HELP_MENU_TITLE=\u30D8\u30EB\u30D7(&H)
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole
 HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=\u5173\u4E8E JConsole(&A)
 HELP_MENU_USER_GUIDE_TITLE=\u8054\u673A\u7528\u6237\u6307\u5357(&U)
 HELP_MENU_TITLE=\u5E2E\u52A9(&H)
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1085,13 +1085,13 @@
     }
 
     // Creates a new empty temporary file in the same directory as the
-    // specified file.  A variant of File.createTempFile.
+    // specified file.  A variant of Files.createTempFile.
     private Path createTempFileInSameDirectoryAs(Path path)
         throws IOException
     {
         Path parent = path.toAbsolutePath().getParent();
-        String dir = (parent == null)? "." : parent.toString();
-        Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath();
+        Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+        Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
         tmppaths.add(tmpPath);
         return tmpPath;
     }
--- a/jdk/src/share/native/java/io/FileInputStream.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/native/java/io/FileInputStream.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -100,6 +100,8 @@
     if (IO_Available(fd, &ret)) {
         if (ret > INT_MAX) {
             ret = (jlong) INT_MAX;
+        } else if (ret < 0) {
+            ret = 0;
         }
         return jlong_to_jint(ret);
     }
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Wed Jul 05 18:57:52 2017 +0200
@@ -634,6 +634,8 @@
     cmsFloat64Number dnum = 0.0;
     int sign = 1;
 
+    if (Buffer == NULL) return 0.0;
+
     if (*Buffer == '-' || *Buffer == '+') {
 
          sign = (*Buffer == '-') ? -1 : 1;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1021,6 +1021,8 @@
     mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
     cmsFreeToneCurveTriple(LabTable);
 
+    if (mpe == NULL) return NULL;
+
     mpe ->Implements = cmsSigLabV2toV4;
     return mpe;
 }
--- a/jdk/src/solaris/bin/arm/jvm.cfg	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/bin/arm/jvm.cfg	Wed Jul 05 18:57:52 2017 +0200
@@ -30,6 +30,6 @@
 # "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
 # and may not be available in a future release.
 #
--client KNOWN
+-client IF_SERVER_CLASS -server
 -server KNOWN
 -minimal KNOWN
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -190,7 +190,7 @@
                 try {
                     Native.putLong(data, motifWindow);
 
-                    XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                    XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                     XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                                 defaultRootWindow,
                                                 XA_MOTIF_DRAG_WINDOW.getAtom(),
@@ -198,10 +198,10 @@
                                                 XConstants.PropModeReplace,
                                                 data, 1);
 
-                    XToolkit.RESTORE_XERROR_HANDLER();
+                    XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                    if (XToolkit.saved_error != null &&
-                        XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                    if ((XErrorHandlerUtil.saved_error != null) &&
+                        (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                         throw new XException("Cannot write motif drag window handle.");
                     }
 
@@ -394,7 +394,7 @@
                 }
             }
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                         motifWindow,
                                         XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -402,15 +402,15 @@
                                         XConstants.PropModeReplace,
                                         data, tableSize);
 
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
 
                 // Create a new motif window and retry.
                 motifWindow = createMotifWindow();
 
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                 XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                             motifWindow,
                                             XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -418,10 +418,10 @@
                                             XConstants.PropModeReplace,
                                             data, tableSize);
 
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (XToolkit.saved_error != null &&
-                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                if ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                     throw new XException("Cannot write motif drag targets property.");
                 }
             }
@@ -534,16 +534,16 @@
             // CARD32 icc_handle
             unsafe.putInt(structData + 4, (int)XA_MOTIF_ATOM_0.getAtom());
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
                                         XA_MOTIF_ATOM_0.getAtom(),
                                         XA_MOTIF_DRAG_INITIATOR_INFO.getAtom(),
                                         8, XConstants.PropModeReplace,
                                         structData, MOTIF_INITIATOR_INFO_SIZE);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write drag initiator info");
             }
         } finally {
@@ -567,16 +567,16 @@
             unsafe.putShort(data + 10, (short)0); /* pad */
             unsafe.putInt(data + 12, dataSize);
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
                                         XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                         XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                         8, XConstants.PropModeReplace,
                                         data, dataSize);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write Motif receiver info property");
             }
         } finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -162,16 +162,16 @@
                 unsafe.putInt(data + 12, dataSize);
             }
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
                                         MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                         MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                         8, XConstants.PropModeReplace,
                                         data, dataSize);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write Motif receiver info property");
             }
         } finally {
@@ -236,16 +236,16 @@
 
                     unsafe.putInt(data + 4, tproxy);
 
-                    XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                    XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                     XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
                                                 MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                                 MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                                 8, XConstants.PropModeReplace,
                                                 data, dataSize);
-                    XToolkit.RESTORE_XERROR_HANDLER();
+                    XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                    if (XToolkit.saved_error != null &&
-                        XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                    if ((XErrorHandlerUtil.saved_error != null) &&
+                        (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                         throw new XException("Cannot write Motif receiver info property");
                     }
                 }
@@ -412,15 +412,15 @@
          */
         XWindowAttributes wattr = new XWindowAttributes();
         try {
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
             int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                           source_win, wattr.pData);
 
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (status == 0 ||
-                (XToolkit.saved_error != null &&
-                 XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+            if ((status == 0) ||
+                ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                 throw new XException("XGetWindowAttributes failed");
             }
 
@@ -429,15 +429,15 @@
             wattr.dispose();
         }
 
-        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
         XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
                                  source_win_mask |
                                  XConstants.StructureNotifyMask);
 
-        XToolkit.RESTORE_XERROR_HANDLER();
+        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-        if (XToolkit.saved_error != null &&
-            XToolkit.saved_error.get_error_code() != XConstants.Success) {
+        if ((XErrorHandlerUtil.saved_error != null) &&
+            (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
             throw new XException("XSelectInput failed");
         }
 
@@ -1024,10 +1024,10 @@
         if (sourceWindow != 0) {
             XToolkit.awtLock();
             try {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
                                          sourceWindowMask);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
             } finally {
                 XToolkit.awtUnlock();
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -99,7 +99,7 @@
             }
 
             if (errorHandler != null) {
-                XToolkit.WITH_XERROR_HANDLER(errorHandler);
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
             }
             Native.putLong(data, 0);
             int status = XlibWrapper.XGetWindowProperty(XToolkit.getDisplay(), window, property.getAtom(),
@@ -112,7 +112,7 @@
             }
 
             if (errorHandler != null) {
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
             }
             return status;
         } finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -674,4 +674,9 @@
     public static final long XkbModifierMapMask = (1L<<2);
     public static final long XkbVirtualModsMask = (1L<<6); //server map
 
+    /*****************************************************************
+     * X SHARED MEMORY EXTENSION FUNCTIONS
+     *****************************************************************/
+
+    public static final int X_ShmAttach = 1;
 }
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -96,14 +96,14 @@
                 action_count++;
             }
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndActionList.setAtomData(window,
                                                         XAtom.XA_ATOM,
                                                         data, action_count);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error) != null &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 cleanup();
                 throw new XException("Cannot write XdndActionList property");
             }
@@ -117,14 +117,14 @@
         try {
             Native.put(data, formats);
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndTypeList.setAtomData(window,
                                                       XAtom.XA_ATOM,
                                                       data, formats.length);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 cleanup();
                 throw new XException("Cannot write XdndActionList property");
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -88,12 +88,12 @@
         try {
             Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndAware.setAtomData(window, XAtom.XA_ATOM, data, 1);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write XdndAware property");
             }
         } finally {
@@ -205,54 +205,50 @@
 
             /* The proxy window must have the XdndAware set, as XDnD protocol
                prescribes to check the proxy window for XdndAware. */
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndAware.setAtomData(newProxy, XAtom.XA_ATOM,
                                                    data, 1);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() !=
-                XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write XdndAware property");
             }
 
             Native.putLong(data, 0, newProxy);
 
             /* The proxy window must have the XdndProxy set to point to itself.*/
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndProxy.setAtomData(newProxy, XAtom.XA_WINDOW,
                                                    data, 1);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() !=
-                XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write XdndProxy property");
             }
 
             Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
                                                    data, 1);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() !=
-                XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write XdndAware property");
             }
 
             Native.putLong(data, 0, newProxy);
 
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
                                                    data, 1);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null &&
-                XToolkit.saved_error.get_error_code() !=
-                XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 throw new XException("Cannot write XdndProxy property");
             }
         } finally {
@@ -278,27 +274,25 @@
             try {
                 Native.putLong(data, 0, entry.getVersion());
 
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                 XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
                                                        data, 1);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (XToolkit.saved_error != null &&
-                    XToolkit.saved_error.get_error_code() !=
-                    XConstants.Success) {
+                if ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                     throw new XException("Cannot write XdndAware property");
                 }
 
                 Native.putLong(data, 0, (int)entry.getProxy());
 
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                 XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
                                                        data, 1);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (XToolkit.saved_error != null &&
-                    XToolkit.saved_error.get_error_code() !=
-                    XConstants.Success) {
+                if ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                     throw new XException("Cannot write XdndProxy property");
                 }
             } finally {
@@ -541,15 +535,15 @@
          */
         XWindowAttributes wattr = new XWindowAttributes();
         try {
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
             int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                           source_win, wattr.pData);
 
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (status == 0 ||
-                (XToolkit.saved_error != null &&
-                 XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+            if ((status == 0) ||
+                ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                 throw new XException("XGetWindowAttributes failed");
             }
 
@@ -558,15 +552,15 @@
             wattr.dispose();
         }
 
-        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
         XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
                                  source_win_mask |
                                  XConstants.StructureNotifyMask);
 
-        XToolkit.RESTORE_XERROR_HANDLER();
+        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-        if (XToolkit.saved_error != null &&
-            XToolkit.saved_error.get_error_code() != XConstants.Success) {
+        if ((XErrorHandlerUtil.saved_error != null) &&
+            (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
             throw new XException("XSelectInput failed");
         }
 
@@ -963,10 +957,10 @@
         if (sourceWindow != 0) {
             XToolkit.awtLock();
             try {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
                                          sourceWindowMask);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
             } finally {
                 XToolkit.awtUnlock();
             }
@@ -1111,15 +1105,15 @@
 
                             XToolkit.awtLock();
                             try {
-                                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+                                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                                 XDnDConstants.XA_XdndTypeList.setAtomData(xclient.get_window(),
                                                                           XAtom.XA_ATOM,
                                                                           wpg.getData(),
                                                                           wpg.getNumberOfItems());
-                                XToolkit.RESTORE_XERROR_HANDLER();
+                                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                                if (XToolkit.saved_error != null &&
-                                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                                if ((XErrorHandlerUtil.saved_error != null) &&
+                                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                                     if (logger.isLoggable(PlatformLogger.WARNING)) {
                                         logger.warning("Cannot set XdndTypeList on the proxy window");
                                     }
--- a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -181,15 +181,15 @@
                                    long time) {
         XWindowAttributes wattr = new XWindowAttributes();
         try {
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
             int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                           targetWindow, wattr.pData);
 
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (status == 0 ||
-                (XToolkit.saved_error != null &&
-                 XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+            if ((status == 0) ||
+                ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                 throw new XException("XGetWindowAttributes failed");
             }
 
@@ -198,15 +198,15 @@
             wattr.dispose();
         }
 
-        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
         XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
                                  targetWindowMask |
                                  XConstants.StructureNotifyMask);
 
-        XToolkit.RESTORE_XERROR_HANDLER();
+        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-        if (XToolkit.saved_error != null &&
-            XToolkit.saved_error.get_error_code() != XConstants.Success) {
+        if ((XErrorHandlerUtil.saved_error != null) &&
+            (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
             throw new XException("XSelectInput failed");
         }
 
@@ -214,10 +214,10 @@
     }
 
     protected final void finalizeDrop() {
-        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
         XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
                                  targetWindowMask);
-        XToolkit.RESTORE_XERROR_HANDLER();
+        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
     }
 
     public abstract boolean processProxyModeEvent(XClientMessageEvent xclient,
--- a/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -168,14 +168,14 @@
                 if (dest_x >= 0 && dest_y >= 0) {
                     XWindowAttributes wattr = new XWindowAttributes();
                     try {
-                        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                         int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                                       window, wattr.pData);
-                        XToolkit.RESTORE_XERROR_HANDLER();
+                        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                        if (status == 0 ||
-                            (XToolkit.saved_error != null &&
-                             XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+                        if ((status == 0) ||
+                            ((XErrorHandlerUtil.saved_error != null) &&
+                            (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                             continue;
                         }
 
@@ -222,14 +222,14 @@
             long event_mask = 0;
             XWindowAttributes wattr = new XWindowAttributes();
             try {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                               embedder, wattr.pData);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (status == 0 ||
-                    (XToolkit.saved_error != null &&
-                     XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+                if ((status == 0) ||
+                    ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                     throw new XException("XGetWindowAttributes failed");
                 }
 
@@ -240,13 +240,13 @@
             }
 
             if ((event_mask & XConstants.PropertyChangeMask) == 0) {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
                                          event_mask | XConstants.PropertyChangeMask);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (XToolkit.saved_error != null &&
-                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                if ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                     throw new XException("XSelectInput failed");
                 }
             }
@@ -394,13 +394,13 @@
 
             /* Restore the original event mask for the embedder. */
             if ((event_mask & XConstants.PropertyChangeMask) == 0) {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
                                          event_mask);
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (XToolkit.saved_error != null &&
-                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
+                if ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                     throw new XException("XSelectInput failed");
                 }
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -301,15 +301,15 @@
         try {
             XWindowAttributes wattr = new XWindowAttributes();
             try {
-                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                               xembed.handle, wattr.pData);
 
-                XToolkit.RESTORE_XERROR_HANDLER();
+                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-                if (status == 0 ||
-                    (XToolkit.saved_error != null &&
-                     XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+                if ((status == 0) ||
+                    ((XErrorHandlerUtil.saved_error != null) &&
+                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                     return null;
                 }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -38,7 +38,30 @@
     public static class XBaseErrorHandler extends XErrorHandler {
         @Override
         public int handleError(long display, XErrorEvent err) {
-            return XToolkit.SAVED_ERROR_HANDLER(display, err);
+            return XErrorHandlerUtil.SAVED_XERROR_HANDLER(display, err);
+        }
+    }
+
+    /**
+     * This is a base synthetic error handler containing a boolean flag which allows
+     * to show that an error is handled or not.
+     */
+    public static class XErrorHandlerWithFlag extends XBaseErrorHandler {
+        private volatile boolean errorOccurred = false;
+
+        public boolean getErrorOccurredFlag() {
+            return errorOccurred;
+        }
+
+        /**
+         * Sets an internal boolean flag to a particular value. Should be always called with
+         * <code>false</code> value of the parameter <code>errorOccurred</code> before this
+         * error handler is set as current.
+         * @param errorOccurred <code>true</code> to indicate that an error was handled,
+         *     <code>false</code> to reset the internal boolean flag
+         */
+        public void setErrorOccurredFlag(boolean errorOccurred) {
+            this.errorOccurred = errorOccurred;
         }
     }
 
@@ -76,4 +99,51 @@
             return theInstance;
         }
     }
+
+    /**
+     * This is a synthetic error handler for errors generated by the native function
+     * <code>XShmAttach</code>. If an error is handled, an internal boolean flag of the
+     * handler is set to <code>true</code>.
+     */
+    public static final class XShmAttachHandler extends XErrorHandlerWithFlag {
+        private XShmAttachHandler() {}
+
+        @Override
+        public int handleError(long display, XErrorEvent err) {
+            if (err.get_minor_code() == XConstants.X_ShmAttach) {
+                setErrorOccurredFlag(true);
+                return 0;
+            }
+            return super.handleError(display, err);
+        }
+
+        // Shared instance
+        private static XShmAttachHandler theInstance = new XShmAttachHandler();
+        public static XShmAttachHandler getInstance() {
+            return theInstance;
+        }
+    }
+
+    /**
+     * This is a synthetic error handler for <code>BadAlloc</code> errors generated by the
+     * native <code>glX*</code> functions. Its internal boolean flag is set to <code>true</code>,
+     * if an error is handled.
+     */
+    public static final class GLXBadAllocHandler extends XErrorHandlerWithFlag {
+        private GLXBadAllocHandler() {}
+
+        @Override
+        public int handleError(long display, XErrorEvent err) {
+            if (err.get_error_code() == XConstants.BadAlloc) {
+                setErrorOccurredFlag(true);
+                return 0;
+            }
+            return super.handleError(display, err);
+        }
+
+        private static GLXBadAllocHandler theInstance = new GLXBadAllocHandler();
+        public static GLXBadAllocHandler getInstance() {
+            return theInstance;
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,162 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.awt.X11;
+
+import java.security.AccessController;
+import sun.awt.SunToolkit;
+import sun.security.action.GetBooleanAction;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * This class contains code of the global toolkit error handler, exposes static
+ * methods which allow to set and unset synthetic error handlers.
+ */
+public final class XErrorHandlerUtil {
+    private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XErrorHandlerUtil");
+
+    /**
+     * The connection to X11 window server.
+     */
+    private static long display;
+
+    /**
+     * Error handler at the moment of <code>XErrorHandlerUtil</code> initialization.
+     */
+    private static long saved_error_handler;
+
+    /**
+     * XErrorEvent being handled.
+     */
+    static volatile XErrorEvent saved_error;
+
+    /**
+     * Current error handler or null if no error handler is set.
+     */
+    private static XErrorHandler current_error_handler;
+
+    /**
+     * Value of sun.awt.noisyerrorhandler system property.
+     */
+    private static boolean noisyAwtHandler = AccessController.doPrivileged(
+        new GetBooleanAction("sun.awt.noisyerrorhandler"));
+
+    /**
+     * The flag indicating that <code>init</code> was called already.
+     */
+    private static boolean initPassed;
+
+    /**
+     * Guarantees that no instance of this class can be created.
+     */
+    private XErrorHandlerUtil() {}
+
+    /**
+     * Sets the toolkit global error handler, stores the connection to X11 server, which
+     * will be used during an error handling process. This method is called once from
+     * <code>awt_init_Display</code> function defined in <code>awt_GraphicsEnv.c</code>
+     * file immediately after the connection to X11 window server is opened.
+     * @param display the connection to X11 server which should be stored
+     */
+    private static void init(long display) {
+        SunToolkit.awtLock();
+        try {
+            if (!initPassed) {
+                XErrorHandlerUtil.display = display;
+                saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
+                initPassed = true;
+            }
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    /**
+     * Sets a synthetic error handler. Must be called with the acquired AWT lock.
+     * @param handler the synthetic error handler to set
+     */
+    public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
+        saved_error = null;
+        current_error_handler = handler;
+    }
+
+    /**
+     * Unsets a current synthetic error handler. Must be called with the acquired AWT lock.
+     */
+    public static void RESTORE_XERROR_HANDLER() {
+        // Wait until all requests are processed by the X server
+        // and only then uninstall the error handler.
+        XSync();
+        current_error_handler = null;
+    }
+
+    /**
+     * Should be called under LOCK.
+     */
+    public static int SAVED_XERROR_HANDLER(long display, XErrorEvent error) {
+        if (saved_error_handler != 0) {
+            // Default XErrorHandler may just terminate the process. Don't call it.
+            // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
+        }
+        if (log.isLoggable(PlatformLogger.FINE)) {
+            log.fine("Unhandled XErrorEvent: " +
+                "id=" + error.get_resourceid() + ", " +
+                "serial=" + error.get_serial() + ", " +
+                "ec=" + error.get_error_code() + ", " +
+                "rc=" + error.get_request_code() + ", " +
+                "mc=" + error.get_minor_code());
+        }
+        return 0;
+    }
+
+    /**
+     * Called from the native code when an error occurs.
+     */
+    private static int globalErrorHandler(long display, long event_ptr) {
+        if (noisyAwtHandler) {
+            XlibWrapper.PrintXErrorEvent(display, event_ptr);
+        }
+        XErrorEvent event = new XErrorEvent(event_ptr);
+        saved_error = event;
+        try {
+            if (current_error_handler != null) {
+                return current_error_handler.handleError(display, event);
+            } else {
+                return SAVED_XERROR_HANDLER(display, event);
+            }
+        } catch (Throwable z) {
+            log.fine("Error in GlobalErrorHandler", z);
+        }
+        return 0;
+    }
+
+    private static void XSync() {
+        SunToolkit.awtLock();
+        try {
+            XlibWrapper.XSync(display, 0);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- a/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -61,7 +61,7 @@
                         }
                         __executed = true;
                         if (errorHandler != null) {
-                            XToolkit.WITH_XERROR_HANDLER(errorHandler);
+                            XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
                         }
                         Native.putLong(children_ptr, 0);
                         int status =
@@ -72,7 +72,7 @@
                                 children_ptr,
                                 nchildren_ptr                   );
                         if (errorHandler != null) {
-                            XToolkit.RESTORE_XERROR_HANDLER();
+                            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
                         }
                         return status;
                 } finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -128,7 +128,6 @@
             initIDs();
             setBackingStoreType();
         }
-        noisyAwtHandler = AccessController.doPrivileged(new GetBooleanAction("sun.awt.noisyerrorhandler"));
     }
 
     /*
@@ -137,78 +136,6 @@
      */
     static native long getTrayIconDisplayTimeout();
 
-    //---- ERROR HANDLER CODE ----//
-
-    /*
-     * Error handler at the moment of XToolkit initialization
-     */
-    private static long saved_error_handler;
-
-    /*
-     * XErrorEvent being handled
-     */
-    static volatile XErrorEvent saved_error;
-
-    /*
-     * Current error handler or null if no error handler is set
-     */
-    private static XErrorHandler current_error_handler;
-
-    /*
-     * Value of sun.awt.noisyerrorhandler system property
-     */
-    private static boolean noisyAwtHandler;
-
-    public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
-        saved_error = null;
-        current_error_handler = handler;
-    }
-
-    public static void RESTORE_XERROR_HANDLER() {
-        // wait until all requests are processed by the X server
-        // and only then uninstall the error handler
-        XSync();
-        current_error_handler = null;
-    }
-
-    // Should be called under LOCK
-    public static int SAVED_ERROR_HANDLER(long display, XErrorEvent error) {
-        if (saved_error_handler != 0) {
-            // Default XErrorHandler may just terminate the process. Don't call it.
-            // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
-        }
-        if (log.isLoggable(PlatformLogger.FINE)) {
-            log.fine("Unhandled XErrorEvent: " +
-                     "id=" + error.get_resourceid() + ", " +
-                     "serial=" + error.get_serial() + ", " +
-                     "ec=" + error.get_error_code() + ", " +
-                     "rc=" + error.get_request_code() + ", " +
-                     "mc=" + error.get_minor_code());
-        }
-        return 0;
-    }
-
-    // Called from the native code when an error occurs
-    private static int globalErrorHandler(long display, long event_ptr) {
-        if (noisyAwtHandler) {
-            XlibWrapper.PrintXErrorEvent(display, event_ptr);
-        }
-        XErrorEvent event = new XErrorEvent(event_ptr);
-        saved_error = event;
-        try {
-            if (current_error_handler != null) {
-                return current_error_handler.handleError(display, event);
-            } else {
-                return SAVED_ERROR_HANDLER(display, event);
-            }
-        } catch (Throwable z) {
-            log.fine("Error in GlobalErrorHandler", z);
-        }
-        return 0;
-    }
-
-    //---- END OF ERROR HANDLER CODE ----//
-
     private native static void initIDs();
     native static void waitForEvents(long nextTaskTime);
     static Thread toolkitThread;
@@ -306,8 +233,6 @@
             //set system property if not yet assigned
             System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled);
 
-            saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
-
             // Detect display mode changes
             XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask);
             XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() {
--- a/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -68,7 +68,7 @@
                         }
                         __executed = true;
                         if (errorHandler != null) {
-                            XToolkit.WITH_XERROR_HANDLER(errorHandler);
+                            XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
                         }
                         int status =
                         XlibWrapper.XTranslateCoordinates(XToolkit.getDisplay(),
@@ -80,7 +80,7 @@
                                 dest_y_ptr,
                                 child_ptr                       );
                         if (errorHandler != null) {
-                            XToolkit.RESTORE_XERROR_HANDLER();
+                            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
                         }
                         return status;
                 } finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XWM.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -284,12 +284,12 @@
             winmgr_running = false;
             substruct.set_event_mask(XConstants.SubstructureRedirectMask);
 
-            XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
                                                 XToolkit.getDefaultRootWindow(),
                                                 XConstants.CWEventMask,
                                                 substruct.pData);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
             /*
              * If no WM is running then our selection for SubstructureRedirect
@@ -632,15 +632,16 @@
 
         XToolkit.awtLock();
         try {
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
             XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
                                          XA_ICEWM_WINOPTHINT.getAtom(),
                                          XA_ICEWM_WINOPTHINT.getAtom(),
                                          8, XConstants.PropModeReplace,
                                          new String(opt));
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 
-            if (XToolkit.saved_error != null && XToolkit.saved_error.get_error_code() != XConstants.Success) {
+            if ((XErrorHandlerUtil.saved_error != null) &&
+                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                 log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
                 return false;
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -151,8 +151,8 @@
             {
                 int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                 if ((status != 0) &&
-                    ((XToolkit.saved_error == null) ||
-                     (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+                    ((XErrorHandlerUtil.saved_error == null) ||
+                    (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
                 {
                     translated = new Point(xtc.get_dest_x(), xtc.get_dest_y());
                 }
@@ -345,13 +345,13 @@
         XWindowAttributes wattr = new XWindowAttributes();
         try
         {
-            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
             int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                           window, wattr.pData);
-            XToolkit.RESTORE_XERROR_HANDLER();
+            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
             if ((status != 0) &&
-                ((XToolkit.saved_error == null) ||
-                 (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+                ((XErrorHandlerUtil.saved_error == null) ||
+                (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
             {
                 return wattr.get_map_state();
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -996,7 +996,7 @@
             pw.println("\t\t\t}");
             pw.println("\t\t\t__executed = true;");
             pw.println("\t\t\tif (errorHandler != null) {");
-            pw.println("\t\t\t    XToolkit.WITH_XERROR_HANDLER(errorHandler);");
+            pw.println("\t\t\t    XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);");
             pw.println("\t\t\t}");
             iter = ft.getArguments().iterator();
             while (iter.hasNext()) {
@@ -1025,7 +1025,7 @@
             }
             pw.println("\t\t\t);");
             pw.println("\t\t\tif (errorHandler != null) {");
-            pw.println("\t\t\t    XToolkit.RESTORE_XERROR_HANDLER();");
+            pw.println("\t\t\t    XErrorHandlerUtil.RESTORE_XERROR_HANDLER();");
             pw.println("\t\t\t}");
             if (!ft.isVoid()) {
                 pw.println("\t\t\treturn status;");
--- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1023,6 +1023,13 @@
 
             // this is already supported in UnixPrintJob
             catList.add(Destination.class);
+
+            // It is unfortunate that CUPS doesn't provide a way to query
+            // if printer supports collation but since most printers
+            // now supports collation and that most OS has a way
+            // of setting it, it is a safe assumption to just always
+            // include SheetCollate as supported attribute.
+            catList.add(SheetCollate.class);
         }
 
         // With the assumption that  Chromaticity is equivalent to
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -758,6 +758,8 @@
     }
 
     XSetIOErrorHandler(xioerror_handler);
+    JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",
+        ptr_to_jlong(awt_display));
 
     /* set awt_numScreens, and whether or not we're using Xinerama */
     xineramaInit();
@@ -904,28 +906,12 @@
 
 static jint canUseShmExt = UNSET_MITSHM;
 static jint canUseShmExtPixmaps = UNSET_MITSHM;
-static jboolean xshmAttachFailed = JNI_FALSE;
-
-int J2DXErrHandler(Display *display, XErrorEvent *xerr) {
-    int ret = 0;
-    if (xerr->minor_code == X_ShmAttach) {
-        xshmAttachFailed = JNI_TRUE;
-    } else {
-        ret = (*xerror_saved_handler)(display, xerr);
-    }
-    return ret;
-}
-jboolean isXShmAttachFailed() {
-    return xshmAttachFailed;
-}
-void resetXShmAttachFailed() {
-    xshmAttachFailed = JNI_FALSE;
-}
 
 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
     XShmSegmentInfo shminfo;
     int XShmMajor, XShmMinor;
     int a, b, c;
+    jboolean xShmAttachResult;
 
     AWT_LOCK();
     if (canUseShmExt != UNSET_MITSHM) {
@@ -963,21 +949,14 @@
         }
         shminfo.readOnly = True;
 
-        resetXShmAttachFailed();
-        /**
-         * The J2DXErrHandler handler will set xshmAttachFailed
-         * to JNI_TRUE if any Shm error has occured.
-         */
-        EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
-                                 XShmAttach(awt_display, &shminfo));
-
+        xShmAttachResult = TryXShmAttach(env, awt_display, &shminfo);
         /**
          * Get rid of the id now to reduce chances of leaking
          * system resources.
          */
         shmctl(shminfo.shmid, IPC_RMID, 0);
 
-        if (isXShmAttachFailed() == JNI_FALSE) {
+        if (xShmAttachResult == JNI_TRUE) {
             canUseShmExt = CAN_USE_MITSHM;
             /* check if we can use shared pixmaps */
             XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
@@ -992,6 +971,23 @@
     }
     AWT_UNLOCK();
 }
+
+/*
+ * Must be called with the acquired AWT lock.
+ */
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo) {
+    jboolean errorOccurredFlag = JNI_FALSE;
+    jobject errorHandlerRef;
+
+    /*
+     * XShmAttachHandler will set its internal flag to JNI_TRUE, if any Shm error occurs.
+     */
+    EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$XShmAttachHandler",
+        "()Lsun/awt/X11/XErrorHandler$XShmAttachHandler;", JNI_TRUE,
+        errorHandlerRef, errorOccurredFlag,
+        XShmAttach(display, shminfo));
+    return errorOccurredFlag == JNI_FALSE ? JNI_TRUE : JNI_FALSE;
+}
 #endif /* MITSHM */
 
 /*
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -50,8 +50,7 @@
 extern int XShmQueryExtension();
 
 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps);
-void resetXShmAttachFailed();
-jboolean isXShmAttachFailed();
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo);
 
 #endif /* MITSHM */
 
--- a/jdk/src/solaris/native/sun/awt/awt_util.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -41,18 +41,6 @@
 
 #include "java_awt_event_MouseWheelEvent.h"
 
-/*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback.  While that
- * specialized handler is installed we save original handler here.
- */
-XErrorHandler xerror_saved_handler;
-
-/*
- * A place for error handler to report the error code.
- */
-unsigned char xerror_code;
-
 extern jint getModifiers(uint32_t state, jint button, jint keyCode);
 extern jint getButton(uint32_t button);
 
--- a/jdk/src/solaris/native/sun/awt/awt_util.h	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.h	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -29,42 +29,47 @@
 #ifndef HEADLESS
 #include "gdefs.h"
 
-#define WITH_XERROR_HANDLER(f) do {             \
-    XSync(awt_display, False);                  \
-    xerror_code = Success;                      \
-    xerror_saved_handler = XSetErrorHandler(f); \
-} while (0)
-
-/* Convenience macro for handlers to use */
-#define XERROR_SAVE(err) do {                   \
-    xerror_code = (err)->error_code;            \
-} while (0)
-
-#define RESTORE_XERROR_HANDLER do {             \
-    XSync(awt_display, False);                  \
-    XSetErrorHandler(xerror_saved_handler);     \
-} while (0)
-
-#define EXEC_WITH_XERROR_HANDLER(f, code) do {  \
-    WITH_XERROR_HANDLER(f);                     \
-    do {                                        \
-        code;                                   \
-    } while (0);                                \
-    RESTORE_XERROR_HANDLER;                     \
+/*
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject)
+ */
+#define WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature,                          \
+                            handlerHasFlag, handlerRef) do {                                      \
+    handlerRef = JNU_CallStaticMethodByName(env, NULL, handlerClassName, "getInstance",           \
+        getInstanceSignature).l;                                                                  \
+    if (handlerHasFlag == JNI_TRUE) {                                                             \
+        JNU_CallMethodByName(env, NULL, handlerRef, "setErrorOccurredFlag", "(Z)V", JNI_FALSE);   \
+    }                                                                                             \
+    JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "WITH_XERROR_HANDLER", \
+        "(Lsun/awt/X11/XErrorHandler;)V", handlerRef);                                            \
 } while (0)
 
 /*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback.  While that
- * specialized handler is installed we save original handler here.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*)
  */
-extern XErrorHandler xerror_saved_handler;
+#define RESTORE_XERROR_HANDLER(env) do {                                                          \
+    JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil",                        \
+        "RESTORE_XERROR_HANDLER", "()V");                                                         \
+} while (0)
 
 /*
- * A place for error handler to report the error code.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject, jboolean, No type - C expression)
  */
-extern unsigned char xerror_code;
-
+#define EXEC_WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag,     \
+                                 handlerRef, errorOccurredFlag, code) do {                        \
+    handlerRef = NULL;                                                                            \
+    WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag, handlerRef); \
+    do {                                                                                          \
+        code;                                                                                     \
+    } while (0);                                                                                  \
+    RESTORE_XERROR_HANDLER(env);                                                                  \
+    if (handlerHasFlag == JNI_TRUE) {                                                             \
+        errorOccurredFlag = JNU_CallMethodByName(env, NULL, handlerRef, "getErrorOccurredFlag",   \
+            "()Z").z;                                                                             \
+    }                                                                                             \
+} while (0)
 #endif /* !HEADLESS */
 
 #ifndef INTERSECTS
--- a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -48,8 +48,6 @@
 extern void
     OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
 
-jboolean surfaceCreationFailed = JNI_FALSE;
-
 #endif /* !HEADLESS */
 
 JNIEXPORT void JNICALL
@@ -349,18 +347,6 @@
     return JNI_TRUE;
 }
 
-static int
-GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)
-{
-    int ret = 0;
-    if (xerr->error_code == BadAlloc) {
-        surfaceCreationFailed = JNI_TRUE;
-    } else {
-        ret = (*xerror_saved_handler)(display, xerr);
-    }
-    return ret;
-}
-
 JNIEXPORT jboolean JNICALL
 Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer
     (JNIEnv *env, jobject glxsd,
@@ -376,6 +362,8 @@
     int attrlist[] = {GLX_PBUFFER_WIDTH, 0,
                       GLX_PBUFFER_HEIGHT, 0,
                       GLX_PRESERVED_CONTENTS, GL_FALSE, 0};
+    jboolean errorOccurredFlag;
+    jobject errorHandlerRef;
 
     J2dTraceLn3(J2D_TRACE_INFO,
                 "GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d",
@@ -403,12 +391,13 @@
     attrlist[1] = width;
     attrlist[3] = height;
 
-    surfaceCreationFailed = JNI_FALSE;
-    EXEC_WITH_XERROR_HANDLER(
-        GLXSD_BadAllocXErrHandler,
-        pbuffer = j2d_glXCreatePbuffer(awt_display,
-                                       glxinfo->fbconfig, attrlist));
-    if ((pbuffer == 0) || surfaceCreationFailed) {
+    errorOccurredFlag = JNI_FALSE;
+    EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$GLXBadAllocHandler",
+        "()Lsun/awt/X11/XErrorHandler$GLXBadAllocHandler;", JNI_TRUE,
+        errorHandlerRef, errorOccurredFlag,
+        pbuffer = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist));
+
+    if ((pbuffer == 0) || errorOccurredFlag) {
         J2dRlsTraceLn(J2D_TRACE_ERROR,
             "GLXSurfaceData_initPbuffer: could not create glx pbuffer");
         return JNI_FALSE;
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -65,7 +65,6 @@
 static DisposeFunc X11SD_Dispose;
 static GetPixmapBgFunc X11SD_GetPixmapWithBg;
 static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg;
-extern int J2DXErrHandler(Display *display, XErrorEvent *xerr);
 extern AwtGraphicsConfigDataPtr
     getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
@@ -521,6 +520,8 @@
 {
     XImage *img = NULL;
     XShmSegmentInfo *shminfo;
+    JNIEnv* env;
+    jboolean xShmAttachResult;
 
     shminfo = malloc(sizeof(XShmSegmentInfo));
     if (shminfo == NULL) {
@@ -559,9 +560,8 @@
 
     shminfo->readOnly = False;
 
-    resetXShmAttachFailed();
-    EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
-                             XShmAttach(awt_display, shminfo));
+    env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+    xShmAttachResult = TryXShmAttach(env, awt_display, shminfo);
 
     /*
      * Once the XSync round trip has finished then we
@@ -570,7 +570,7 @@
      */
     shmctl(shminfo->shmid, IPC_RMID, 0);
 
-    if (isXShmAttachFailed() == JNI_TRUE) {
+    if (xShmAttachResult == JNI_FALSE) {
         J2dRlsTraceLn1(J2D_TRACE_ERROR,
                        "X11SD_SetupSharedSegment XShmAttach has failed: %s",
                        strerror(errno));
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -1264,8 +1264,8 @@
     if (jvm != NULL) {
         env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
         if (env) {
-            return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XToolkit", "globalErrorHandler", "(JJ)I",
-                                              ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
+            return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil",
+                "globalErrorHandler", "(JJ)I", ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
         }
     }
     return 0;
--- a/jdk/src/windows/bin/cmdtoargs.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/bin/cmdtoargs.c	Wed Jul 05 18:57:52 2017 +0200
@@ -128,7 +128,9 @@
                 *wildcard = JNI_TRUE;
             }
             if (prev == '\\') {
-                *dest++ = prev;
+                for (i = 0 ; i < slashes ; i++) {
+                    *dest++ = prev;
+                }
             }
             *dest++ = ch;
             break;
@@ -184,7 +186,7 @@
         argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg));
         argv[nargs].arg = JLI_StringDup(arg);
         argv[nargs].has_wildcard = wildcard;
-
+        *arg = NULL;
         nargs++;
     } while (src != NULL);
 
@@ -602,6 +604,14 @@
     v->add("d", FALSE);
     vectors[i++] = v;
 
+    v= new Vector(argv[0], "\\\\?");
+    v->add("\\\\?", TRUE);
+    vectors[i++] = v;
+
+    v= new Vector(argv[0], "\\\\*");
+    v->add("\\\\*", TRUE);
+    vectors[i++] = v;
+
     dotest(vectors);
     printf("All tests pass [%d]\n", i);
     doexit(0);
--- a/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java	Wed Jul 05 18:57:52 2017 +0200
@@ -549,6 +549,8 @@
                 userx += xAdvance;
                 userpos.x += xAdvance;
                 deviceTransform.transform(userpos, devpos);
+                devx = devpos.x;
+                devy = devpos.y;
             }
         } else {
             super.drawString(str, x, y, font, frc, targetW);
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Wed Jul 05 18:57:52 2017 +0200
@@ -100,6 +100,7 @@
     public static final int ERROR_INVALID_LEVEL         = 124;
     public static final int ERROR_DIR_NOT_EMPTY         = 145;
     public static final int ERROR_ALREADY_EXISTS        = 183;
+    public static final int ERROR_MORE_DATA             = 234;
     public static final int ERROR_DIRECTORY             = 267;
     public static final int ERROR_NOTIFY_ENUM_DIR       = 1022;
     public static final int ERROR_NONE_MAPPED           = 1332;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Wed Jul 05 18:57:52 2017 +0200
@@ -973,19 +973,19 @@
      * HANDLE CreateIoCompletionPort (
      *   HANDLE FileHandle,
      *   HANDLE ExistingCompletionPort,
-     *   DWORD CompletionKey,
+     *   ULONG_PTR CompletionKey,
      *   DWORD NumberOfConcurrentThreads
      * )
      */
     static native long CreateIoCompletionPort(long fileHandle, long existingPort,
-        int completionKey) throws WindowsException;
+        long completionKey) throws WindowsException;
 
 
     /**
      * GetQueuedCompletionStatus(
      *   HANDLE CompletionPort,
      *   LPDWORD lpNumberOfBytesTransferred,
-     *   LPDWORD lpCompletionKey,
+     *   PULONG_PTR lpCompletionKey,
      *   LPOVERLAPPED *lpOverlapped,
      *   DWORD dwMilliseconds
      */
@@ -999,12 +999,12 @@
     static class CompletionStatus {
         private int error;
         private int bytesTransferred;
-        private int completionKey;
+        private long completionKey;
         private CompletionStatus() { }
 
         int error() { return error; }
         int bytesTransferred() { return bytesTransferred; }
-        int completionKey() { return completionKey; }
+        long completionKey() { return completionKey; }
     }
     private static native void GetQueuedCompletionStatus0(long completionPort,
         CompletionStatus status) throws WindowsException;
@@ -1013,12 +1013,12 @@
      * PostQueuedCompletionStatus(
      *   HANDLE CompletionPort,
      *   DWORD dwNumberOfBytesTransferred,
-     *   DWORD dwCompletionKey,
+     *   ULONG_PTR dwCompletionKey,
      *   LPOVERLAPPED lpOverlapped
      * )
      */
     static native void PostQueuedCompletionStatus(long completionPort,
-        int completionKey) throws WindowsException;
+        long completionKey) throws WindowsException;
 
     /**
      * ReadDirectoryChangesW(
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 18:57:52 2017 +0200
@@ -41,6 +41,7 @@
 class WindowsWatchService
     extends AbstractWatchService
 {
+    private final static int WAKEUP_COMPLETION_KEY = 0;
     private final Unsafe unsafe = Unsafe.getUnsafe();
 
     // background thread to service I/O completion port
@@ -83,7 +84,7 @@
      */
     private class WindowsWatchKey extends AbstractWatchKey {
         // file key (used to detect existing registrations)
-        private FileKey fileKey;
+        private final FileKey fileKey;
 
         // handle to directory
         private volatile long handle = INVALID_HANDLE_VALUE;
@@ -223,8 +224,7 @@
             FileKey other = (FileKey)obj;
             if (this.volSerialNumber != other.volSerialNumber) return false;
             if (this.fileIndexHigh != other.fileIndexHigh) return false;
-            if (this.fileIndexLow != other.fileIndexLow) return false;
-            return true;
+            return this.fileIndexLow == other.fileIndexLow;
         }
     }
 
@@ -268,6 +268,7 @@
         private static final short OFFSETOF_FILENAME        = 12;
 
         // size of per-directory buffer for events (FIXME - make this configurable)
+        // Need to be less than 4*16384 = 65536. DWORD align.
         private static final int CHANGES_BUFFER_SIZE    = 16 * 1024;
 
         private final WindowsFileSystem fs;
@@ -275,27 +276,28 @@
         private final long port;
 
         // maps completion key to WatchKey
-        private final Map<Integer,WindowsWatchKey> int2key;
+        private final Map<Integer,WindowsWatchKey> ck2key;
 
         // maps file key to WatchKey
         private final Map<FileKey,WindowsWatchKey> fk2key;
 
         // unique completion key for each directory
+        // native completion key capacity is 64 bits on Win64.
         private int lastCompletionKey;
 
         Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) {
             this.fs = fs;
             this.watcher = watcher;
             this.port = port;
-            this.int2key = new HashMap<Integer,WindowsWatchKey>();
-            this.fk2key = new HashMap<FileKey,WindowsWatchKey>();
+            this.ck2key = new HashMap<>();
+            this.fk2key = new HashMap<>();
             this.lastCompletionKey = 0;
         }
 
         @Override
         void wakeup() throws IOException {
             try {
-                PostQueuedCompletionStatus(port, 0);
+                PostQueuedCompletionStatus(port, WAKEUP_COMPLETION_KEY);
             } catch (WindowsException x) {
                 throw new IOException(x.getMessage());
             }
@@ -322,7 +324,6 @@
             for (WatchEvent.Modifier modifier: modifiers) {
                 if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
                     watchSubtree = true;
-                    continue;
                 } else {
                     if (modifier == null)
                         return new NullPointerException();
@@ -333,7 +334,7 @@
             }
 
             // open directory
-            long handle = -1L;
+            long handle;
             try {
                 handle = CreateFile(dir.getPathForWin32Calls(),
                                     FILE_LIST_DIRECTORY,
@@ -347,7 +348,7 @@
             boolean registered = false;
             try {
                 // read attributes and check file is a directory
-                WindowsFileAttributes attrs = null;
+                WindowsFileAttributes attrs;
                 try {
                     attrs = WindowsFileAttributes.readAttributes(handle);
                 } catch (WindowsException x) {
@@ -370,9 +371,10 @@
                     return existing;
                 }
 
-                // unique completion key (skip 0)
+                // Can overflow the int type capacity.
+                // Skip WAKEUP_COMPLETION_KEY value.
                 int completionKey = ++lastCompletionKey;
-                if (completionKey == 0)
+                if (completionKey == WAKEUP_COMPLETION_KEY)
                     completionKey = ++lastCompletionKey;
 
                 // associate handle with completion port
@@ -418,13 +420,13 @@
                     // 1. remove mapping from old completion key to existing watch key
                     // 2. release existing key's resources (handle/buffer)
                     // 3. re-initialize key with new handle/buffer
-                    int2key.remove(existing.completionKey());
+                    ck2key.remove(existing.completionKey());
                     existing.releaseResources();
                     watchKey = existing.init(handle, events, watchSubtree, buffer,
                         countAddress, overlappedAddress, completionKey);
                 }
                 // map completion map to watch key
-                int2key.put(completionKey, watchKey);
+                ck2key.put(completionKey, watchKey);
 
                 registered = true;
                 return watchKey;
@@ -440,7 +442,7 @@
             WindowsWatchKey key = (WindowsWatchKey)obj;
             if (key.isValid()) {
                 fk2key.remove(key.fileKey());
-                int2key.remove(key.completionKey());
+                ck2key.remove(key.completionKey());
                 key.invalidate();
             }
         }
@@ -449,11 +451,11 @@
         @Override
         void implCloseAll() {
             // cancel all keys
-            for (Map.Entry<Integer,WindowsWatchKey> entry: int2key.entrySet()) {
+            for (Map.Entry<Integer, WindowsWatchKey> entry: ck2key.entrySet()) {
                 entry.getValue().invalidate();
             }
             fk2key.clear();
-            int2key.clear();
+            ck2key.clear();
 
             // close I/O completion port
             CloseHandle(port);
@@ -517,7 +519,7 @@
         @Override
         public void run() {
             for (;;) {
-                CompletionStatus info = null;
+                CompletionStatus info;
                 try {
                     info = GetQueuedCompletionStatus(port);
                 } catch (WindowsException x) {
@@ -527,7 +529,7 @@
                 }
 
                 // wakeup
-                if (info.completionKey() == 0) {
+                if (info.completionKey() == WAKEUP_COMPLETION_KEY) {
                     boolean shutdown = processRequests();
                     if (shutdown) {
                         return;
@@ -536,7 +538,7 @@
                 }
 
                 // map completionKey to get WatchKey
-                WindowsWatchKey key = int2key.get(info.completionKey());
+                WindowsWatchKey key = ck2key.get((int)info.completionKey());
                 if (key == null) {
                     // We get here when a registration is changed. In that case
                     // the directory is closed which causes an event with the
@@ -544,38 +546,44 @@
                     continue;
                 }
 
-                // ReadDirectoryChangesW failed
-                if (info.error() != 0) {
+                boolean criticalError = false;
+                int errorCode = info.error();
+                int messageSize = info.bytesTransferred();
+                if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
                     // buffer overflow
-                    if (info.error() == ERROR_NOTIFY_ENUM_DIR) {
-                        key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
-                    } else {
-                        // other error so cancel key
-                        implCancelKey(key);
-                        key.signal();
-                    }
-                    continue;
-                }
+                    key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
+                } else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
+                    // ReadDirectoryChangesW failed
+                    criticalError = true;
+                } else {
+                    // ERROR_MORE_DATA is a warning about incomplite
+                    // data transfer over TCP/UDP stack. For the case
+                    // [messageSize] is zero in the most of cases.
 
-                // process the events
-                if (info.bytesTransferred() > 0) {
-                    processEvents(key, info.bytesTransferred());
-                } else {
-                    // insufficient buffer size
-                    key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
-                }
+                    if (messageSize > 0) {
+                        // process non-empty events.
+                        processEvents(key, messageSize);
+                    } else if (errorCode == 0) {
+                        // insufficient buffer size
+                        // not described, but can happen.
+                        key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
+                    }
 
-                // start read for next batch of changes
-                try {
-                    ReadDirectoryChangesW(key.handle(),
-                                          key.buffer().address(),
-                                          CHANGES_BUFFER_SIZE,
-                                          key.watchSubtree(),
-                                          ALL_FILE_NOTIFY_EVENTS,
-                                          key.countAddress(),
-                                          key.overlappedAddress());
-                } catch (WindowsException x) {
-                    // no choice but to cancel key
+                    // start read for next batch of changes
+                    try {
+                        ReadDirectoryChangesW(key.handle(),
+                                              key.buffer().address(),
+                                              CHANGES_BUFFER_SIZE,
+                                              key.watchSubtree(),
+                                              ALL_FILE_NOTIFY_EVENTS,
+                                              key.countAddress(),
+                                              key.overlappedAddress());
+                    } catch (WindowsException x) {
+                        // no choice but to cancel key
+                        criticalError = true;
+                    }
+                }
+                if (criticalError) {
                     implCancelKey(key);
                     key.signal();
                 }
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Wed Jul 05 18:57:52 2017 +0200
@@ -80,42 +80,24 @@
         } else {
             ktab.processArgs(args);
         }
-        try {
+        ktab.table = KeyTab.getInstance(ktab.name);
+        if (ktab.table.isMissing() && ktab.action != 'a') {
             if (ktab.name == null) {
-                //  ktab.admin = new KeyTabAdmin();    // use the default keytab.
-                ktab.table = KeyTab.getInstance();
-                if (ktab.table == null) {
-                    if (ktab.action == 'a') {
-                        ktab.table = KeyTab.create();
-                    } else {
-                        System.out.println("No default key table exists.");
-                        System.exit(-1);
-                    }
-                }
+                System.out.println("No default key table exists.");
             } else {
-                if ((ktab.action != 'a') &&
-                    !(new File(ktab.name)).exists()) {
-                    System.out.println("Key table " +
-                                ktab.name + " does not exist.");
-                    System.exit(-1);
-                } else {
-                    ktab.table = KeyTab.getInstance(ktab.name);
-                }
-                if (ktab.table == null) {
-                    if (ktab.action == 'a') {
-                        ktab.table = KeyTab.create(ktab.name);
-                    } else {
-                        System.out.println("The format of key table " +
-                                ktab.name + " is incorrect.");
-                        System.exit(-1);
-                    }
-                }
+                System.out.println("Key table " +
+                        ktab.name + " does not exist.");
             }
-        } catch (RealmException e) {
-            System.err.println("Error loading key table.");
             System.exit(-1);
-        } catch (IOException e) {
-            System.err.println("Error loading key table.");
+        }
+        if (!ktab.table.isValid()) {
+            if (ktab.name == null) {
+                System.out.println("The format of the default key table " +
+                        " is incorrect.");
+            } else {
+                System.out.println("The format of key table " +
+                        ktab.name + " is incorrect.");
+            }
             System.exit(-1);
         }
         switch (ktab.action) {
--- a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -199,7 +199,7 @@
 
 /**
  * If the given attributes are the attributes of a reparse point, then
- * read and return the attributes of the final target.
+ * read and return the attributes of the special cases.
  */
 DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
 {
@@ -213,6 +213,28 @@
     return a;
 }
 
+/**
+ * Take special cases into account when retrieving the attributes
+ * of path
+ */
+DWORD getFinalAttributes(WCHAR *path)
+{
+    DWORD attr = INVALID_FILE_ATTRIBUTES;
+
+    WIN32_FILE_ATTRIBUTE_DATA wfad;
+    WIN32_FIND_DATAW wfd;
+    HANDLE h;
+
+    if (GetFileAttributesExW(path, GetFileExInfoStandard, &wfad)) {
+        attr = getFinalAttributesIfReparsePoint(path, wfad.dwFileAttributes);
+    } else if (GetLastError() == ERROR_SHARING_VIOLATION &&
+               (h = FindFirstFileW(path, &wfd)) != INVALID_HANDLE_VALUE) {
+        attr = getFinalAttributesIfReparsePoint(path, wfd.dwFileAttributes);
+        CloseHandle(h);
+    }
+    return attr;
+}
+
 JNIEXPORT jstring JNICALL
 Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
                                            jstring pathname)
@@ -337,38 +359,21 @@
 Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
                                                   jobject file)
 {
-
     jint rv = 0;
     jint pathlen;
 
-    /* both pagefile.sys and hiberfil.sys have length 12 */
-#define SPECIALFILE_NAMELEN 12
-
     WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
-    WIN32_FILE_ATTRIBUTE_DATA wfad;
     if (pathbuf == NULL)
         return rv;
     if (!isReservedDeviceNameW(pathbuf)) {
-        if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
-            DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
-            if (a != INVALID_FILE_ATTRIBUTES) {
-                rv = (java_io_FileSystem_BA_EXISTS
-                    | ((a & FILE_ATTRIBUTE_DIRECTORY)
-                        ? java_io_FileSystem_BA_DIRECTORY
-                        : java_io_FileSystem_BA_REGULAR)
-                    | ((a & FILE_ATTRIBUTE_HIDDEN)
-                        ? java_io_FileSystem_BA_HIDDEN : 0));
-            }
-        } else { /* pagefile.sys is a special case */
-            if (GetLastError() == ERROR_SHARING_VIOLATION) {
-                rv = java_io_FileSystem_BA_EXISTS;
-                if ((pathlen = (jint)wcslen(pathbuf)) >= SPECIALFILE_NAMELEN &&
-                    (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
-                              L"pagefile.sys") == 0) ||
-                    (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
-                              L"hiberfil.sys") == 0))
-                  rv |= java_io_FileSystem_BA_REGULAR;
-            }
+        DWORD a = getFinalAttributes(pathbuf);
+        if (a != INVALID_FILE_ATTRIBUTES) {
+            rv = (java_io_FileSystem_BA_EXISTS
+                | ((a & FILE_ATTRIBUTE_DIRECTORY)
+                    ? java_io_FileSystem_BA_DIRECTORY
+                    : java_io_FileSystem_BA_REGULAR)
+                | ((a & FILE_ATTRIBUTE_HIDDEN)
+                    ? java_io_FileSystem_BA_HIDDEN : 0));
         }
     }
     free(pathbuf);
--- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Wed Jul 05 18:57:52 2017 +0200
@@ -162,7 +162,7 @@
     }
     completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
     completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
-    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
+    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
 
     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
     if (clazz == NULL) {
@@ -1169,12 +1169,11 @@
 
 JNIEXPORT jlong JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
-    jlong fileHandle, jlong existingPort, jint completionKey)
+    jlong fileHandle, jlong existingPort, jlong completionKey)
 {
-    ULONG_PTR ck = completionKey;
     HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
                                          (HANDLE)jlong_to_ptr(existingPort),
-                                         ck,
+                                         (ULONG_PTR)completionKey,
                                          0);
     if (port == NULL) {
         throwWindowsException(env, GetLastError());
@@ -1203,21 +1202,20 @@
         (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
         (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
             (jint)bytesTransferred);
-        (*env)->SetIntField(env, obj, completionStatus_completionKey,
-            (jint)completionKey);
-
+        (*env)->SetLongField(env, obj, completionStatus_completionKey,
+            (jlong)completionKey);
     }
 }
 
 JNIEXPORT void JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
-    jlong completionPort, jint completionKey)
+    jlong completionPort, jlong completionKey)
 {
     BOOL res;
 
     res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
                                      (DWORD)0,  /* dwNumberOfBytesTransferred */
-                                     (DWORD)completionKey,
+                                     (ULONG_PTR)completionKey,
                                      NULL);  /* lpOverlapped */
     if (res == 0) {
         throwWindowsException(env, GetLastError());
@@ -1232,7 +1230,17 @@
     BOOL res;
     BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
 
-    ((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL;
+    /* 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));
+
     res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
                                 (LPVOID)jlong_to_ptr(bufferAddress),
                                 (DWORD)bufferLength,
--- a/jdk/test/Makefile	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/Makefile	Wed Jul 05 18:57:52 2017 +0200
@@ -657,9 +657,12 @@
 # Multiple by 4 the timeout numbers
 JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
 JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
-# Boost the max memory for jtreg to avoid gc thrashing
+# Set the max memory for jtreg control vm
 JTREG_MEMORY_OPTION = -J-Xmx512m
 JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
+# Set the max memory for jtreg target test vms
+JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
+JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
 
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
--- a/jdk/test/ProblemList.txt	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 18:57:52 2017 +0200
@@ -137,15 +137,12 @@
 # 8008200
 java/lang/Class/asSubclass/BasicUnit.java                       generic-all
 
-# 8009552
-vm/verifier/TestStaticIF.java                                   generic-all
-
 ############################################################################
 
 # jdk_management
 
 # 8010897
-sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java	macosx-all 
+sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java	macosx-all
 
 ############################################################################
 
@@ -154,9 +151,6 @@
 # 6959636
 javax/management/loading/LibraryLoader/LibraryLoaderTest.java	windows-all
 
-# 8005472
-com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh windows-all
-
 ############################################################################
 
 # jdk_math
@@ -305,9 +299,6 @@
 # 7194428
 sun/security/mscapi/ShortRSAKey1024.sh                          windows-all
 
-# 8000897, vm crash
-sun/security/provider/DSA/TestAlgParameterGenerator.java        generic-all
-
 # 7144048, performance issue
 sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all
 
@@ -338,12 +329,9 @@
 sun/jvmstat/monitor/MonitoredVm/CR6672135.java                  generic-all
 
 # Tests take too long, on sparcs see 7143279
-tools/pack200/CommandLineTests.java                             solaris-all, macosx-all 
+tools/pack200/CommandLineTests.java                             solaris-all, macosx-all
 tools/pack200/Pack200Test.java                                  solaris-all, macosx-all
 
-# 7150569
-tools/launcher/UnicodeTest.java                                 macosx-all
-
 # 8007410
 tools/launcher/FXLauncherTest.java                              linux-all
 
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,47 +1,78 @@
 
-import java.nio.charset.Charset;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardWatchEventKinds;
-import java.nio.file.WatchEvent;
-import java.nio.file.WatchService;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.management.MBeanServerConnection;
 import javax.management.Notification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
 
 public class Client {
-    public static void main(String[] argv) throws Exception {
-        if (argv.length != 1) throw new IllegalArgumentException("Expecting exactly one jmx url argument");
+    public static void run(String url) throws Exception {
+        final int notifEmittedCnt = 10;
+        final CountDownLatch counter = new CountDownLatch(notifEmittedCnt);
+        final Set<Long> seqSet = Collections.synchronizedSet(new HashSet<Long>());
+        final AtomicBoolean duplNotification = new AtomicBoolean();
 
-        JMXServiceURL serverUrl = new JMXServiceURL(argv[0]);
+        JMXServiceURL serverUrl = new JMXServiceURL(url);
 
         ObjectName name = new ObjectName("test", "foo", "bar");
         JMXConnector jmxConnector = JMXConnectorFactory.connect(serverUrl);
         System.out.println("client connected");
         jmxConnector.addConnectionNotificationListener(new NotificationListener() {
+            @Override
             public void handleNotification(Notification notification, Object handback) {
-                System.err.println("no!" + notification);
+                System.out.println("connection notification: " + notification);
+                if (!seqSet.add(notification.getSequenceNumber())) {
+                    duplNotification.set(true);
+                }
+                if (notification.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
+                    long lostNotifs = ((Long)((JMXConnectionNotification)notification).getUserData()).longValue();
+                    for(int i=0;i<lostNotifs;i++) {
+                        counter.countDown();
+                    }
+                }
             }
         }, null, null);
         MBeanServerConnection jmxServer = jmxConnector.getMBeanServerConnection();
 
         jmxServer.addNotificationListener(name, new NotificationListener() {
+            @Override
             public void handleNotification(Notification notification, Object handback) {
-                System.out.println("client got:" + notification);
+                System.out.println("client got: " + notification);
+                if (!seqSet.add(notification.getSequenceNumber())) {
+                    duplNotification.set(true);
+                }
+                counter.countDown();
             }
         }, null, null);
 
-        for(int i=0;i<10;i++) {
-            System.out.println("client invoking foo");
+        System.out.println("client invoking foo (" + notifEmittedCnt + " times)");
+        for(int i=0;i<notifEmittedCnt;i++) {
+            System.out.print(".");
             jmxServer.invoke(name, "foo", new Object[]{}, new String[]{});
-            Thread.sleep(50);
         }
-
-        System.err.println("happy!");
+        System.out.println();
+        try {
+            System.out.println("waiting for " + notifEmittedCnt + " notifications to arrive");
+            if (!counter.await(30, TimeUnit.SECONDS)) {
+                throw new InterruptedException();
+            }
+            if (duplNotification.get()) {
+                System.out.println("ERROR: received duplicated notifications");
+                throw new Error("received duplicated notifications");
+            }
+            System.out.println("\nshutting down client");
+        } catch (InterruptedException e) {
+            System.out.println("ERROR: notification processing thread interrupted");
+            throw new Error("notification thread interrupted unexpectedly");
+        }
     }
 }
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,11 +1,6 @@
+import java.io.File;
 import java.lang.management.ManagementFactory;
 import java.net.BindException;
-import java.nio.charset.Charset;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
 import java.rmi.registry.LocateRegistry;
 import java.rmi.server.ExportException;
 import java.util.Random;
@@ -16,7 +11,7 @@
 import javax.management.remote.JMXServiceURL;
 
 public class Server {
-    public static void main(String[] argv) throws Exception {
+    public static String start() throws Exception {
         int serverPort = 12345;
         ObjectName name = new ObjectName("test", "foo", "bar");
         MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
@@ -40,7 +35,7 @@
         JMXServiceURL serverUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + serverPort + "/test");
         JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(serverUrl, null, jmxServer);
         jmxConnector.start();
-        System.out.println(serverUrl);
-        System.err.println("server listening on " + serverUrl);
+
+        return serverUrl.toString();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,123 @@
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @summary Tests for the RMI unmarshalling errors not to cause silent failure.
+ * @author Jaroslav Bachorik
+ * @bug 6937053 8005472
+ *
+ * @run clean TestSerializationMismatch
+ * @run main TestSerializationMismatch
+ *
+ */
+public class TestSerializationMismatch {
+    static final String clientDir = "Client";
+    static final String serverDir = "Server";
+    static final String testSrc = System.getProperty("test.src");
+    static final String testSrcDir = testSrc != null ? testSrc : ".";
+    static final String testSrcClientDir = testSrcDir + File.separator + clientDir + File.separator;
+    static final String testSrcServerDir = testSrcDir + File.separator + serverDir + File.separator;
+    static final String testClasses = System.getProperty("test.classes");
+    static final String testClassesDir = testClasses != null ? testClasses : ".";
+    static final String testClassesClientDir = testClassesDir + File.separator + clientDir + File.separator;
+    static final String testClassesServerDir = testClassesDir + File.separator + serverDir + File.separator;
+
+    static final boolean debug = true;
+
+    public static void main(String[] args) throws Exception {
+        setup();
+
+        compileClient();
+        compileServer();
+
+        debug("starting server");
+        String url = startServer();
+        debug("server started and listening on " + url);
+        debug("starting client");
+        startClient(url);
+    }
+
+    static void setup() {
+        debug("setting up the output dirs");
+        cleanupDir(testClassesClientDir);
+        cleanupDir(testClassesServerDir);
+    }
+
+    static void cleanupDir(String path) {
+        debug("cleaning " + path);
+        File dir = new File(path);
+        if (dir.exists()) {
+            for(File src : dir.listFiles()) {
+                boolean rslt = src.delete();
+                debug((rslt == false ? "not " : "") + "deleted " + src);
+            }
+        } else {
+            dir.mkdirs();
+        }
+    }
+
+    static void compileClient() {
+        debug("compiling client");
+        compile("-d" , testClassesClientDir,
+            "-sourcepath", testSrcClientDir,
+            testSrcClientDir + "Client.java",
+            testSrcClientDir + "ConfigKey.java",
+            testSrcClientDir + "TestNotification.java");
+    }
+
+    static void compileServer() {
+        debug("compiling server");
+        compile("-d" , testClassesServerDir,
+            "-sourcepath", testSrcServerDir,
+            testSrcServerDir + "Server.java",
+            testSrcServerDir + "ConfigKey.java",
+            testSrcServerDir + "TestNotification.java",
+            testSrcServerDir + "Ste.java",
+            testSrcServerDir + "SteMBean.java");
+    }
+
+    static String startServer() throws Exception {
+        ClassLoader serverCL = customCL(testClassesServerDir);
+
+        Class serverClz = serverCL.loadClass("Server");
+        Method startMethod = serverClz.getMethod("start");
+        return (String)startMethod.invoke(null);
+    }
+
+    static void startClient(String url) throws Exception {
+        ClassLoader clientCL = customCL(testClassesClientDir);
+
+        Thread.currentThread().setContextClassLoader(clientCL);
+        Class clientClz = clientCL.loadClass("Client");
+        Method runMethod = clientClz.getMethod("run", String.class);
+        runMethod.invoke(null, url);
+    }
+
+    static ClassLoader customCL(String classDir) throws Exception {
+        return new URLClassLoader(
+            new URL[]{
+                new File(classDir).toURI().toURL()
+            },
+            TestSerializationMismatch.class.getClassLoader()
+        );
+    }
+
+    static void debug(Object message) {
+        if (debug) {
+            System.out.println(message);
+        }
+    }
+
+    /* run javac <args> */
+    static void compile(String... args) {
+        debug("Running: javac " + Arrays.toString(args));
+        if (com.sun.tools.javac.Main.compile(args) != 0) {
+            throw new RuntimeException("javac failed: args=" + Arrays.toString(args));
+        }
+    }
+}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# 
-# @test
-# @summary  Tests for the RMI unmarshalling errors not to cause silent failure.
-# @author   Jaroslav Bachorik
-# @bug      6937053
-#
-# @run shell TestSerializationMismatch.sh
-#
-
-#set -x
-
-#Set appropriate jdk
-#
-
-if [ ! -z "${TESTJAVA}" ] ; then
-     jdk="$TESTJAVA"
-else
-     echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test."
-     exit 1
-fi
-
-SERVER_TESTCLASSES=$TESTCLASSES/Server
-CLIENT_TESTCLASSES=$TESTCLASSES/Client
-
-URL_PATH=$SERVER_TESTCLASSES/jmxurl
-
-rm $URL_PATH
-
-mkdir -p $SERVER_TESTCLASSES
-mkdir -p $CLIENT_TESTCLASSES
-
-$TESTJAVA/bin/javac -d $CLIENT_TESTCLASSES $TESTSRC/Client/ConfigKey.java $TESTSRC/Client/TestNotification.java $TESTSRC/Client/Client.java
-$TESTJAVA/bin/javac -d $SERVER_TESTCLASSES $TESTSRC/Server/ConfigKey.java $TESTSRC/Server/TestNotification.java $TESTSRC/Server/SteMBean.java $TESTSRC/Server/Ste.java $TESTSRC/Server/Server.java
-
-startServer()
-{
-   ($TESTJAVA/bin/java -classpath $SERVER_TESTCLASSES Server) 1>$URL_PATH &
-   SERVER_PID=$!
-}
-
-runClient() 
-{
-   while true
-   do
-      [ -f $URL_PATH ] && break
-      sleep 2
-   done
-   read JMXURL < $URL_PATH
-   
-   HAS_ERRORS=`($TESTJAVA/bin/java -classpath $CLIENT_TESTCLASSES Client $JMXURL) 2>&1 | grep -i "SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.UnmarshalException"`
-}
-
-startServer
-
-runClient
-
-sleep 1 # wait for notifications to arrive
-
-kill "$SERVER_PID"
-
-if [ -z "$HAS_ERRORS" ]
-then
-  echo "Test PASSED"
-  exit 0
-fi
-
-echo "Test FAILED"
-echo $HAS_ERRORS 1>&2
-exit 1
-
--- a/jdk/test/java/awt/WMSpecificTests/Metacity/FullscreenDialogModality.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/awt/WMSpecificTests/Metacity/FullscreenDialogModality.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,6 +25,8 @@
  * @test
  * @bug 8012586
  * @summary verify that modal dialog will appeared above fullscreen window under Metacity WM.
+ * @library ../../regtesthelpers
+ * @build Util
  * @run main FullscreenDialogModality
  * @run main/othervm FullscreenDialogModality
  * @author vkravets
--- a/jdk/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -37,11 +37,12 @@
 
 public class TranslucentJAppletTest {
 
+    private static volatile GraphicsConfiguration graphicsConfig = null;
     private static JFrame frame;
     private static volatile boolean paintComponentCalled = false;
 
     private static void initAndShowGUI() {
-        frame = new JFrame();
+        frame = new JFrame(graphicsConfig);
         JApplet applet = new JApplet();
         applet.setBackground(new Color(0, 0, 0, 0));
         JPanel panel = new JPanel() {
@@ -66,6 +67,27 @@
     {
         sun.awt.SunToolkit tk = (sun.awt.SunToolkit)Toolkit.getDefaultToolkit();
 
+        final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        for (GraphicsDevice gd : ge.getScreenDevices()) {
+            if (gd.isWindowTranslucencySupported(
+                        GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT))
+            {
+                for (GraphicsConfiguration gc : gd.getConfigurations()) {
+                    if (gc.isTranslucencyCapable()) {
+                        graphicsConfig = gc;
+                        break;
+                    }
+                }
+            }
+            if (graphicsConfig != null) {
+                break;
+            }
+        }
+        if (graphicsConfig == null) {
+            System.out.println("The system does not support translucency. Consider the test passed.");
+            return;
+        }
+
         Robot r = new Robot();
         Color color1 = r.getPixelColor(100, 100); // (0, 0) in frame coordinates
 
--- a/jdk/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6362683
+ * @bug 6362683 8012381
  * @summary Collation should work.
  * @run main/manual Collate2DPrintingTest
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PrintLatinCJKTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 800535
+ * @summary JDK7 Printing: CJK and Latin Text in string overlap
+ * @run main/manual=yesno PrintLatinCJKTest
+ */
+
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JTextArea;
+
+import javax.swing.SwingUtilities;
+
+public class PrintLatinCJKTest implements Printable, ActionListener {
+
+    static PrintLatinCJKTest testInstance = new PrintLatinCJKTest();
+    private PageFormat pf;
+
+    static String info =
+       "You need a printer for this test. If you have none, let "+
+       "the test pass. If there is a printer, press Print, send "+
+       "the output to the printer, and examine it. It should have "+
+       "text looking like this : \u4e00\u4e01\u4e02\u4e03\u4e04English.";
+
+    public static void showFrame() {
+         JFrame f = new JFrame();
+         JTextArea jta = new JTextArea(info, 4, 30);
+         jta.setLineWrap(true);
+         jta.setWrapStyleWord(true);
+         f.add("Center", jta);
+         JButton b = new JButton("Print");
+         b.addActionListener(testInstance);
+         f.add("South", b);
+         f.pack();
+         f.setVisible(true);
+    }
+
+    public int print(Graphics g, PageFormat pf, int pageIndex)
+                         throws PrinterException {
+
+        if (pageIndex > 0) {
+            return Printable.NO_SUCH_PAGE;
+        }
+        g.translate((int) pf.getImageableX(), (int) pf.getImageableY());
+        g.setFont(new Font("Dialog", Font.PLAIN, 36));
+        g.drawString("\u4e00\u4e01\u4e02\u4e03\u4e04English", 20, 100);
+        return Printable.PAGE_EXISTS;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        try {
+            PrinterJob job = PrinterJob.getPrinterJob();
+            job.setPrintable(testInstance);
+            if (job.printDialog()) {
+                job.print();
+            }
+        } catch (PrinterException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                showFrame();
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/Test8013416.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8013416
+ * @summary Tests public synthetic methods
+ * @author Sergey Malenkov
+ */
+
+import java.beans.DefaultPersistenceDelegate;
+import java.beans.Encoder;
+import java.beans.Expression;
+import java.beans.Statement;
+import java.beans.XMLEncoder;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class Test8013416 extends AbstractTest {
+    public static void main(String[] args) {
+        new Test8013416().test(true);
+    }
+
+    protected Object getObject() {
+        Public<String, String> map = new Public<String, String>();
+        map.put(" pz1 ", " pz2 ");
+        map.put(" pz3 ", " pz4 ");
+        return map;
+    }
+
+    @Override
+    protected void initialize(XMLEncoder encoder) {
+        super.initialize(encoder);
+        encoder.setPersistenceDelegate(Public.class, new PublicPersistenceDelegate());
+    }
+
+    private static final class PublicPersistenceDelegate extends DefaultPersistenceDelegate {
+        @Override
+        protected Expression instantiate(Object oldInstance, Encoder out) {
+            return new Expression(oldInstance, oldInstance.getClass(), "new", null);
+        }
+
+        @Override
+        protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
+            super.initialize(type, oldInstance, newInstance, out);
+
+            Public<String, String> map = (Public) oldInstance;
+            for (Entry<String, String> entry : map.getAll()) {
+                String[] args = {entry.getKey(), entry.getValue()};
+                out.writeStatement(new Statement(oldInstance, "put", args));
+            }
+        }
+    }
+
+    public static final class Public<K, V> extends Private<K, V> {
+    }
+
+    private static class Private<K, V> {
+        private HashMap<K, V> map = new HashMap<K, V>();
+
+        public void put(K key, V value) {
+            this.map.put(key, value);
+        }
+
+        public Set<Entry<K, V>> getAll() {
+            return this.map.entrySet();
+        }
+    }
+}
--- a/jdk/test/java/io/File/IsHidden.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/io/File/IsHidden.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -46,6 +46,11 @@
         Files.getFileAttributeView(f.toPath(), DosFileAttributeView.class).setHidden(value);
     }
 
+    private static void checkHidden(File f) {
+        if (!f.isHidden())
+            throw new RuntimeException(f + " should be hidden");
+    }
+
     private static void testWin32() throws Exception {
         File f = new File(dir, "test");
         f.deleteOnExit();
@@ -58,6 +63,11 @@
         }
         ck(".foo", false);
         ck("foo", false);
+
+        File pagefile = new File("C:\\pagefile.sys");
+        File hiberfil = new File("C:\\hiberfil.sys");
+        if (pagefile.exists()) checkHidden(pagefile);
+        if (hiberfil.exists()) checkHidden(hiberfil);
     }
 
     private static void testUnix() throws Exception {
--- a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6402006 7030573
+ * @bug 6402006 7030573 8011136
  * @summary Test if available returns correct value when reading
  *          a large file.
  */
@@ -61,9 +61,12 @@
             remaining -= skipBytes(fis, bigSkip, remaining);
             remaining -= skipBytes(fis, 10L, remaining);
             remaining -= skipBytes(fis, bigSkip, remaining);
-            if (fis.available() != (int) remaining) {
-                 throw new RuntimeException("available() returns "
-                     + fis.available() + " but expected " + remaining);
+            int expected = (remaining >= Integer.MAX_VALUE)
+                           ? Integer.MAX_VALUE
+                           : (remaining > 0 ? (int) remaining : 0);
+            if (fis.available() != expected) {
+                throw new RuntimeException("available() returns "
+                        + fis.available() + " but expected " + expected);
             }
         } finally {
             file.delete();
@@ -77,19 +80,18 @@
         long skip = is.skip(toSkip);
         if (skip != toSkip) {
             throw new RuntimeException("skip() returns " + skip
-                + " but expected " + toSkip);
+                                       + " but expected " + toSkip);
         }
         long remaining = avail - skip;
-        int expected = remaining >= Integer.MAX_VALUE
-                           ? Integer.MAX_VALUE
-                           : (int) remaining;
+        int expected = (remaining >= Integer.MAX_VALUE)
+                       ? Integer.MAX_VALUE
+                       : (remaining > 0 ? (int) remaining : 0);
 
-        System.out.println("Skipped " + skip + " bytes "
-            + " available() returns " + expected +
-            " remaining=" + remaining);
+        System.out.println("Skipped " + skip + " bytes, available() returns "
+                           + expected + ", remaining " + remaining);
         if (is.available() != expected) {
             throw new RuntimeException("available() returns "
-                + is.available() + " but expected " + expected);
+                    + is.available() + " but expected " + expected);
         }
         return skip;
     }
--- a/jdk/test/java/io/FileInputStream/NegativeAvailable.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/NegativeAvailable.java	Wed Jul 05 18:57:52 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8010837
+ * @bug 8010837 8011136
  * @summary Test if available returns correct value when skipping beyond
  *          the end of a file.
  * @author Dan Xu
@@ -42,6 +42,7 @@
     public static void main(String[] args) throws IOException {
         final int SIZE = 10;
         final int SKIP = 5;
+        final int NEGATIVE_SKIP = -5;
 
         // Create a temporary file with size of 10 bytes.
         Path tmp = Files.createTempFile(null, null);
@@ -56,12 +57,15 @@
         try (FileInputStream fis = new FileInputStream(tempFile)) {
             if (tempFile.length() != SIZE) {
                 throw new RuntimeException("unexpected file size = "
-                    + tempFile.length());
+                                           + tempFile.length());
             }
             long space = skipBytes(fis, SKIP, SIZE);
+            space = skipBytes(fis, NEGATIVE_SKIP, space);
             space = skipBytes(fis, SKIP, space);
             space = skipBytes(fis, SKIP, space);
             space = skipBytes(fis, SKIP, space);
+            space = skipBytes(fis, NEGATIVE_SKIP, space);
+            space = skipBytes(fis, NEGATIVE_SKIP, space);
         }
         Files.deleteIfExists(tmp);
     }
@@ -74,17 +78,18 @@
         long skip = fis.skip(toSkip);
         if (skip != toSkip) {
             throw new RuntimeException("skip() returns " + skip
-                + " but expected " + toSkip);
+                                       + " but expected " + toSkip);
         }
-        long remaining = space - toSkip;
+        long newSpace = space - toSkip;
+        long remaining = newSpace > 0 ? newSpace : 0;
         int avail = fis.available();
         if (avail != remaining) {
             throw new RuntimeException("available() returns " + avail
-                + " but expected " + remaining);
+                                       + " but expected " + remaining);
         }
 
         System.out.println("Skipped " + skip + " bytes "
-            + " available() returns " + avail);
-        return remaining;
+                           + " available() returns " + avail);
+        return newSpace;
     }
 }
--- a/jdk/test/java/io/pathNames/General.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/io/pathNames/General.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -40,7 +40,7 @@
 
 
     /* Generate a filename unique to this run */
-    private static String gensym() {
+    protected static String gensym() {
         return "x." + ++gensymCounter;
     }
 
@@ -127,9 +127,9 @@
         }
         for (int i = 0; i < dl.length; i++) {
             File f = new File(d, dl[i]);
-            if (f.isDirectory() && f.canRead()) {
+            if (f.isDirectory()) {
                 String[] dl2 = f.list();
-                if (dl2.length >= 250) {
+                if (dl2 == null || dl2.length >= 250) {
                     /* Heuristic to avoid scanning huge directories */
                     continue;
                 }
@@ -277,8 +277,8 @@
     {
         check(ans, ask + slash);
         checkNames(depth, create,
-                   ans.endsWith(File.separator) ? ans : ans + File.separator,
-                   ask + slash);
+                   ans,
+                   ask);
     }
 
 
@@ -308,13 +308,16 @@
                                   String ans, String ask)
         throws Exception
     {
+        ans = ans.endsWith(File.separator) ? ans : ans + File.separator;
+        ask = ask.endsWith(File.separator) ? ask : ask + File.separator;
+
         int d = depth - 1;
         File f = new File(ans);
         String n;
 
         /* Normal name */
         if (f.exists()) {
-            if (f.isDirectory() && f.canRead()) {
+            if (f.isDirectory() && f.list() != null) {
                 if ((n = findSomeFile(ans, create)) != null)
                     checkSlashes(d, create, ans + n, ask + n);
                 if ((n = findSomeDir(ans, create)) != null)
--- a/jdk/test/java/io/pathNames/GeneralWin32.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/io/pathNames/GeneralWin32.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520
+   @bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520 8009258
    @summary General exhaustive test of win32 pathname handling
    @author Mark Reinhold
 
@@ -31,8 +31,6 @@
  */
 
 import java.io.*;
-import java.util.*;
-
 
 public class GeneralWin32 extends General {
 
@@ -49,25 +47,29 @@
     private static final String EXISTENT_UNC_SHARE = "pcdist";
     private static final String NONEXISTENT_UNC_HOST = "non-existent-unc-host";
     private static final String NONEXISTENT_UNC_SHARE = "bogus-share";
-
+    private static final int DEPTH = 2;
+    private static String baseDir = null;
+    private static String userDir = null;
 
     /* Pathnames relative to working directory */
 
-    private static void checkCaseLookup(String ud) throws IOException {
+    private static void checkCaseLookup() throws IOException {
         /* Use long names here to avoid 8.3 format, which Samba servers often
            force to lowercase */
-        File d = new File("XyZzY0123", "FOO_bar_BAZ");
-        File f = new File(d, "GLORPified");
+        String relative = baseDir.substring(userDir.length() + 1);
+        File d1 = new File(relative, "XyZzY0123");
+        File d2 = new File(d1, "FOO_bar_BAZ");
+        File f = new File(d2, "GLORPified");
         if (!f.exists()) {
-            if (!d.exists()) {
-                if (!d.mkdirs()) {
-                    throw new RuntimeException("Can't create directory " + d);
+            if (!d2.exists()) {
+                if (!d2.mkdirs()) {
+                    throw new RuntimeException("Can't create directory " + d2);
                 }
             }
             OutputStream o = new FileOutputStream(f);
             o.close();
         }
-        File f2 = new File(d.getParent(), "mumble"); /* For later ud tests */
+        File f2 = new File(d2.getParent(), "mumble"); /* For later ud tests */
         if (!f2.exists()) {
             OutputStream o = new FileOutputStream(f2);
             o.close();
@@ -75,11 +77,11 @@
 
         /* Computing the canonical path of a Win32 file should expose the true
            case of filenames, rather than just using the input case */
-        File y = new File(ud, f.getPath());
+        File y = new File(userDir, f.getPath());
         String ans = y.getPath();
-        check(ans, "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
-        check(ans, "xyzzy0123\\foo_bar_baz\\glorpified");
-        check(ans, "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
+        check(ans, relative + "\\" + "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
+        check(ans, relative + "\\" + "xyzzy0123\\foo_bar_baz\\glorpified");
+        check(ans, relative + "\\" + "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
     }
 
     private static void checkWild(File f) throws Exception {
@@ -91,18 +93,18 @@
         throw new Exception("Wildcard path not rejected: " + f);
     }
 
-    private static void checkWildCards(String ud) throws Exception {
-        File d = new File(ud).getCanonicalFile();
+    private static void checkWildCards() throws Exception {
+        File d = new File(baseDir).getCanonicalFile();
         checkWild(new File(d, "*.*"));
         checkWild(new File(d, "*.???"));
         checkWild(new File(new File(d, "*.*"), "foo"));
     }
 
     private static void checkRelativePaths() throws Exception {
-        String ud = System.getProperty("user.dir").replace('/', '\\');
-        checkCaseLookup(ud);
-        checkWildCards(ud);
-        checkNames(3, true, ud + "\\", "");
+        checkCaseLookup();
+        checkWildCards();
+        String relative = baseDir.substring(userDir.length() + 1);
+        checkNames(3, true, baseDir.toString(), relative);
     }
 
 
@@ -134,7 +136,8 @@
         String ans = exists ? df.getAbsolutePath() : d;
         if (!ans.endsWith("\\"))
             ans = ans + "\\";
-        checkNames(depth, false, ans, d);
+        String relative = baseDir.substring(userDir.length() + 1);
+        checkNames(depth, false, ans + relative, d + relative);
     }
 
     private static void checkDrivePaths() throws Exception {
@@ -149,7 +152,7 @@
         String s = ("\\\\" + NONEXISTENT_UNC_HOST
                     + "\\" + NONEXISTENT_UNC_SHARE);
         ensureNon(s);
-        checkSlashes(2, false, s, s);
+        checkSlashes(DEPTH, false, s, s);
 
         s = "\\\\" + EXISTENT_UNC_HOST + "\\" + EXISTENT_UNC_SHARE;
         if (!(new File(s)).exists()) {
@@ -158,7 +161,7 @@
             return;
         }
 
-        checkSlashes(2, false, s, s);
+        checkSlashes(DEPTH, false, s, s);
     }
 
 
@@ -168,9 +171,33 @@
             return;
         }
         if (args.length > 0) debug = true;
+        userDir = System.getProperty("user.dir");
+        baseDir = initTestData(6);
         checkRelativePaths();
         checkDrivePaths();
         checkUncPaths();
     }
 
+    private static String initTestData(int maxDepth) throws IOException {
+        File parent = new File(System.getProperty("user.dir"));
+        String baseDir = null;
+        maxDepth = maxDepth < DEPTH + 2 ? DEPTH + 2 : maxDepth;
+        for (int i = 0; i < maxDepth; i ++) {
+            File dir1 = new File(parent, gensym());
+            dir1.mkdir();
+            if (i != 0) {
+                File dir2 = new File(parent, gensym());
+                dir2.mkdir();
+                File f1 = new File(parent, gensym());
+                f1.createNewFile();
+                File f2 = new File(parent, gensym());
+                f2.createNewFile();
+            }
+            if (i == DEPTH + 1) {
+                baseDir = dir1.getAbsolutePath();
+            }
+            parent = dir1;
+        }
+        return baseDir;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/StringContentEqualsBug.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8014477
+ * @summary test String.contentEquals(StringBuffer)
+ */
+public class StringContentEqualsBug {
+
+    static abstract class Task extends Thread {
+        volatile StringBuffer sb;
+        volatile Exception exception;
+
+        Task(StringBuffer sb) {
+            this.sb = sb;
+        }
+
+        @Override
+        public void run() {
+            try {
+                StringBuffer sb;
+                while ((sb = this.sb) != null) {
+                    doWith(sb);
+                }
+            }
+            catch (Exception e) {
+                exception = e;
+            }
+        }
+
+        protected abstract void doWith(StringBuffer sb);
+    }
+
+    static class Tester extends Task {
+        Tester(StringBuffer sb) {
+            super(sb);
+        }
+
+        @Override
+        protected void doWith(StringBuffer sb) {
+            "AA".contentEquals(sb);
+        }
+    }
+
+    static class Disturber extends Task {
+        Disturber(StringBuffer sb) {
+            super(sb);
+        }
+
+        @Override
+        protected void doWith(StringBuffer sb) {
+            sb.setLength(0);
+            sb.trimToSize();
+            sb.append("AA");
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        StringBuffer sb = new StringBuffer();
+        Task[] tasks = new Task[3];
+        (tasks[0] = new Tester(sb)).start();
+        for (int i = 1; i < tasks.length; i++) {
+            (tasks[i] = new Disturber(sb)).start();
+        }
+
+        try
+        {
+            // wait at most 5 seconds for any of the threads to throw exception
+            for (int i = 0; i < 20; i++) {
+                for (Task task : tasks) {
+                    if (task.exception != null) {
+                        throw task.exception;
+                    }
+                }
+                Thread.sleep(250L);
+            }
+        }
+        finally {
+            for (Task task : tasks) {
+                task.sb = null;
+                task.join();
+            }
+        }
+    }
+}
--- a/jdk/test/java/lang/StringBuffer/ToStringCache.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/lang/StringBuffer/ToStringCache.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 8013395
+ * @bug 8013395 8014814
  * @summary Test StringBuffer.toString caching
  */
 
@@ -199,6 +199,28 @@
         b = sb.toString();
         checkUnequal(a, b);
 
+        // Extra checks that append(null) works correctly
+
+        sb.append((String)null);
+        b = sb.toString();
+        checkUnequal(a, b);
+        a = b;
+
+        sb.append((StringBuffer)null);
+        b = sb.toString();
+        checkUnequal(a, b);
+        a = b;
+
+        sb.append((StringBuilder)null);
+        b = sb.toString();
+        checkUnequal(a, b);
+        a = b;
+
+        sb.append((CharSequence)null);
+        b = sb.toString();
+        checkUnequal(a, b);
+        a = b;
+
         // non-mutating methods
 
         // Reset to known value
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,13 +22,18 @@
  */
 
 /*
+ * The -XX:MarkSweepAlwaysCompactCount=1 argument below makes sure serial gc
+ * compacts the heap at every full gc so that the usage is correctly updated.
+ */
+
+/*
  * @test
  * @bug     4892507
  * @summary Basic Test for MemoryPool.resetPeakUsage()
  * @author  Mandy Chung
  *
  * @build ResetPeakMemoryUsage MemoryUtil
- * @run main/othervm -XX:+UseSerialGC -Xmn8m ResetPeakMemoryUsage
+ * @run main/othervm -XX:+UseSerialGC -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
  * @run main/othervm -XX:+UseConcMarkSweepGC -Xmn8m ResetPeakMemoryUsage
  * @run main/othervm -XX:+UseParallelGC -Xmn8m ResetPeakMemoryUsage
  * @run main/othervm -XX:+UseG1GC -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 7038914
+ * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
+ * @run main/othervm -Xmx16M -XX:-UseTLAB OOMEInReferenceHandler
+ * @author peter.levart@gmail.com
+ */
+
+import java.lang.ref.*;
+
+public class OOMEInReferenceHandler {
+     static Object[] fillHeap() {
+         Object[] first = null, last = null;
+         int size = 1 << 20;
+         while (size > 0) {
+             try {
+                 Object[] array = new Object[size];
+                 if (first == null) {
+                     first = array;
+                 } else {
+                     last[0] = array;
+                 }
+                 last = array;
+             } catch (OutOfMemoryError oome) {
+                 size = size >>> 1;
+             }
+         }
+         return first;
+     }
+
+     public static void main(String[] args) throws Exception {
+         // preinitialize the InterruptedException class so that the reference handler
+         // does not die due to OOME when loading the class if it is the first use
+         InterruptedException ie = new InterruptedException("dummy");
+
+         ThreadGroup tg = Thread.currentThread().getThreadGroup();
+         for (
+             ThreadGroup tgn = tg;
+             tgn != null;
+             tg = tgn, tgn = tg.getParent()
+             )
+             ;
+
+         Thread[] threads = new Thread[tg.activeCount()];
+         Thread referenceHandlerThread = null;
+         int n = tg.enumerate(threads);
+         for (int i = 0; i < n; i++) {
+             if ("Reference Handler".equals(threads[i].getName())) {
+                 referenceHandlerThread = threads[i];
+             }
+         }
+
+         if (referenceHandlerThread == null) {
+             throw new IllegalStateException("Couldn't find Reference Handler thread.");
+         }
+
+         ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
+         Object referent = new Object();
+         WeakReference<Object> weakRef = new WeakReference<>(referent, refQueue);
+
+         Object waste = fillHeap();
+
+         referenceHandlerThread.interrupt();
+
+         // allow referenceHandlerThread some time to throw OOME
+         Thread.sleep(500L);
+
+         // release waste & referent
+         waste = null;
+         referent = null;
+
+         // wait at most 10 seconds for success or failure
+         for (int i = 0; i < 20; i++) {
+             if (refQueue.poll() != null) {
+                 // Reference Handler thread still working -> success
+                 return;
+             }
+             System.gc();
+             Thread.sleep(500L); // wait a little to allow GC to do it's work before allocating objects
+             if (!referenceHandlerThread.isAlive()) {
+                 // Reference Handler thread died -> failure
+                 throw new Exception("Reference Handler thread died.");
+             }
+         }
+
+         // no sure answer after 10 seconds
+         throw new IllegalStateException("Reference Handler thread stuck.");
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/FaultyFileSystem.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,499 @@
+/*
+ * 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.IOException;
+import java.net.URI;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.AccessMode;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * A {@code FileSystem} that helps testing by trigger exception throwing based on filenames.
+ */
+class FaultyFileSystem extends FileSystem {
+    final Path root;
+    final boolean removeRootAfterClose;
+    final FileSystem delegate;
+    boolean isOpen;
+
+    FaultyFileSystem(Path root) throws IOException {
+        if (root == null) {
+            root = Files.createTempDirectory("faultyFS");
+            removeRootAfterClose = true;
+        } else {
+            if (! Files.isDirectory(root)) {
+                throw new IllegalArgumentException("must be a directory.");
+            }
+            removeRootAfterClose = false;
+        }
+        this.root = root;
+        delegate = root.getFileSystem();
+        isOpen = true;
+    }
+
+    private static Path unwrap(Path p) {
+        return PassThroughFileSystem.unwrap(p);
+    }
+
+    Path getRoot() {
+        return new PassThroughFileSystem.PassThroughPath(this, root);
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (isOpen) {
+            if (removeRootAfterClose) {
+                TestUtil.removeAll(root);
+            }
+            isOpen = false;
+        }
+    }
+
+    @Override
+    public FileSystemProvider provider() {
+        return FaultyFSProvider.getInstance();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return isOpen;
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return delegate.isReadOnly();
+    }
+
+    @Override
+    public String getSeparator() {
+        return delegate.getSeparator();
+    }
+
+    private <T> Iterable<T> SoleIterable(final T element) {
+        return new Iterable<T>() {
+            @Override
+            public Iterator<T> iterator() {
+                return new Iterator<T>() {
+                    private T soleElement = element;
+
+                    @Override
+                    public boolean hasNext() {
+                        return soleElement != null;
+                    }
+
+                    @Override
+                    public T next() {
+                        try {
+                            return soleElement;
+                        } finally {
+                            soleElement = null;
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Iterable<Path> getRootDirectories() {
+        return SoleIterable(getRoot());
+    }
+
+    @Override
+    public Iterable<FileStore> getFileStores() {
+        FileStore store;
+        try {
+            store = Files.getFileStore(root);
+        } catch (IOException ioe) {
+            store = null;
+        }
+        return SoleIterable(store);
+    }
+
+    @Override
+    public Set<String> supportedFileAttributeViews() {
+        // assume that unwrapped objects aren't exposed
+        return delegate.supportedFileAttributeViews();
+    }
+
+    @Override
+    public Path getPath(String first, String... more) {
+        return new PassThroughFileSystem.PassThroughPath(this, delegate.getPath(first, more));
+    }
+
+    @Override
+    public PathMatcher getPathMatcher(String syntaxAndPattern) {
+        final PathMatcher matcher = delegate.getPathMatcher(syntaxAndPattern);
+        return new PathMatcher() {
+            @Override
+            public boolean matches(Path path) {
+                return matcher.matches(unwrap(path));
+            }
+        };
+    }
+
+    @Override
+    public UserPrincipalLookupService getUserPrincipalLookupService() {
+        // assume that unwrapped objects aren't exposed
+        return delegate.getUserPrincipalLookupService();
+    }
+
+    @Override
+    public WatchService newWatchService() throws IOException {
+        // to keep it simple
+        throw new UnsupportedOperationException();
+    }
+
+    static class FaultyException extends IOException {
+        FaultyException() {
+            super("fault triggered.");
+        }
+    }
+
+    static class FaultyFSProvider extends FileSystemProvider {
+        private static final String SCHEME = "faulty";
+        private static volatile FaultyFileSystem delegate;
+        private static FaultyFSProvider INSTANCE = new FaultyFSProvider();
+        private boolean enabled;
+
+        private FaultyFSProvider() {}
+
+        public static FaultyFSProvider getInstance() {
+            return INSTANCE;
+        }
+
+        public void setFaultyMode(boolean enable) {
+            enabled = enable;
+        }
+
+        private void triggerEx(String filename, String... names) throws IOException {
+            if (! enabled) {
+                return;
+            }
+
+            if (filename.equals("SecurityException")) {
+                throw new SecurityException("FaultyFS", new FaultyException());
+            }
+
+            if (filename.equals("IOException")) {
+                throw new FaultyException();
+            }
+
+            for (String name: names) {
+                if (name.equals(filename)) {
+                    throw new FaultyException();
+                }
+            }
+        }
+
+        private void triggerEx(Path path, String... names) throws IOException {
+            triggerEx(path.getFileName().toString(), names);
+        }
+
+        @Override
+        public String getScheme() {
+            return SCHEME;
+        }
+
+        private void checkScheme(URI uri) {
+            if (!uri.getScheme().equalsIgnoreCase(SCHEME))
+                throw new IllegalArgumentException();
+        }
+
+        private void checkUri(URI uri) {
+            checkScheme(uri);
+            if (!uri.getSchemeSpecificPart().equals("///"))
+                throw new IllegalArgumentException();
+        }
+
+        @Override
+        public FileSystem newFileSystem(Path fakeRoot, Map<String,?> env)
+            throws IOException
+        {
+            if (env != null && env.keySet().contains("IOException")) {
+                triggerEx("IOException");
+            }
+
+            synchronized (FaultyFSProvider.class) {
+                if (delegate != null && delegate.isOpen())
+                    throw new FileSystemAlreadyExistsException();
+                FaultyFileSystem result = new FaultyFileSystem(fakeRoot);
+                delegate = result;
+                return result;
+            }
+        }
+
+        @Override
+        public FileSystem newFileSystem(URI uri, Map<String,?> env)
+            throws IOException
+        {
+            if (env != null && env.keySet().contains("IOException")) {
+                triggerEx("IOException");
+            }
+
+            checkUri(uri);
+            synchronized (FaultyFSProvider.class) {
+                if (delegate != null && delegate.isOpen())
+                    throw new FileSystemAlreadyExistsException();
+                FaultyFileSystem result = new FaultyFileSystem(null);
+                delegate = result;
+                return result;
+            }
+        }
+
+        @Override
+        public FileSystem getFileSystem(URI uri) {
+            checkUri(uri);
+            FileSystem result = delegate;
+            if (result == null)
+                throw new FileSystemNotFoundException();
+            return result;
+        }
+
+        @Override
+        public Path getPath(URI uri) {
+            checkScheme(uri);
+            if (delegate == null)
+                throw new FileSystemNotFoundException();
+
+            // only allow absolute path
+            String path = uri.getSchemeSpecificPart();
+            if (! path.startsWith("///")) {
+                throw new IllegalArgumentException();
+            }
+            return new PassThroughFileSystem.PassThroughPath(delegate, delegate.root.resolve(path.substring(3)));
+        }
+
+        @Override
+        public void setAttribute(Path file, String attribute, Object value, LinkOption... options)
+            throws IOException
+        {
+            triggerEx(file, "setAttribute");
+            Files.setAttribute(unwrap(file), attribute, value, options);
+        }
+
+        @Override
+        public Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options)
+            throws IOException
+        {
+            triggerEx(file, "readAttributes");
+            return Files.readAttributes(unwrap(file), attributes, options);
+        }
+
+        @Override
+        public <V extends FileAttributeView> V getFileAttributeView(Path file,
+                                                                    Class<V> type,
+                                                                    LinkOption... options)
+        {
+            return Files.getFileAttributeView(unwrap(file), type, options);
+        }
+
+        @Override
+        public <A extends BasicFileAttributes> A readAttributes(Path file,
+                                                                Class<A> type,
+                                                                LinkOption... options)
+            throws IOException
+        {
+            triggerEx(file, "readAttributes");
+            return Files.readAttributes(unwrap(file), type, options);
+        }
+
+        @Override
+        public void delete(Path file) throws IOException {
+            triggerEx(file, "delete");
+            Files.delete(unwrap(file));
+        }
+
+        @Override
+        public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
+            throws IOException
+        {
+            triggerEx(target, "createSymbolicLink");
+            Files.createSymbolicLink(unwrap(link), unwrap(target), attrs);
+        }
+
+        @Override
+        public void createLink(Path link, Path existing) throws IOException {
+            triggerEx(existing, "createLink");
+            Files.createLink(unwrap(link), unwrap(existing));
+        }
+
+        @Override
+        public Path readSymbolicLink(Path link) throws IOException {
+            Path target = Files.readSymbolicLink(unwrap(link));
+            triggerEx(target, "readSymbolicLink");
+            return new PassThroughFileSystem.PassThroughPath(delegate, target);
+        }
+
+
+        @Override
+        public void copy(Path source, Path target, CopyOption... options) throws IOException {
+            triggerEx(source, "copy");
+            Files.copy(unwrap(source), unwrap(target), options);
+        }
+
+        @Override
+        public void move(Path source, Path target, CopyOption... options) throws IOException {
+            triggerEx(source, "move");
+            Files.move(unwrap(source), unwrap(target), options);
+        }
+
+        private DirectoryStream<Path> wrap(final DirectoryStream<Path> stream) {
+            return new DirectoryStream<Path>() {
+                @Override
+                public Iterator<Path> iterator() {
+                    final Iterator<Path> itr = stream.iterator();
+                    return new Iterator<Path>() {
+                        private Path next = null;
+                        @Override
+                        public boolean hasNext() {
+                            if (next == null) {
+                                if (itr.hasNext()) {
+                                    next = itr.next();
+                                } else {
+                                    return false;
+                                }
+                            }
+                            if (next != null) {
+                                try {
+                                    triggerEx(next, "DirectoryIteratorException");
+                                } catch (IOException ioe) {
+                                    throw new DirectoryIteratorException(ioe);
+                                } catch (SecurityException se) {
+                                    // ??? Does DS throw SecurityException during iteration?
+                                    next = null;
+                                    return hasNext();
+                                }
+                            }
+                            return (next != null);
+                        }
+                        @Override
+                        public Path next() {
+                            try {
+                                if (next != null || hasNext()) {
+                                    return new PassThroughFileSystem.PassThroughPath(delegate, next);
+                                } else {
+                                    throw new NoSuchElementException();
+                                }
+                            } finally {
+                                next = null;
+                            }
+                        }
+
+                        @Override
+                        public void remove() {
+                            itr.remove();
+                        }
+                    };
+                }
+                @Override
+                public void close() throws IOException {
+                    stream.close();
+                }
+            };
+        }
+
+        @Override
+        public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
+            throws IOException
+        {
+            triggerEx(dir, "newDirectoryStream");
+            return wrap(Files.newDirectoryStream(unwrap(dir), filter));
+        }
+
+        @Override
+        public void createDirectory(Path dir, FileAttribute<?>... attrs)
+            throws IOException
+        {
+            triggerEx(dir, "createDirectory");
+            Files.createDirectory(unwrap(dir), attrs);
+        }
+
+        @Override
+        public SeekableByteChannel newByteChannel(Path file,
+                                                  Set<? extends OpenOption> options,
+                                                  FileAttribute<?>... attrs)
+            throws IOException
+        {
+            triggerEx(file, "newByteChannel");
+            return Files.newByteChannel(unwrap(file), options, attrs);
+        }
+
+
+        @Override
+        public boolean isHidden(Path file) throws IOException {
+            triggerEx(file, "isHidden");
+            return Files.isHidden(unwrap(file));
+        }
+
+        @Override
+        public FileStore getFileStore(Path file) throws IOException {
+            triggerEx(file, "getFileStore");
+            return Files.getFileStore(unwrap(file));
+        }
+
+        @Override
+        public boolean isSameFile(Path file, Path other) throws IOException {
+            triggerEx(file, "isSameFile");
+            return Files.isSameFile(unwrap(file), unwrap(other));
+        }
+
+        @Override
+        public void checkAccess(Path file, AccessMode... modes)
+            throws IOException
+        {
+            triggerEx(file, "checkAccess");
+            // hack
+            if (modes.length == 0) {
+                if (Files.exists(unwrap(file)))
+                    return;
+                else
+                    throw new NoSuchFileException(file.toString());
+            }
+            throw new RuntimeException("not implemented yet");
+        }
+    }
+}
--- a/jdk/test/java/nio/file/Files/PassThroughFileSystem.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/nio/file/Files/PassThroughFileSystem.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -304,7 +304,7 @@
         public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
             throws IOException
         {
-            return wrap(Files.newDirectoryStream(dir, filter));
+            return wrap(Files.newDirectoryStream(unwrap(dir), filter));
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/StreamTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,621 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8006884
+ * @summary Unit test for java.nio.file.Files
+ * @library ..
+ * @build PassThroughFileSystem FaultyFileSystem
+ * @run testng StreamTest
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.charset.Charset;
+import java.nio.charset.MalformedInputException;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemLoopException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Comparators;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.Collectors;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test(groups = "unit")
+public class StreamTest {
+    /**
+     * Default test folder
+     * testFolder - empty
+     *            - file
+     *            - dir - d1
+     *                  - f1
+     *                  - lnDir2 (../dir2)
+     *            - dir2
+     *            - linkDir (./dir)
+     *            - linkFile(./file)
+     */
+    static Path testFolder;
+    static boolean supportsLinks;
+    static Path[] level1;
+    static Path[] all;
+    static Path[] all_folowLinks;
+
+    @BeforeClass
+    void setupTestFolder() throws IOException {
+        testFolder = TestUtil.createTemporaryDirectory();
+        supportsLinks = TestUtil.supportsLinks(testFolder);
+        TreeSet<Path> set = new TreeSet<>();
+
+        // Level 1
+        Path empty = testFolder.resolve("empty");
+        Path file = testFolder.resolve("file");
+        Path dir = testFolder.resolve("dir");
+        Path dir2 = testFolder.resolve("dir2");
+        Files.createDirectory(empty);
+        Files.createFile(file);
+        Files.createDirectory(dir);
+        Files.createDirectory(dir2);
+        set.add(empty);
+        set.add(file);
+        set.add(dir);
+        set.add(dir2);
+        if (supportsLinks) {
+            Path tmp = testFolder.resolve("linkDir");
+            Files.createSymbolicLink(tmp, dir);
+            set.add(tmp);
+            tmp = testFolder.resolve("linkFile");
+            Files.createSymbolicLink(tmp, file);
+            set.add(tmp);
+        }
+        level1 = set.toArray(new Path[0]);
+
+        // Level 2
+        Path tmp = dir.resolve("d1");
+        Files.createDirectory(tmp);
+        set.add(tmp);
+        tmp = dir.resolve("f1");
+        Files.createFile(tmp);
+        set.add(tmp);
+        if (supportsLinks) {
+            tmp = dir.resolve("lnDir2");
+            Files.createSymbolicLink(tmp, dir2);
+            set.add(tmp);
+        }
+        // walk include starting folder
+        set.add(testFolder);
+        all = set.toArray(new Path[0]);
+
+        // Follow links
+        if (supportsLinks) {
+            tmp = testFolder.resolve("linkDir");
+            set.add(tmp.resolve("d1"));
+            set.add(tmp.resolve("f1"));
+            tmp = tmp.resolve("lnDir2");
+            set.add(tmp);
+        }
+        all_folowLinks = set.toArray(new Path[0]);
+    }
+
+    @AfterClass
+    void cleanupTestFolder() throws IOException {
+        TestUtil.removeAll(testFolder);
+    }
+
+    public void testBasic() {
+        try (CloseableStream<Path> s = Files.list(testFolder)) {
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            assertEquals(actual, level1);
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+
+        try (CloseableStream<Path> s = Files.list(testFolder.resolve("empty"))) {
+            int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
+            assertEquals(count, 0, "Expect empty stream.");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    public void testWalk() {
+        try (CloseableStream<Path> s = Files.walk(testFolder)) {
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            assertEquals(actual, all);
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    public void testWalkOneLevel() {
+        try (CloseableStream<Path> s = Files.walk(testFolder, 1)) {
+            Object[] actual = s.filter(path -> ! path.equals(testFolder))
+                               .sorted(Comparators.naturalOrder())
+                               .toArray();
+            assertEquals(actual, level1);
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    public void testWalkFollowLink() {
+        // If link is not supported, the directory structure won't have link.
+        // We still want to test the behavior with FOLLOW_LINKS option.
+        try (CloseableStream<Path> s = Files.walk(testFolder, FileVisitOption.FOLLOW_LINKS)) {
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            assertEquals(actual, all_folowLinks);
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    private void validateFileSystemLoopException(Path start, Path... causes) {
+        try (CloseableStream<Path> s = Files.walk(start, FileVisitOption.FOLLOW_LINKS)) {
+            try {
+                int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
+                fail("Should got FileSystemLoopException, but got " + count + "elements.");
+            } catch (UncheckedIOException uioe) {
+                IOException ioe = uioe.getCause();
+                if (ioe instanceof FileSystemLoopException) {
+                    FileSystemLoopException fsle = (FileSystemLoopException) ioe;
+                    boolean match = false;
+                    for (Path cause: causes) {
+                        if (fsle.getFile().equals(cause.toString())) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    assertTrue(match);
+                } else {
+                    fail("Unexpected UncheckedIOException cause " + ioe.toString());
+                }
+            }
+        } catch(IOException ex) {
+            fail("Unexpected IOException " + ex);
+        }
+    }
+
+    public void testWalkFollowLinkLoop() {
+        if (!supportsLinks) {
+            return;
+        }
+
+        // Loops.
+        try {
+            Path dir = testFolder.resolve("dir");
+            Path linkdir = testFolder.resolve("linkDir");
+            Path d1 = dir.resolve("d1");
+            Path cause = d1.resolve("lnSelf");
+            Files.createSymbolicLink(cause, d1);
+
+            // loop in descendant.
+            validateFileSystemLoopException(dir, cause);
+            // loop in self
+            validateFileSystemLoopException(d1, cause);
+            // start from other place via link
+            validateFileSystemLoopException(linkdir,
+                    linkdir.resolve(Paths.get("d1", "lnSelf")));
+            Files.delete(cause);
+
+            // loop to parent.
+            cause = d1.resolve("lnParent");
+            Files.createSymbolicLink(cause, dir);
+
+            // loop should be detected at test/dir/d1/lnParent/d1
+            validateFileSystemLoopException(d1, cause.resolve("d1"));
+            // loop should be detected at link
+            validateFileSystemLoopException(dir, cause);
+            // loop should be detected at test/linkdir/d1/lnParent
+            // which is test/dir we have visited via test/linkdir
+            validateFileSystemLoopException(linkdir,
+                    linkdir.resolve(Paths.get("d1", "lnParent")));
+            Files.delete(cause);
+
+            // cross loop
+            Path dir2 = testFolder.resolve("dir2");
+            cause = dir2.resolve("lnDir");
+            Files.createSymbolicLink(cause, dir);
+            validateFileSystemLoopException(dir,
+                    dir.resolve(Paths.get("lnDir2", "lnDir")));
+            validateFileSystemLoopException(dir2,
+                    dir2.resolve(Paths.get("lnDir", "lnDir2")));
+            validateFileSystemLoopException(linkdir,
+                    linkdir.resolve(Paths.get("lnDir2", "lnDir")));
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe);
+        }
+    }
+
+    private static class PathBiPredicate implements BiPredicate<Path, BasicFileAttributes> {
+        private final BiPredicate<Path, BasicFileAttributes> pred;
+        private final Set<Path> visited = new TreeSet<Path>();
+
+        PathBiPredicate(BiPredicate<Path, BasicFileAttributes> pred) {
+            this.pred = Objects.requireNonNull(pred);
+        }
+
+        public boolean test(Path path, BasicFileAttributes attrs) {
+            visited.add(path);
+            return pred.test(path, attrs);
+        }
+
+        public Path[] visited() {
+            return visited.toArray(new Path[0]);
+        }
+    }
+
+    public void testFind() throws IOException {
+        PathBiPredicate pred = new PathBiPredicate((path, attrs) -> true);
+
+        try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+            Set<Path> result = s.collect(Collectors.toCollection(TreeSet::new));
+            assertEquals(pred.visited(), all);
+            assertEquals(result.toArray(new Path[0]), pred.visited());
+        }
+
+        pred = new PathBiPredicate((path, attrs) -> attrs.isSymbolicLink());
+        try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+            s.forEach(path -> assertTrue(Files.isSymbolicLink(path)));
+            assertEquals(pred.visited(), all);
+        }
+
+        pred = new PathBiPredicate((path, attrs) ->
+            path.getFileName().toString().startsWith("e"));
+        try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+            s.forEach(path -> assertEquals(path.getFileName().toString(), "empty"));
+            assertEquals(pred.visited(), all);
+        }
+
+        pred = new PathBiPredicate((path, attrs) ->
+            path.getFileName().toString().startsWith("l") && attrs.isRegularFile());
+        try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+            s.forEach(path -> fail("Expect empty stream"));
+            assertEquals(pred.visited(), all);
+        }
+    }
+
+    // Test borrowed from BytesAndLines
+    public void testLines() throws IOException {
+        final Charset US_ASCII = Charset.forName("US-ASCII");
+        Path tmpfile = Files.createTempFile("blah", "txt");
+
+        try {
+            // zero lines
+            assertTrue(Files.size(tmpfile) == 0, "File should be empty");
+            try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+                assertEquals(s.mapToInt(l -> 1).reduce(0, Integer::sum), 0, "No line expected");
+            }
+
+            // one line
+            byte[] hi = { (byte)'h', (byte)'i' };
+            Files.write(tmpfile, hi);
+            try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+                List<String> lines = s.collect(Collectors.toList());
+                assertTrue(lines.size() == 1, "One line expected");
+                assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
+            }
+
+            // two lines using platform's line separator
+            List<String> expected = Arrays.asList("hi", "there");
+            Files.write(tmpfile, expected, US_ASCII);
+            assertTrue(Files.size(tmpfile) > 0, "File is empty");
+            try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+                List<String> lines = s.collect(Collectors.toList());
+                assertTrue(lines.equals(expected), "Unexpected lines");
+            }
+
+            // MalformedInputException
+            byte[] bad = { (byte)0xff, (byte)0xff };
+            Files.write(tmpfile, bad);
+            try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+                try {
+                    List<String> lines = s.collect(Collectors.toList());
+                    throw new RuntimeException("UncheckedIOException expected");
+                } catch (UncheckedIOException ex) {
+                    assertTrue(ex.getCause() instanceof MalformedInputException,
+                               "MalformedInputException expected");
+                }
+            }
+
+            // NullPointerException
+            try {
+                Files.lines(null, US_ASCII);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException ignore) { }
+            try {
+                Files.lines(tmpfile, null);
+                throw new RuntimeException("NullPointerException expected");
+            } catch (NullPointerException ignore) { }
+
+        } finally {
+            Files.delete(tmpfile);
+        }
+    }
+
+    public void testDirectoryIteratorException() throws IOException {
+        Path dir = testFolder.resolve("dir2");
+        Path trigger = dir.resolve("DirectoryIteratorException");
+        Files.createFile(trigger);
+        FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+        FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(dir, null);
+
+        try {
+            fsp.setFaultyMode(false);
+            Path fakeRoot = fs.getRoot();
+            try {
+                try (CloseableStream<Path> s = Files.list(fakeRoot)) {
+                    s.forEach(path -> assertEquals(path.getFileName().toString(), "DirectoryIteratorException"));
+                }
+            } catch (UncheckedIOException uioe) {
+                fail("Unexpected exception.");
+            }
+
+            fsp.setFaultyMode(true);
+            try {
+                try (DirectoryStream<Path> ds = Files.newDirectoryStream(fakeRoot)) {
+                    Iterator<Path> itor = ds.iterator();
+                    while (itor.hasNext()) {
+                        itor.next();
+                    }
+                }
+                fail("Shoule throw DirectoryIteratorException");
+            } catch (DirectoryIteratorException die) {
+            }
+
+            try {
+                try (CloseableStream<Path> s = Files.list(fakeRoot)) {
+                    s.forEach(path -> fail("should not get here"));
+                }
+            } catch (UncheckedIOException uioe) {
+                assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+            } catch (DirectoryIteratorException die) {
+                fail("Should have been converted into UncheckedIOException.");
+            }
+        } finally {
+            // Cleanup
+            if (fs != null) {
+                fs.close();
+            }
+            Files.delete(trigger);
+        }
+    }
+
+    public void testUncheckedIOException() throws IOException {
+        Path triggerFile = testFolder.resolve(Paths.get("dir2", "IOException"));
+        Files.createFile(triggerFile);
+        Path triggerDir = testFolder.resolve(Paths.get("empty", "IOException"));
+        Files.createDirectories(triggerDir);
+        Files.createFile(triggerDir.resolve("file"));
+        FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+        FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
+
+        try {
+            fsp.setFaultyMode(false);
+            Path fakeRoot = fs.getRoot();
+            try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+                // only one file
+                s.forEach(path -> assertEquals(path.getFileName().toString(), "IOException"));
+            }
+
+            try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                // ordered as depth-first
+                assertEquals(result, new String[] { "empty", "IOException", "file"});
+            }
+
+            fsp.setFaultyMode(true);
+            try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+                s.forEach(path -> fail("should have caused exception"));
+            } catch (UncheckedIOException uioe) {
+                assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+
+            try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to IOException");
+            } catch (UncheckedIOException uioe) {
+                assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+
+            try (CloseableStream<Path> s = Files.walk(
+                fakeRoot.resolve("empty").resolve("IOException")))
+            {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to IOException");
+            } catch (IOException ioe) {
+                assertTrue(ioe instanceof FaultyFileSystem.FaultyException);
+            } catch (UncheckedIOException ex) {
+                fail("Top level should be repored as is");
+            }
+         } finally {
+            // Cleanup
+            if (fs != null) {
+                fs.close();
+            }
+            Files.delete(triggerFile);
+            TestUtil.removeAll(triggerDir);
+        }
+    }
+
+    public void testSecurityException() throws IOException {
+        Path triggerFile = testFolder.resolve(Paths.get("dir", "SecurityException"));
+        Files.createFile(triggerFile);
+        Path sampleFile = testFolder.resolve(Paths.get("dir", "sample"));
+        Files.createFile(sampleFile);
+        Path triggerDir = testFolder.resolve(Paths.get("dir2", "SecurityException"));
+        Files.createDirectories(triggerDir);
+        Files.createFile(triggerDir.resolve("fileInSE"));
+        Path sample = testFolder.resolve(Paths.get("dir2", "file"));
+        Files.createFile(sample);
+        FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+        FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
+
+        try {
+            fsp.setFaultyMode(false);
+            Path fakeRoot = fs.getRoot();
+            // validate setting
+            try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "SecurityException", "sample" });
+            }
+
+            try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "dir2", "SecurityException", "fileInSE", "file" });
+            }
+
+            // execute test
+            fsp.setFaultyMode(true);
+            // ignore file cause SecurityException
+            try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "dir", "d1","f1", "lnDir2", "sample" });
+            }
+            // skip folder cause SecurityException
+            try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "dir2", "file" });
+            }
+
+            // list instead of walk
+            try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "sample" });
+            }
+            try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                assertEqualsNoOrder(result, new String[] { "file" });
+            }
+
+            // root cause SecurityException should be reported
+            try (CloseableStream<Path> s = Files.walk(
+                fakeRoot.resolve("dir2").resolve("SecurityException")))
+            {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to SecurityException");
+            } catch (SecurityException se) {
+                assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+
+            // Walk a file cause SecurityException, we should get SE
+            try (CloseableStream<Path> s = Files.walk(
+                fakeRoot.resolve("dir").resolve("SecurityException")))
+            {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to SecurityException");
+            } catch (SecurityException se) {
+                assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+
+            // List a file cause SecurityException, we should get SE as cannot read attribute
+            try (CloseableStream<Path> s = Files.list(
+                fakeRoot.resolve("dir2").resolve("SecurityException")))
+            {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to SecurityException");
+            } catch (SecurityException se) {
+                assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+
+            try (CloseableStream<Path> s = Files.list(
+                fakeRoot.resolve("dir").resolve("SecurityException")))
+            {
+                String[] result = s.map(path -> path.getFileName().toString())
+                                   .toArray(String[]::new);
+                fail("should not reach here due to SecurityException");
+            } catch (SecurityException se) {
+                assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+            }
+         } finally {
+            // Cleanup
+            if (fs != null) {
+                fs.close();
+            }
+            Files.delete(triggerFile);
+            Files.delete(sampleFile);
+            Files.delete(sample);
+            TestUtil.removeAll(triggerDir);
+        }
+    }
+
+    public void testConstructException() {
+        try (CloseableStream<String> s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) {
+            s.forEach(l -> fail("File is not even exist!"));
+        } catch (IOException ioe) {
+            ioe.printStackTrace(System.err);
+            assertTrue(ioe instanceof NoSuchFileException);
+        }
+    }
+
+    public void testClosedStream() throws IOException {
+        try (CloseableStream<Path> s = Files.list(testFolder)) {
+            s.close();
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            assertTrue(actual.length <= level1.length);
+        }
+
+        try (CloseableStream<Path> s = Files.walk(testFolder)) {
+            s.close();
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            fail("Operate on closed stream should throw IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // expected
+        }
+
+        try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE,
+                    (p, attr) -> true)) {
+            s.close();
+            Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+            fail("Operate on closed stream should throw IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // expected
+        }
+    }
+}
--- a/jdk/test/java/util/Arrays/ParallelSorting.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/java/util/Arrays/ParallelSorting.java	Wed Jul 05 18:57:52 2017 +0200
@@ -50,11 +50,11 @@
 
     // Array lengths used in a long run (default)
     private static final int[] LONG_RUN_LENGTHS = {
-        1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 };
+        1000, 10000, 100000, 1000000 };
 
     // Array lengths used in a short run
     private static final int[] SHORT_RUN_LENGTHS = {
-        1, 2, 3, 21, 55, 1000, 10000 };
+        5000, 9000, 10000, 12000 };
 
     // Random initial values used in a long run (default)
     private static final long[] LONG_RUN_RANDOMS = { 666, 0xC0FFEE, 999 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/View/8014863/bug8014863.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2007, 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
+ * @bug 8014863
+ * @summary  Tests the calculation of the line breaks when a text is inserted
+ * @author Dmitry Markov
+ * @library ../../../regtesthelpers
+ * @build Util
+ * @run main bug8014863
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.text.html.HTMLEditorKit;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+public class bug8014863 {
+
+    private static JEditorPane editorPane;
+    private static Robot robot;
+    private static SunToolkit toolkit;
+
+    public static void main(String[] args) throws Exception {
+        toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        robot = new Robot();
+
+        createAndShowGUI();
+
+        toolkit.realSync();
+
+        Util.hitKeys(robot, KeyEvent.VK_HOME);
+        Util.hitKeys(robot, KeyEvent.VK_O);
+
+        toolkit.realSync();
+
+        if (3 != getNumberOfTextLines()) {
+            throw new RuntimeException("The number of texts lines does not meet the expectation");
+        }
+
+        Util.hitKeys(robot, KeyEvent.VK_N);
+
+        toolkit.realSync();
+
+        if (3 != getNumberOfTextLines()) {
+            throw new RuntimeException("The number of texts lines does not meet the expectation");
+        }
+
+        Util.hitKeys(robot, KeyEvent.VK_E);
+        Util.hitKeys(robot, KeyEvent.VK_SPACE);
+        Util.hitKeys(robot, KeyEvent.VK_T);
+        Util.hitKeys(robot, KeyEvent.VK_W);
+
+        toolkit.realSync();
+
+        if (3 != getNumberOfTextLines()) {
+            throw new RuntimeException("The number of texts lines does not meet the expectation");
+        }
+    }
+
+    private static int getNumberOfTextLines() throws Exception {
+        int numberOfLines = 0;
+        int caretPosition = getCaretPosition();
+        int current = 1;
+        int previous;
+
+        setCaretPosition(current);
+        do {
+            previous = current;
+            Util.hitKeys(robot, KeyEvent.VK_DOWN);
+            toolkit.realSync();
+            current = getCaretPosition();
+            numberOfLines++;
+        } while (current != previous);
+
+        setCaretPosition(caretPosition);
+        return numberOfLines;
+    }
+
+    private static int getCaretPosition() throws Exception {
+        final int[] result = new int[1];
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                result[0] = editorPane.getCaretPosition();
+            }
+        });
+        return result[0];
+    }
+
+    private static void setCaretPosition(final int position) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                editorPane.setCaretPosition(position);
+            }
+        });
+    }
+
+    private static void createAndShowGUI() throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                try {
+                    UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }
+                JFrame frame = new JFrame();
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+                editorPane = new JEditorPane();
+                HTMLEditorKit editorKit = new HTMLEditorKit();
+                editorPane.setEditorKit(editorKit);
+                editorPane.setText("<p>qqqq <em>pp</em> qqqq <em>pp</em> " +
+                        "qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp" +
+                        "</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq</p>");
+                editorPane.setCaretPosition(1);
+
+                frame.add(editorPane);
+                frame.setSize(200, 200);
+                frame.setVisible(true);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/html/parser/Parser/7011777/bug7011777.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * @bug 7011777
+ * @summary Tests correct parsing of a HTML comment inside 'script' tags
+ * @author Dmitry Markov
+ */
+
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.parser.ParserDelegator;
+import java.io.StringReader;
+
+public class bug7011777 {
+    static String comment = "<!--\n" +
+            "function foo() {\n" +
+            "  var tag1 = \"</script>\";\n" +
+            "  var tag2 = \"<div>\";\n" +
+            "  var tag3 = \"</div>\";\n" +
+            "  var tag4 = \"<script>\";\n" +
+            "}\n" +
+            "// -->";
+    static String html = "<script>" + comment + "</script>";
+    public static void main(String[] args) throws Exception {
+            new ParserDelegator().parse(new StringReader(html), new MyParserCallback(), true);
+    }
+
+    static class MyParserCallback extends HTMLEditorKit.ParserCallback {
+
+        @Override
+        public void handleComment(char[] data, int pos) {
+            String commentWithoutTags = comment.substring("<!--".length(), comment.length() - "-->".length());
+            String str = new String(data);
+            if (!commentWithoutTags.equals(str)) {
+                System.out.println("Sample string:\n" + commentWithoutTags);
+                System.out.println("Returned string:\n" + str);
+                throw new RuntimeException("Test Failed, sample and returned strings are mismatched!");
+            }
+        }
+    }
+
+}
--- a/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -146,12 +146,6 @@
         }
 
         @Override
-        protected Image platformImageBytesOrStreamToImage(InputStream str,
-                byte[] bytes, long format) throws IOException {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        @Override
         protected byte[] imageToPlatformBytes(Image image, long format)
                 throws IOException {
             throw new UnsupportedOperationException("Not supported yet.");
@@ -161,5 +155,10 @@
         public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
             throw new UnsupportedOperationException("Not supported yet.");
         }
+
+        @Override
+        protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
     }
 }
\ No newline at end of file
--- a/jdk/test/sun/management/jdp/JdpTest.sh	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/sun/management/jdp/JdpTest.sh	Wed Jul 05 18:57:52 2017 +0200
@@ -2,17 +2,17 @@
 
 # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-# 
+#
 # This code is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License version 2 only, as
 # published by the Free Software Foundation.
-# 
+#
 # 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.
@@ -22,8 +22,8 @@
 # questions.
 
 # @test
-# @bug 7169888 
-# @compile -XDignore.symbol.file JdpUnitTest.java JdpClient.java JdpDoSomething.java 
+# @bug 7169888
+# @compile -XDignore.symbol.file JdpUnitTest.java JdpClient.java JdpDoSomething.java
 # @run shell JdpTest.sh --jtreg --no-compile
 # @summary No word Failed expected in the test output
 
@@ -44,17 +44,20 @@
 _logname=".classes/output.txt"
 _last_pid=""
 
+_ip="224.0.23.178"
+_port="7095"
+_jmxport="4545"
 
 _do_compile(){
     # If the test run without JTReg, we have to compile it by our self
     # Under JTReg see @compile statement above
-    # sun.* packages is not included to symbol file lib/ct.sym so we have 
+    # sun.* packages is not included to symbol file lib/ct.sym so we have
     # to ignore it
 
     if [ ! -d ${_testclasses} ]
     then
 	  mkdir -p ${_testclasses}
-    fi   
+    fi
 
     rm -f ${_testclasses}/*.class
 
@@ -64,11 +67,11 @@
                                              JdpDoSomething.java  \
                                              JdpClient.java
 
-   
+
     if [ ! -f ${_testclasses}/JdpDoSomething.class -o ! -f ${_testclasses}/JdpClient.class -o ! -f ${_testclasses}/JdpUnitTest.class ]
     then
       echo "ERROR: Can't compile"
-      exit -1
+      exit 255
     fi
 }
 
@@ -84,10 +87,10 @@
   npid=`_get_pid`
   if [ "${npid}" = "" ]
   then
-     echo "ERROR: Test app not started"
+     echo "ERROR: Test app not started. Please check machine resources before filing a bug."
      if [ "${_jtreg}" = "yes" ]
      then
-       exit -1
+       exit 255
      fi
   fi
 }
@@ -100,53 +103,53 @@
    rm ${_lockFileName}
 
 # wait until VM is actually shuts down
-  while true 
+  while true
   do
     npid=`_get_pid`
-    if [ "${npid}" = "" ] 
+    if [ "${npid}" = "" ]
     then
       break
     fi
     sleep 1
-  done 
+  done
 }
-   
+
 _testme(){
   ${TESTJAVA}/bin/java \
   -cp ${_testclasses} \
   $* \
-    -Dcom.sun.management.jdp.port=7095 \
-    -Dcom.sun.management.jdp.address=239.255.255.225 \
-  JdpClient 
+    -Dcom.sun.management.jdp.port=${_port} \
+    -Dcom.sun.management.jdp.address=${_ip} \
+  JdpClient
 
-}   
+}
 
 
 _jcmd(){
     ${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null
-} 
+}
 
 
 _echo(){
     echo "$*"
     echo "$*" >> ${_logname}
 }
-   
+
 # ============= TESTS ======================================
-   
+
 test_01(){
-		
-    _echo "**** Test one ****"		
+
+    _echo "**** Test one ****"
 
     _app_start JdpUnitTest \
-    -Dcom.sun.management.jdp.port=7095 \
-    -Dcom.sun.management.jdp.address=239.255.255.225 \
+    -Dcom.sun.management.jdp.port=${_port} \
+    -Dcom.sun.management.jdp.address=${_ip} \
     -Dcom.sun.management.jdp.pause=5
 
     res=`_testme`
 
-    case "${res}" in 
-     OK*)  
+    case "${res}" in
+     OK*)
 	_echo "Passed"
      ;;
      *)
@@ -155,24 +158,24 @@
     esac
 
     _app_stop
-}  
+}
 
 test_02(){
-		
-    _echo "**** Test two ****"		
+
+    _echo "**** Test two ****"
 
     _app_start JdpDoSomething \
-     -Dcom.sun.management.jdp.port=7095 \
-     -Dcom.sun.management.jdp.address=239.255.255.225 \
+     -Dcom.sun.management.jdp.port=${_port} \
+     -Dcom.sun.management.jdp.address=${_ip} \
      -Dcom.sun.management.jdp.pause=5 \
-     -Dcom.sun.management.jmxremote.port=4545 \
+     -Dcom.sun.management.jmxremote.port=${_jmxport} \
      -Dcom.sun.management.jmxremote.authenticate=false \
      -Dcom.sun.management.jmxremote.ssl=false
 
     res=`_testme`
 
-    case "${res}" in 
-     OK*)  
+    case "${res}" in
+     OK*)
 	_echo "Passed"
      ;;
      *)
@@ -181,26 +184,26 @@
     esac
 
     _app_stop
-}  
+}
 
 test_03(){
-		
+
     _echo "**** Test three ****"
 
     _app_start JdpDoSomething
-    
+
     _jcmd  ManagementAgent.start\
-                jdp.port=7095 \
-                jdp.address=239.255.255.225 \
+                jdp.port=${_port} \
+                jdp.address=${_ip} \
                 jdp.pause=5 \
-                jmxremote.port=4545 \
+                jmxremote.port=${_jmxport} \
                 jmxremote.authenticate=false \
                 jmxremote.ssl=false
 
     res=`_testme`
 
-    case "${res}" in 
-     OK*)  
+    case "${res}" in
+     OK*)
 	_echo "Passed"
      ;;
      *)
@@ -209,7 +212,7 @@
     esac
 
     _app_stop
-}  
+}
 
 test_04(){
 
@@ -217,7 +220,7 @@
 
     _app_start JdpDoSomething \
      -Dcom.sun.management.jmxremote.autodiscovery=true \
-     -Dcom.sun.management.jmxremote.port=4545 \
+     -Dcom.sun.management.jmxremote.port=${_jmxport} \
      -Dcom.sun.management.jmxremote.authenticate=false \
      -Dcom.sun.management.jmxremote.ssl=false
 
@@ -243,7 +246,7 @@
 
     _jcmd  ManagementAgent.start\
                 jmxremote.autodiscovery=true \
-                jmxremote.port=4545 \
+                jmxremote.port=${_jmxport} \
                 jmxremote.authenticate=false \
                 jmxremote.ssl=false
 
@@ -279,20 +282,20 @@
 
 
 #------------------------------------------------------------------------------
-# reading parameters 
+# reading parameters
 
-for parm in "$@"  
+for parm in "$@"
 do
    case $parm in
   --verbose)      _verbose=yes  ;;
   --jtreg)        _jtreg=yes    ;;
   --no-compile)   _compile=no   ;;
   --testsuite=*)  _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"`  ;;
-  *) 
-     echo "Undefined parameter $parm. Try --help for help" 
-     exit 
+  *)
+     echo "Undefined parameter $parm. Try --help for help"
+     exit
    ;;
- esac 
+ esac
 done
 
 if [ "${_compile}" = "yes" ]
@@ -325,11 +328,11 @@
 cat ${_testsrc}/policy.tpl | \
      sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \
  > ${_policyname}
- 
+
 fi
- 
+
 # Local mode tests
 for i in `echo ${_testsuite} | sed -e "s/,/ /g"`
 do
-  test_${i} 
+  test_${i}
 done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/KtabZero.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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 sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.ktab.KeyTabConstants;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/*
+ * @test
+ * @bug 8014196
+ * @summary ktab creates a file with zero kt_vno
+ */
+public class KtabZero {
+
+    static final String NAME = "k.tab";
+
+    public static void main(String[] args) throws Exception {
+
+        // 0. Non-existing keytab
+        Files.deleteIfExists(Paths.get(NAME));
+        check(true);
+
+        // 1. Create with KeyTab
+        Files.deleteIfExists(Paths.get(NAME));
+        KeyTab.getInstance(NAME).save();
+        check(false);
+
+        // 2. Create with the tool
+        Files.deleteIfExists(Paths.get(NAME));
+        try {
+            Class ktab = Class.forName("sun.security.krb5.internal.tools.Ktab");
+            ktab.getDeclaredMethod("main", String[].class).invoke(null,
+                    (Object)(("-k " + NAME + " -a me@HERE pass").split(" ")));
+        } catch (ClassNotFoundException cnfe) {
+            // Only Windows has ktab tool
+            System.out.println("No ktab tool here. Ignored.");
+            return;
+        }
+        check(false);
+    }
+
+    // Checks existence as well as kt-vno
+    static void check(boolean showBeMissing) throws Exception {
+        KeyTab kt = KeyTab.getInstance(NAME);
+        if (kt.isMissing() != showBeMissing) {
+            throw new Exception("isMissing is not " + showBeMissing);
+        }
+        Field f = KeyTab.class.getDeclaredField("kt_vno");
+        f.setAccessible(true);
+        if (f.getInt(kt) != KeyTabConstants.KRB5_KT_VNO) {
+            throw new Exception("kt_vno is " + f.getInt(kt));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/ktzero.sh	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,74 @@
+#
+# 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.
+#
+
+# @test
+# @bug 8014196
+# @summary ktab creates a file with zero kt_vno
+# @run shell ktzero.sh
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+  JAVAC_CMD=`which javac`
+  TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+if [ "${TESTSRC}" = "" ] ; then
+  TESTSRC="."
+fi
+
+OS=`uname -s`
+case "$OS" in
+  CYGWIN* )
+    FS="/"
+    ;;
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    echo "Unsupported system!"
+    exit 0;
+    ;;
+esac
+
+KEYTAB=ktzero.tmp
+
+rm $KEYTAB 2> /dev/null
+KTAB="${TESTJAVA}${FS}bin${FS}ktab -k $KEYTAB"
+
+# Listing non-existing ktab should fail
+$KTAB -l && exit 1
+
+# Can add to non-existing ktab
+$KTAB -a me@LOCAL mine || exit 2
+
+# Now can be listed
+$KTAB -l || exit 3
+
+echo ABCDEFG > $KEYTAB
+
+# Invalid keytab should fail for all commands
+$KTAB -l && exit 4
+$KTAB -a me@LOCAL mine && exit 2
+
+exit 0
--- a/jdk/test/sun/text/resources/LocaleData	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleData	Wed Jul 05 18:57:52 2017 +0200
@@ -7663,3 +7663,7 @@
 
 # bug 7114053
 LocaleNames/sq/sq=shqip
+
+# bug 7074882
+FormatData/mt/MonthNames/7=Awwissu
+FormatData/mt/MonthAbbreviations/7=Aww
--- a/jdk/test/sun/text/resources/LocaleDataTest.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -35,7 +35,7 @@
  *      6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 6916787
  *      6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
  *      7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
- *      7114053
+ *      7114053 7074882
  * @summary Verify locale data
  *
  */
--- a/jdk/test/tools/launcher/Arrrghs.java	Thu May 30 10:58:13 2013 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java	Wed Jul 05 18:57:52 2017 +0200
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
- *      6894719 6968053 7151434 7146424
+ *      6894719 6968053 7151434 7146424 8007333
  * @summary Argument parsing validation.
  * @compile -XDignore.symbol.file Arrrghs.java
  * @run main/othervm Arrrghs
@@ -310,6 +310,20 @@
         checkArgumentParsing("..\\..\\", "..\\..\\");
         checkArgumentParsing("../../", "../../");
         checkArgumentParsing("a b\\ c", "a", "b\\", "c");
+        // 2 back-slashes
+        checkArgumentParsing("\\\\?", "\\\\?");
+        // 3 back-slashes
+        checkArgumentParsing("\\\\\\?", "\\\\\\?");
+        // 4 back-slashes
+        checkArgumentParsing("\\\\\\\\?", "\\\\\\\\?");
+        // 5 back-slashes
+        checkArgumentParsing("\\\\\\\\\\?", "\\\\\\\\\\?");
+        // 6 back-slashes
+        checkArgumentParsing("\\\\\\\\\\\\?", "\\\\\\\\\\\\?");
+
+        // more treatment of  mixed slashes
+        checkArgumentParsing("f1/ f3\\ f4/", "f1/", "f3\\", "f4/");
+        checkArgumentParsing("f1/ f2\' ' f3/ f4/", "f1/", "f2\'", "'", "f3/", "f4/");
     }
 
     private void initEmptyDir(File emptyDir) throws IOException {
--- a/make/deploy-rules.gmk	Thu May 30 10:58:13 2013 -0700
+++ b/make/deploy-rules.gmk	Wed Jul 05 18:57:52 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 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
@@ -42,20 +42,6 @@
 endif
 
 DEPLOY_BUILD_TARGETS = sanity deploy 
-# Only build 7-Zip LZMA file compression if it is available
-# Enable 7-Zip LZMA file (de)compression for Java Kernel if it is available
-ifeq ($(ARCH_DATA_MODEL), 32)
-  ifeq ($(PLATFORM), windows)
-      EC_TMP = $(shell if [ -d $(DEPLOY_TOPDIR)/make/lzma ] ; then \
-        $(ECHO) true ; \
-      else \
-  $(ECHO) false ; \
-      fi )
-  ifeq ($(EC_TMP), true)
-        DEPLOY_BUILD_TARGETS += extra-comp-all
-      endif
-  endif
-endif
 
 ifneq ($(JQS), off)
   ifeq ($(ARCH_DATA_MODEL), 32)
@@ -65,22 +51,6 @@
   endif
 endif
 
-ifeq ($(ARCH_DATA_MODEL), 32)
-  ifeq ($(PLATFORM), windows)
-    # Only set up to use UPX compression if it is available
-    UP_TMP = $(shell if [ -d $(DEPLOY_TOPDIR)/make/upx ] ; then \
-      $(ECHO) true ; \
-    else \
-      $(ECHO) false ; \
-    fi )
-    ifeq ($(UP_TMP), true)
-      DEPLOY_BUILD_TARGETS += cmd-comp-all
-    endif
-  endif
-endif
-
-
-
 ifndef DEV_ONLY
   DEPLOY_BUILD_TARGETS += images
 else
--- a/nashorn/.hgignore	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/.hgignore	Wed Jul 05 18:57:52 2017 +0200
@@ -24,3 +24,4 @@
 .idea/*
 test/lib/testng.jar
 test/script/external/*
+.project
--- a/nashorn/.hgtags	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/.hgtags	Wed Jul 05 18:57:52 2017 +0200
@@ -201,3 +201,4 @@
 45ce27fbe2720d80070095c0db7344ec41e2833d jdk8-b89
 67ca019e3713dd71c884d753de02fd0021981969 jdk8-b90
 6b9f4120380091b8b1751a825b9f84bf1be224fe jdk8-b91
+dee23cce5235b594a96d3361b65eacc97bd5a583 jdk8-b92
--- a/nashorn/docs/JavaScriptingProgrammersGuide.html	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/docs/JavaScriptingProgrammersGuide.html	Wed Jul 05 18:57:52 2017 +0200
@@ -71,9 +71,20 @@
 Arrays</a></span></li>
 <li><span><a href="#jsimplement">Implementing Java
 Interfaces</a></span></li>
-<li><span><a href="#jsextend">Extending Java classes
+<li><span><a href="#jsextendabstract">Extending Abstract Java Classes
+</a></span></li>
+<li><span><a href="#jsextendconcrete">Extending Concrete Java Classes
+</a></span></li>
+<li><span><a href="#jsimplementmultiple">Implementing Multiple Java Interfaces
+</a></span></li>
+<li><span><a href="#classBoundImplementations">Class-Bound Implementations
 </a></span></li>
 <li><span><a href="#jsoverload">Overload Resolution</a></span></li>
+<li><span><a href="#dataTypeMapping">Mapping of Data Types Between Java
+and JavaScript</a></span></li>
+
+
+
 </ul>
 </li>
 <li><span><a href="#engineimpl">Implementing Your Own Script
@@ -466,10 +477,10 @@
 </code>
 </pre> 
 
-Note that the name of the type is always a string for a fully qualified name. You can use any of these types to create new instances, e.g.:
+Note that the name of the type is always a string for a fully qualified name. You can use any of these expressions to create new instances, e.g.:
 
 <pre><code>
- var anArrayList = new Java.type("java.util.ArrayList")
+ var anArrayList = new (Java.type("java.util.ArrayList"))
 </code></pre> 
 
 or
@@ -496,6 +507,37 @@
 <p>
 You can access both static and non-static inner classes. If you want to create an instance of a non-static inner class, remember to pass an instance of its outer class as the first argument to the constructor.
 </p>
+<p>
+In addition to creating new instances, the type objects returned from <code>Java.type</code> calls can also be used to access the
+static fields and methods of the classes:
+<pre><code>
+ var File = Java.type("java.io.File")
+ File.createTempFile("nashorn", ".tmp")
+</code></pre> 
+<p>
+Methods with names of the form <code>isXxx()</code>, <code>getXxx()</code>, and <code>setXxx()</code> can also be used as properties, for both instances and statics.
+</p>
+<p>
+A type object returned from <code>Java.type</code> is distinct from a <code>java.lang.Class</code> object. You can obtain one from the other using properties <code>class</code> and <code>static</code> on them.
+<pre><code>
+ var ArrayList = Java.type("java.util.ArrayList")
+ var a = new ArrayList
+
+ // All of the following print true:
+ print("Type acts as target of instanceof: " + (a instanceof ArrayList))
+ print("Class doesn't act as target of instanceof: " + !(a instanceof a.getClass()))
+ print("Type is not same as instance's getClass(): " + (a.getClass() !== ArrayList))
+ print("Type's `class` property is same as instance getClass(): " + (a.getClass() === ArrayList.class))
+ print("Type is same as instance getClass()'s `static` property: " + (a.getClass().static === ArrayList))
+</code></pre> 
+<p>
+You can think of the type object as similar to the class names as used in Java source code: you use them as the
+arguments to the <code>new</code> and <code>instanceof</code> operators and as the namespace for the static fields
+and methods, but they are different than the runtime <code>Class</code> objects returned by <code>getClass()</code> calls.
+Syntactically and semantically, this separation produces code that is most similar to Java code, where a distinction
+between compile-time class expressions and runtime class objects also exists. (Also, Java can't have the equivalent of <code>static</code>
+property on a <code>Class</code> object since compile-time class expressions are never reified as objects).
+</p>
 <hr>
 <a name="jsimport" id="jsimport"></a>
 <h3>Importing Java Packages, Classes</h3>
@@ -558,10 +600,7 @@
 <a name="jsarrays" id="jsarrays"></a>
 <h3>Creating, Converting and Using Java Arrays</h3>
 <p>
-Array element access or length access is
-the same as in Java. Also, a script array can be used when a Java
-method expects a Java array (auto conversion). So in most cases we
-don't have to create Java arrays explicitly.</p>
+Array element access or length access is the same as in Java.</p>
 <pre><code>
 // <a href="source/javaarray.js">javaarray.js</a>
 
@@ -577,27 +616,31 @@
 </pre>
 <p>
 It is also possible to convert between JavaScript and Java arrays.
-Given a JavaScript array and a Java type, <code>Java.toJavaArray</code> returns a Java array with the same initial contents, and with the specified component type. 
+Given a JavaScript array and a Java type, <code>Java.to</code> returns a Java array with the same initial contents, and with the specified array type. 
 </p>
 <pre><code>
  var anArray = [1, "13", false]
- var javaIntArray = Java.toJavaArray(anArray, "int")
+ var javaIntArray = Java.to(anArray, "int[]")
  print(javaIntArray[0]) // prints 1
  print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
  print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
 </code></pre>
 <p>
-Given a Java array or Collection, <code>Java.toJavaScriptArray</code> returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.i
+You can use either a string or a type object returned from <code>Java.type()</code> to specify the type of the array. 
+You can also omit the array type, in which case a <code>Object[]</code> will be created.
+</p>
+<p>
+Given a Java array or Collection, <code>Java.from</code> returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.
 </p>
 <pre><code>
 var File = Java.type("java.io.File");
 var listCurDir = new File(".").listFiles();
-var jsList = Java.toJavaScriptArray(listCurDir);
+var jsList = Java.from(listCurDir);
 print(jsList);
 </code></pre>
 <hr>
 <a name="jsimplement" id="jsimplement"></a>
-<h3>Implementing Java Interfaces</h3>
+<h3>Implementing Java interfaces</h3>
 <p>A Java interface can be implemented in JavaScript by using a
 Java anonymous class-like syntax:</p>
 <pre><code>
@@ -631,8 +674,8 @@
 </code>
 </pre>
 <hr>
-<a name="jsextend" id="jsextend"></a>
-<h3>Extending Java classes</h3>
+<a name="jsextendabstract" id="jsextendabstract"></a>
+<h3>Extending Abstract Java Classes</h3>
 <p>
 If a Java class is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
 </p>
@@ -671,6 +714,9 @@
 
 Here, <code>Timer.schedule()</code> expects a <code>TimerTask</code> as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
 
+<hr>
+<a name="jsextendconcrete" id="jsextendconcrete"></a>
+<h3>Extending Concrete Java Classes</h3>
 <p>
 To extend a concrete Java class, you have to use <code>Java.extend</code> function.
 <code>Java.extend</code> returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it.  
@@ -695,26 +741,178 @@
 printSizeInvokedArrayList.size();
 printAddInvokedArrayList.add(33, 33);
 </code></pre>
+<p>
+The reason you must use <code>Java.extend()</code> with concrete classes is that with concrete classes, there can be a 
+syntactic ambiguity if you just invoke their constructor. Consider this example:
+</p>
+<pre><code>
+var t = new java.lang.Thread({ run: function() { print("Hello!") } })
+</code></pre>
+<p>
+If we allowed subclassing of concrete classes with constructor syntax, Nashorn couldn't tell if you're creating a new 
+<code>Thread</code> and passing it a <code>Runnable</code> at this point, or you are subclassing <code>Thread</code> and
+passing it a new implementation for its own <code>run()</code> method.
+</p>
+<hr>
+<a name="jsimplementmultiple" id="jsimplementmultiple"></a>
+<h3>Implementing Multiple Interfaces</h3>
+<p>
+<code>Java.extend</code> can in fact take a list of multiple types. At most one of the types can be a class, and the rest must
+be interfaces (the class doesn't have to be the first in the list). You will get back an object that extends the class and 
+implements all the interfaces. (Obviously, if you only specify interfaces and no class, the object will extend <code>java.lang.Object</code>).
+<hr>
+<a name="classBoundImplementations" id="classBoundImplementations"></a>
+<h3>Class-Bound Implementations</h3>
+<p>
+The methods shown so far for extending Java classes and implementing interfaces &ndash; passing an implementation JavaScript object 
+or function to a constructor, or using <code>Java.extend</code> with <code>new</code> &ndash; all produce classes that take an
+extra JavaScript object parameter in their constructors that specifies the implementation. The implementation is therefore always bound
+to the actual instance being created with <code>new</code>, and not to the whole class. This has some advantages, for example in the
+memory footprint of the runtime, as Nashorn can just create a single "universal adapter" for every combination of types being implemented.
+In reality, the below code shows that different instantiations of, say, <code>Runnable</code> have the same class regardless of them having
+different JavaScript implementation objects:
+</p>
+<pre><code>
+var Runnable = java.lang.Runnable;
+var r1 = new Runnable(function() { print("I'm runnable 1!") })
+var r2 = new Runnable(function() { print("I'm runnable 2!") })
+r1.run()
+r2.run()
+print("We share the same class: " + (r1.class === r2.class))
+</code></pre>
+<p>
+prints:
+</p>
+<pre><code>
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: true
+</code></pre>
+<p>
+Sometimes, however, you'll want to extend a Java class or implement an interface with implementation bound to the class, not to
+its instances. Such a need arises, for example, when you need to pass the class for instantiation to an external API; prime example
+of this is the JavaFX framework where you need to pass an Application class to the FX API and let it instantiate it.
+</p>
+<p>
+Fortunately, there's a solution for that: <code>Java.extend()</code> &ndash; aside from being able to take any number of type parameters
+denoting a class to extend and interfaces to implement &ndash; can also take one last argument that has to be a JavaScript object
+that serves as the implementation for the methods. In this case, <code>Java.extend()</code> will create a class that has the same
+constructors as the original class had, as they don't need to take an an extra implementation object parameter. The example below
+shows how you can create class-bound implementations, and shows that in this case, the implementation classes for different invocations
+are indeed different:
+</p>
+<pre><code>
+var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
+var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
+var r1 = new RunnableImpl1()
+var r2 = new RunnableImpl2()
+r1.run()
+r2.run()
+print("We share the same class: " + (r1.class === r2.class))
+</code></pre>
+<p>
+prints:
+</p>
+<pre><code>
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: false
+</code></pre>
+<p>
+As you can see, the major difference here is that we moved the implementation object into the invocation of <code>Java.extend</code>
+from the constructor invocations &ndash; indeed the constructor invocations now don't even need to take an extra parameter! Since
+the implementations are bound to a class, the two classes obviously can't be the same, and we indeed see that the two runnables no
+longer share the same class &ndash; every invocation of <code>Java.extend()</code> with a class-specific implementation object triggers
+the creation of a new Java adapter class.
+</p>
+<p>
+Finally, the adapter classes with class-bound implementations can <i>still</i> take an additional constructor parameter to further
+override the behavior on a per-instance basis. Thus, you can even combine the two approaches: you can provide part of the implementation
+in a class-based JavaScript implementation object passed to <code>Java.extend</code>, and part in another object passed to the constructor.
+Whatever functions are provided by the constructor-passed object will override the functions in the class-bound object.
+</p>
+<pre><code>
+var RunnableImpl = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
+var r1 = new RunnableImpl()
+var r2 = new RunnableImpl(function() { print("I'm runnable 2!") })
+r1.run()
+r2.run()
+print("We share the same class: " + (r1.class === r2.class))
+</code></pre>
+<p>
+prints:
+</p>
+<pre><code>
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: true
+</code></pre>
 <hr>
 <a name="jsoverload" id="jsoverload"></a>
 <h3>Overload Resolution</h3>
 <p>Java methods can be overloaded by argument types. In Java,
 overload resolution occurs at compile time (performed by javac).
-When calling Java methods from a script, the script
-interpreter/compiler needs to select the appropriate method. With
-the JavaScript engine, you do not need to do anything special - the
-correct Java method overload variant is selected based on the
-argument types. But, sometimes you may want (or have) to explicitly
-select a particular overload variant.</p>
+When calling Java methods from Nashorn, the appropriate method will be
+selected based on the argument types at invocation time. You do not need
+to do anything special &ndash; the correct Java method overload variant 
+is selected based automatically. You still have the option of explicitly
+specifying a particular overload variant. Reasons for this include 
+either running into a genuine ambiguity with actual argument types, or 
+rarely reasons of performance &ndash; if you specify the actual overload
+then the engine doesn't have to perform resolution during invocation.
+Individual overloads of a Java methods are exposed as special properties
+with the name of the method followed with its signature in parentheses. 
+You can invoke them like this:</p>
 <pre><code>
 // <a href="source/overload.js">overload.js</a>
 
 var out = java.lang.System.out;
 
 // select a particular print function 
-out["println(java.lang.Object)"]("hello");
+out["println(Object)"]("hello");
 </code>
 </pre>
+<p>
+Note that you normally don't even have to use qualified class names in 
+the signatures as long as the unqualified name of the type is sufficient
+for uniquely identifying the signature. In practice this means that only
+in the extremely unlikely case that two overloads only differ in 
+parameter types that have identical unqualified names but come from 
+different packages would you need to use the fully qualified name of the
+class.
+</p>
+<hr>
+<a name="dataTypeMapping" id="dataTypeMapping"></a>
+<h3>Mapping of Data Types Between Java and JavaScript</h3>
+<p>
+We have previously shown some of the data type mappings between Java and JavaScript.
+We saw that arrays need to be explicitly converted. We have also shown that JavaScript functions
+are automatically converted to SAM types when passed as parameters to Java methods. Most other
+conversions work as you would expect.
+</p>
+<p>
+Every JavaScript object is also a <code>java.util.Map</code> so APIs receiving maps will receive them directly.
+</p>
+<p>
+When numbers are passed to a Java API, they will be converted to the expected target numeric type, either boxed or
+primitive, but if the target type is less specific, say <code>Number</code> or <code>Object</code>, you can only
+count on them being a <code>Number</code>, and have to test specifically for whether it's a boxed <code>Double</code>,
+<code>Integer</code>, <code>Long</code>, etc. &ndash; it can be any of these due to internal optimizations. Also, you 
+can pass any JavaScript value to a Java API expecting either a boxed or primitive number; the JavaScript specification's
+<code>ToNumber</code> conversion algorithm will be applied to the value.
+</p>
+<p>
+In a similar vein, if a Java method expects a <code>String</code> or a <code>Boolean</code>, the values will be
+converted using all conversions allowed by the JavaScript specification's <code>ToString</code> and <code>ToBoolean</code>
+conversions.
+</p>
+<p>
+Finally, a word of caution about strings. Due to internal performance optimizations of string operations, JavaScript strings are
+not always necessarily of type <code>java.lang.String</code>, but they will always be of type <code>java.lang.CharSequence</code>.
+If you pass them to a Java method that expects a <code>java.lang.String</code> parameter, then you will naturally receive a Java
+String, but if the signature of your method is more generic, i.e. it receives a <code>java.lang.Object</code> parameter, you can 
+end up with an object of private engine implementation class that implements <code>CharSequence</code> but is not a Java String.
+</p>
 <hr>
 <a name="engineimpl" id="engineimpl"></a>
 <h2>Implementing Your Own Script Engine</h2>
--- a/nashorn/docs/source/javaarray.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/docs/source/javaarray.js	Wed Jul 05 18:57:52 2017 +0200
@@ -40,7 +40,7 @@
 
 // convert a script array to Java array
 var anArray = [1, "13", false];
-var javaIntArray = Java.toJavaArray(anArray, "int");
+var javaIntArray = Java.to(anArray, "int[]");
 print(javaIntArray[0]);// prints 1
 print(javaIntArray[1]); // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
 print(javaIntArray[2]);// prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
@@ -48,5 +48,5 @@
 // convert a Java array to a JavaScript array
 var File = Java.type("java.io.File");
 var listCurDir = new File(".").listFiles();
-var jsList = Java.toJavaScriptArray(listCurDir);
+var jsList = Java.from(listCurDir);
 print(jsList);
--- a/nashorn/make/build-benchmark.xml	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/make/build-benchmark.xml	Wed Jul 05 18:57:52 2017 +0200
@@ -24,258 +24,270 @@
 <project name="nashorn-benchmarks" default="all" basedir="..">
 
   <target name="octane-init" depends="jar">
-    <fileset id="octane-set"
-	     dir="${octane-test-sys-prop.test.js.roots}"
-	     excludes="${octane-test-sys-prop.test.js.exclude.list}">
-      <include name="*.js"/>
-    </fileset>
-    <pathconvert pathsep=" " property="octane-tests" refid="octane-set"/>
+    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes pdfjs raytrace regexp richards splay"/>
+  </target>
+  
+  <!-- ignore benchmarks where rhino crashes -->
+  <target name="octane-init-rhino" depends="jar">
+    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes raytrace regexp richards splay"/>
   </target>
 
   <!-- box2d -->
   <target name="octane-box2d" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/box2d.js"/>
+      <param name="octane-tests" value="box2d"/>
     </antcall>
   </target>
 
   <target name="octane-box2d-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/box2d.js"/>
+      <param name="octane-tests" value="box2d"/>
     </antcall>
   </target>
 
   <target name="octane-box2d-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/box2d.js"/>
+      <param name="octane-tests" value="box2d"/>
     </antcall>
   </target>
 
+
   <!-- code-load -->  
   <target name="octane-code-load" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/code-load.js"/>
+      <param name="octane-tests" value="code-load"/>
     </antcall>
   </target>
 
   <target name="octane-code-load-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/code-load.js"/>
+      <param name="octane-tests" value="code-load"/>
     </antcall>
   </target>
 
   <target name="octane-code-load-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/code-load.js"/>
+      <param name="octane-tests" value="code-load"/>
     </antcall>
   </target>
 
+
   <!-- crypto -->
   <target name="octane-crypto" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/crypto.js"/>
+      <param name="octane-tests" value="crypto"/>
     </antcall>
   </target>
 
   <target name="octane-crypto-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/crypto.js"/>
+      <param name="octane-tests" value="crypto"/>
     </antcall>
   </target>
 
   <target name="octane-crypto-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/crypto.js"/>
+      <param name="octane-tests" value="crypto"/>
     </antcall>
   </target>
 
+
   <!-- deltablue -->
   <target name="octane-deltablue" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/deltablue.js"/>
+      <param name="octane-tests" value="deltablue"/>
     </antcall>
   </target>
 
   <target name="octane-deltablue-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/deltablue.js"/>
+      <param name="octane-tests" value="deltablue"/>
     </antcall>
   </target>
 
   <target name="octane-deltablue-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/deltablue.js"/>
+      <param name="octane-tests" value="deltablue"/>
     </antcall>
   </target>
 
+
   <!-- earley-boyer -->
   <target name="octane-earley-boyer" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/earley-boyer.js"/>
+      <param name="octane-tests" value="earley-boyer"/>
     </antcall>
   </target>
 
   <target name="octane-earley-boyer-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/earley-boyer.js"/>
+      <param name="octane-tests" value="earley-boyer"/>
     </antcall>
   </target>
 
   <target name="octane-earley-boyer-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/earley-boyer.js"/>
+      <param name="octane-tests" value="earley-boyer"/>
     </antcall>
   </target>
 
+
   <!-- gbemu -->  
   <target name="octane-gbemu" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/gbemu.js"/>
+      <param name="octane-tests" value="gbemu"/>
     </antcall>
   </target>
 
   <target name="octane-gbemu-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/gbemu.js"/>
+      <param name="octane-tests" value="gbemu"/>
     </antcall>
   </target>
 
   <target name="octane-gbemu-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/gbemu.js"/>
+      <param name="octane-tests" value="gbemu"/>
     </antcall>
   </target>
 
+
   <!-- mandreel -->  
   <target name="octane-mandreel" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/mandreel.js"/>
+      <param name="octane-tests" value="mandreel"/>
     </antcall>
   </target>
 
   <target name="octane-mandreel-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/mandreel.js"/>
+      <param name="octane-tests" value="mandreel"/>
     </antcall>
   </target>
 
   <target name="octane-mandreel-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/mandreel.js"/>
+      <param name="octane-tests" value="mandreel"/>
     </antcall>
   </target>
 
+
   <!-- navier-stokes -->
   <target name="octane-navier-stokes" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/navier-stokes.js"/>
+      <param name="octane-tests" value="navier-stokes"/>
     </antcall>
   </target>
 
   <target name="octane-navier-stokes-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/navier-stokes.js"/>
+      <param name="octane-tests" value="navier-stokes"/>
     </antcall>
   </target>
 
   <target name="octane-navier-stokes-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/navier-stokes.js"/>
+      <param name="octane-tests" value="navier-stokes"/>
     </antcall>
   </target>
 
+
   <!-- pdfjs -->  
   <target name="octane-pdfjs" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/pdfjs.js"/>
+      <param name="octane-tests" value="pdfjs"/>
     </antcall>
   </target>
 
   <target name="octane-pdfjs-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/pdfjs.js"/>
+      <param name="octane-tests" value="pdfjs"/>
     </antcall>
   </target>
 
   <target name="octane-pdfjs-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/pdfjs.js"/>
+      <param name="octane-tests" value="pdfjs"/>
     </antcall>
   </target>
 
+
   <!-- raytrace -->
   <target name="octane-raytrace" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/raytrace.js"/>
+      <param name="octane-tests" value="raytrace"/>
     </antcall>
   </target>
 
   <target name="octane-raytrace-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/raytrace.js"/>
+      <param name="octane-tests" value="raytrace"/>
     </antcall>
   </target>
 
   <target name="octane-raytrace-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/raytrace.js"/>
+      <param name="octane-tests" value="raytrace"/>
     </antcall>
   </target>
 
+
   <!-- regexp -->
   <target name="octane-regexp" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/regexp.js"/>
+      <param name="octane-tests" value="regexp"/>
     </antcall>
   </target>
 
   <target name="octane-regexp-octane-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/regexp.js"/>
+      <param name="octane-tests" value="regexp"/>
     </antcall>
   </target>
 
   <target name="octane-regexp-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/regexp.js"/>
+      <param name="octane-tests" value="regexp"/>
     </antcall>
   </target>
 
+
   <!-- richards -->
   <target name="octane-richards" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/richards.js"/>
+      <param name="octane-tests" value="richards"/>
     </antcall>
   </target>
 
   <target name="octane-richards-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/richards.js"/>
+      <param name="octane-tests" value="richards"/>
     </antcall>
   </target>
 
   <target name="octane-richards-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/richards.js"/>
+      <param name="octane-tests" value="richards"/>
     </antcall>
   </target>
 
+
   <!-- splay -->
   <target name="octane-splay" depends="jar">
     <antcall target="run-octane">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/splay.js"/>
+      <param name="octane-tests" value="splay"/>
     </antcall>
   </target>
 
   <target name="octane-splay-v8" depends="jar">
     <antcall target="run-octane-v8">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/splay.js"/>
+      <param name="octane-tests" value="splay"/>
     </antcall>
   </target>
 
   <target name="octane-splay-rhino" depends="jar">
     <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/splay.js"/>
+      <param name="octane-tests" value="splay"/>
     </antcall>
   </target>
 
@@ -307,7 +319,7 @@
   </target>
 
   <!-- run octane benchmarks using Rhino as runtime -->
-  <target name="octane-rhino" depends="octane-init">
+  <target name="octane-rhino" depends="octane-init-rhino">
     <antcall target="run-octane-rhino"/>
   </target>
   
--- a/nashorn/make/build.xml	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/make/build.xml	Wed Jul 05 18:57:52 2017 +0200
@@ -212,7 +212,9 @@
            target="${javac.target}"
            debug="${javac.debug}"
            encoding="${javac.encoding}"
-           includeantruntime="false"/>
+           includeantruntime="false">
+        <compilerarg line="-extdirs &quot;&quot;"/>
+    </javac>
 
     <!-- tests that check nashorn internals and internal API -->
     <jar jarfile="${nashorn.internal.tests.jar}">
@@ -305,6 +307,8 @@
       <include name="**/codegen/*Test.class"/>
       <include name="**/parser/*Test.class"/>
       <include name="**/runtime/*Test.class"/>
+      <include name="**/runtime/regexp/*Test.class"/>
+      <include name="**/runtime/regexp/joni/*Test.class"/>
       <include name="**/framework/*Test.class"/>
     </fileset>
 
--- a/nashorn/make/code_coverage.xml	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/make/code_coverage.xml	Wed Jul 05 18:57:52 2017 +0200
@@ -139,6 +139,32 @@
       <arg value="${cc.merged.xml}"/>
       <arg value="-exclude"/>
       <arg value="com\.oracle\.nashorn\.runtime\.ScriptRuntime*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.javaadapters*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.objects\.annotations*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.scripts*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.lookup\.MethodHandleFactory*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.test\.framework*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.test\.models*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.ir\.debug*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.runtime\.regexp\.joni\.bench*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.runtime\.DebugLogger*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.runtime\.Timing*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.runtime\.Logging*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.runtime\.Debug*"/>
+      <arg value="-exclude"/>
+      <arg value="jdk\.nashorn\.internal\.objects\.NativeDebug*"/>
       <arg line="${cc.all.xmls}"/>
       <classpath>
         <pathelement location="${jcov.jar}"/>
--- a/nashorn/make/project.properties	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/make/project.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -87,6 +87,7 @@
 
 testng.listeners=\
  org.testng.reporters.SuiteHTMLReporter, \
+ org.testng.reporters.TestHTMLReporter, \
  org.testng.reporters.jq.Main, \
  org.testng.reporters.FailedReporter, \
  org.testng.reporters.XMLReporter \
@@ -214,9 +215,13 @@
 run.test.xmx=3G
 run.test.xms=2G
 
+run.test.user.language=tr
+run.test.user.country=TR
+
 #  -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods
 # add '-Dtest.js.outofprocess' to run each test in a new sub-process
-run.test.jvmargs.main=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -ea -Dnashorn.debug=true -Dfile.encoding=UTF-8
+run.test.jvmargs.main=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -ea -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country}
+
 #-XX:+HeapDumpOnOutOfMemoryError -XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M  
 run.test.jvmargs.octane.main=-Xms${run.test.xms} ${run.test.jvmargs.main}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.api.scripting;
+
+/**
+ * netscape.javascript.JSObject-like interface for nashorn script objects.
+ */
+public abstract class JSObject {
+    /**
+     * Call a JavaScript method
+     *
+     * @param methodName name of method
+     * @param args arguments to method
+     * @return result of call
+     */
+    public abstract Object call(String methodName, Object args[]);
+
+    /**
+     * Evaluate a JavaScript expression
+     *
+     * @param s JavaScript expression to evaluate
+     * @return evaluation result
+     */
+    public abstract Object eval(String s);
+
+    /**
+     * Retrieves a named member of a JavaScript object.
+     *
+     * @param name of member
+     * @return member
+     */
+    public abstract Object getMember(String name);
+
+    /**
+     * Retrieves an indexed member of a JavaScript object.
+     *
+     * @param index index of member slot
+     * @return member
+     */
+    public abstract Object getSlot(int index);
+
+    /**
+     * Remove a named member from a JavaScript object
+     *
+     * @param name name of member
+     */
+    public abstract void removeMember(String name);
+
+    /**
+     * Set a named member in a JavaScript object
+     *
+     * @param name  name of member
+     * @param value value of member
+     */
+    public abstract void setMember(String name, Object value);
+
+    /**
+     * Set an indexed member in a JavaScript object
+     *
+     * @param index index of member slot
+     * @param value value of member
+     */
+    public abstract void setSlot(int index, Object value);
+}
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,7 +42,6 @@
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import netscape.javascript.JSObject;
 
 /**
  * Mirror object that wraps a given ScriptObject instance. User can
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js	Wed Jul 05 18:57:52 2017 +0200
@@ -88,7 +88,7 @@
             }
         }
 
-        array = Java.toJavaArray(array);
+        array = Java.to(array);
         return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
     }
 });
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed Jul 05 18:57:52 2017 +0200
@@ -84,8 +84,8 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
@@ -111,7 +111,7 @@
  * computed.
  */
 
-final class Attr extends NodeOperatorVisitor {
+final class Attr extends NodeOperatorVisitor<LexicalContext> {
 
     /**
      * Local definitions in current block (to discriminate from function
@@ -138,6 +138,7 @@
      * Constructor.
      */
     Attr(final TemporarySymbols temporarySymbols) {
+        super(new LexicalContext());
         this.temporarySymbols = temporarySymbols;
         this.localDefs   = new ArrayDeque<>();
         this.localUses   = new ArrayDeque<>();
@@ -202,7 +203,7 @@
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
         // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
         // in a separate step above) and "var" declarations in for loop initializers.
-        body.accept(new NodeOperatorVisitor() {
+        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterFunctionNode(final FunctionNode nestedFn) {
                 return false;
@@ -218,7 +219,7 @@
                     if (varNode.isFunctionDeclaration()) {
                         newType(symbol, FunctionNode.FUNCTION_TYPE);
                     }
-                    return varNode.setName((IdentNode)ident.setSymbol(getLexicalContext(), symbol));
+                    return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
                 }
                 return varNode;
             }
@@ -227,8 +228,8 @@
 
     private void enterFunctionBody() {
 
-        final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
-        final Block body = getLexicalContext().getCurrentBlock();
+        final FunctionNode functionNode = lc.getCurrentFunction();
+        final Block body = lc.getCurrentBlock();
 
         initFunctionWideVariables(functionNode, body);
 
@@ -256,7 +257,7 @@
         //the symbols in the block should really be stateless
         block.clearSymbols();
 
-        if (getLexicalContext().isFunctionBody()) {
+        if (lc.isFunctionBody()) {
             enterFunctionBody();
         }
         pushLocalsBlock();
@@ -283,7 +284,7 @@
     @Override
     public boolean enterCatchNode(final CatchNode catchNode) {
         final IdentNode exception = catchNode.getException();
-        final Block     block     = getLexicalContext().getCurrentBlock();
+        final Block     block     = lc.getCurrentBlock();
 
         start(catchNode);
 
@@ -298,10 +299,10 @@
     @Override
     public Node leaveCatchNode(final CatchNode catchNode) {
         final IdentNode exception = catchNode.getException();
-        final Block  block        = getLexicalContext().getCurrentBlock();
+        final Block  block        = lc.getCurrentBlock();
         final Symbol symbol       = findSymbol(block, exception.getName());
         assert symbol != null;
-        return end(catchNode.setException((IdentNode)exception.setSymbol(getLexicalContext(), symbol)));
+        return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol)));
     }
 
     /**
@@ -320,7 +321,7 @@
             flags |= IS_SCOPE;
         }
 
-        final FunctionNode function = getLexicalContext().getFunction(block);
+        final FunctionNode function = lc.getFunction(block);
         if (symbol != null) {
             // Symbol was already defined. Check if it needs to be redefined.
             if ((flags & KINDMASK) == IS_PARAM) {
@@ -353,12 +354,12 @@
             if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
                 symbolBlock = block; //internal vars are always defined in the block closest to them
             } else {
-                symbolBlock = getLexicalContext().getFunctionBody(function);
+                symbolBlock = lc.getFunctionBody(function);
             }
 
             // Create and add to appropriate block.
             symbol = new Symbol(name, flags);
-            symbolBlock.putSymbol(getLexicalContext(), symbol);
+            symbolBlock.putSymbol(lc, symbol);
 
             if ((flags & Symbol.KINDMASK) != IS_GLOBAL) {
                 symbol.setNeedsSlot(true);
@@ -381,7 +382,7 @@
         //an outermost function in our lexical context that is not a program (runScript)
         //is possible - it is a function being compiled lazily
         if (functionNode.isDeclared()) {
-            final Iterator<Block> blocks = getLexicalContext().getBlocks();
+            final Iterator<Block> blocks = lc.getBlocks();
             if (blocks.hasNext()) {
                 defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR);
             }
@@ -397,13 +398,11 @@
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         FunctionNode newFunctionNode = functionNode;
 
-        final LexicalContext lc = getLexicalContext();
-
         final Block body = newFunctionNode.getBody();
 
         //look for this function in the parent block
         if (functionNode.isDeclared()) {
-            final Iterator<Block> blocks = getLexicalContext().getBlocks();
+            final Iterator<Block> blocks = lc.getBlocks();
             if (blocks.hasNext()) {
                 newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName()));
             }
@@ -411,7 +410,7 @@
             final boolean anonymous = functionNode.isAnonymous();
             final String  name      = anonymous ? null : functionNode.getIdent().getName();
             if (anonymous || body.getExistingSymbol(name) != null) {
-                newFunctionNode = (FunctionNode)ensureSymbol(lc, FunctionNode.FUNCTION_TYPE, newFunctionNode);
+                newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode);
             } else {
                 assert name != null;
                 final Symbol self = body.getExistingSymbol(name);
@@ -490,8 +489,6 @@
 
         start(identNode);
 
-        final LexicalContext lc = getLexicalContext();
-
         if (identNode.isPropertyName()) {
             // assign a pseudo symbol to property name
             final Symbol pseudoSymbol = pseudoSymbol(name);
@@ -549,7 +546,7 @@
      */
     private void maybeForceScope(final Symbol symbol) {
         if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
-            Symbol.setSymbolIsScope(getLexicalContext(), symbol);
+            Symbol.setSymbolIsScope(lc, symbol);
         }
     }
 
@@ -558,7 +555,7 @@
             return false;
         }
         boolean previousWasBlock = false;
-        for(final Iterator<LexicalContextNode> it = getLexicalContext().getAllNodes(); it.hasNext();) {
+        for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
             final LexicalContextNode node = it.next();
             if(node instanceof FunctionNode) {
                 // We reached the function boundary without seeing a definition for the symbol - it needs to be in
@@ -594,10 +591,8 @@
         }
 
         if (symbol.isScope()) {
-            final LexicalContext lc = getLexicalContext();
-
             Block scopeBlock = null;
-            for (final Iterator<LexicalContextNode> contextNodeIter = getLexicalContext().getAllNodes(); contextNodeIter.hasNext(); ) {
+            for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
                 final LexicalContextNode node = contextNodeIter.next();
                 if (node instanceof Block) {
                     if (((Block)node).getExistingSymbol(name) != null) {
@@ -610,7 +605,7 @@
             }
 
             if (scopeBlock != null) {
-                assert getLexicalContext().contains(scopeBlock);
+                assert lc.contains(scopeBlock);
                 lc.setFlag(scopeBlock, Block.NEEDS_SCOPE);
             }
         }
@@ -622,8 +617,8 @@
      * @see #needsParentScope()
      */
     private void setUsesGlobalSymbol() {
-        for (final Iterator<FunctionNode> fns = getLexicalContext().getFunctions(); fns.hasNext();) {
-            getLexicalContext().setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
+        for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
+            lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
         }
     }
 
@@ -635,7 +630,7 @@
     private Symbol findSymbol(final Block block, final String name) {
         // Search up block chain to locate symbol.
 
-        for (final Iterator<Block> blocks = getLexicalContext().getBlocks(block); blocks.hasNext();) {
+        for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
             // Find name.
             final Symbol symbol = blocks.next().getExistingSymbol(name);
             // If found then we are good.
@@ -656,11 +651,11 @@
     public Node leaveLiteralNode(final LiteralNode literalNode) {
         assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens
         assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported";
-        final Symbol symbol = new Symbol(getLexicalContext().getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
+        final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
         if (literalNode instanceof ArrayLiteralNode) {
             ((ArrayLiteralNode)literalNode).analyze();
         }
-        return end(literalNode.setSymbol(getLexicalContext(), symbol));
+        return end(literalNode.setSymbol(lc, symbol));
     }
 
     @Override
@@ -676,7 +671,7 @@
     @Override
     public Node leavePropertyNode(final PropertyNode propertyNode) {
         // assign a pseudo symbol to property name, see NASHORN-710
-        return propertyNode.setSymbol(getLexicalContext(), new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT));
+        return propertyNode.setSymbol(lc, new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT));
     }
 
     @Override
@@ -734,11 +729,11 @@
             type = Type.OBJECT;
         }
 
-        switchNode.setTag(newInternal(getLexicalContext().getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
+        switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
 
         end(switchNode);
 
-        return switchNode.setCases(getLexicalContext(), newCases);
+        return switchNode.setCases(lc, newCases);
     }
 
     @Override
@@ -761,7 +756,7 @@
         final IdentNode ident = varNode.getName();
         final String    name  = ident.getName();
 
-        final Symbol symbol = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR);
+        final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR);
         assert symbol != null;
 
         // NASHORN-467 - use before definition of vars - conservative
@@ -781,7 +776,6 @@
         final IdentNode ident = newVarNode.getName();
         final String    name  = ident.getName();
 
-        final LexicalContext lc = getLexicalContext();
         final Symbol  symbol = findSymbol(lc.getCurrentBlock(), ident.getName());
 
         if (init == null) {
@@ -834,7 +828,7 @@
 
     @Override
     public Node leaveDELETE(final UnaryNode unaryNode) {
-        final FunctionNode   currentFunctionNode = getLexicalContext().getCurrentFunction();
+        final FunctionNode   currentFunctionNode = lc.getCurrentFunction();
         final boolean        strictMode          = currentFunctionNode.isStrict();
         final Node           rhs                 = unaryNode.rhs();
         final Node           strictFlagNode      = LiteralNode.newInstance(unaryNode, strictMode).accept(this);
@@ -894,10 +888,10 @@
      * @return true if the symbol denoted by the specified name in the current lexical context defined in the program level.
      */
     private boolean isProgramLevelSymbol(final String name) {
-        for(final Iterator<Block> it = getLexicalContext().getBlocks(); it.hasNext();) {
+        for(final Iterator<Block> it = lc.getBlocks(); it.hasNext();) {
             final Block next = it.next();
             if(next.getExistingSymbol(name) != null) {
-                return next == getLexicalContext().getFunctionBody(getLexicalContext().getOutermostFunction());
+                return next == lc.getFunctionBody(lc.getOutermostFunction());
             }
         }
         throw new AssertionError("Couldn't find symbol " + name + " in the context");
@@ -914,14 +908,14 @@
     }
 
     private IdentNode compilerConstant(CompilerConstants cc) {
-        final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+        final FunctionNode functionNode = lc.getCurrentFunction();
         return (IdentNode)
             new IdentNode(
                 functionNode.getToken(),
                 functionNode.getFinish(),
                 cc.symbolName()).
                 setSymbol(
-                    getLexicalContext(),
+                    lc,
                     functionNode.compilerConstant(cc));
     }
 
@@ -999,7 +993,7 @@
         final Node lhs = binaryNode.lhs();
 
         if (lhs instanceof IdentNode) {
-            final Block     block = getLexicalContext().getCurrentBlock();
+            final Block     block = lc.getCurrentBlock();
             final IdentNode ident = (IdentNode)lhs;
             final String    name  = ident.getName();
 
@@ -1043,7 +1037,7 @@
     }
 
     private boolean isLocal(FunctionNode function, Symbol symbol) {
-        final FunctionNode definingFn = getLexicalContext().getDefiningFunction(symbol);
+        final FunctionNode definingFn = lc.getDefiningFunction(symbol);
         // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local
         return definingFn == null || definingFn == function;
     }
@@ -1329,7 +1323,7 @@
     @Override
     public Node leaveForNode(final ForNode forNode) {
         if (forNode.isForIn()) {
-            forNode.setIterator(newInternal(getLexicalContext().getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73
+            forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73
             /*
              * Iterators return objects, so we need to widen the scope of the
              * init variable if it, for example, has been assigned double type
@@ -1407,7 +1401,7 @@
             final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName());
             assert paramSymbol != null;
             assert paramSymbol.isParam();
-            newParams.add((IdentNode)param.setSymbol(getLexicalContext(), paramSymbol));
+            newParams.add((IdentNode)param.setSymbol(lc, paramSymbol));
 
             assert paramSymbol != null;
             Type type = functionNode.getHints().getParameterType(pos);
@@ -1439,10 +1433,10 @@
         FunctionNode newFunctionNode = functionNode;
 
         if (nparams == 0 || (specialize * 2) < nparams) {
-            newFunctionNode = newFunctionNode.clearSnapshot(getLexicalContext());
+            newFunctionNode = newFunctionNode.clearSnapshot(lc);
         }
 
-        return newFunctionNode.setParameters(getLexicalContext(), newParams);
+        return newFunctionNode.setParameters(lc, newParams);
     }
 
     /**
@@ -1506,7 +1500,7 @@
     }
 
     private Symbol exceptionSymbol() {
-        return newInternal(getLexicalContext().getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class));
+        return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class));
     }
 
     /**
@@ -1520,8 +1514,8 @@
      * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes
      */
     private Node ensureAssignmentSlots(final Node assignmentDest) {
-        final LexicalContext attrLexicalContext = getLexicalContext();
-        return assignmentDest.accept(new NodeVisitor() {
+        final LexicalContext attrLexicalContext = lc;
+        return assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public Node leaveIndexNode(final IndexNode indexNode) {
                 assert indexNode.getSymbol().isTemp();
@@ -1565,7 +1559,7 @@
         FunctionNode currentFunctionNode = functionNode;
         do {
             changed.clear();
-            final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor() {
+            final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
 
                 private Node widen(final Node node, final Type to) {
                     if (node instanceof LiteralNode) {
@@ -1579,7 +1573,7 @@
                             symbol = temporarySymbols.getTypedTemporarySymbol(to);
                         }
                         newType(symbol, to);
-                        final Node newNode = node.setSymbol(getLexicalContext(), symbol);
+                        final Node newNode = node.setSymbol(lc, symbol);
                         changed.add(newNode);
                         return newNode;
                     }
@@ -1622,7 +1616,7 @@
                     return newBinaryNode;
                 }
             });
-            getLexicalContext().replace(currentFunctionNode, newFunctionNode);
+            lc.replace(currentFunctionNode, newFunctionNode);
             currentFunctionNode = newFunctionNode;
         } while (!changed.isEmpty());
         return currentFunctionNode;
@@ -1643,12 +1637,12 @@
     }
 
     private Node ensureSymbol(final Type type, final Node node) {
-        LOG.info("New TEMPORARY added to ", getLexicalContext().getCurrentFunction().getName(), " type=", type);
-        return ensureSymbol(getLexicalContext(), type, node);
+        LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
+        return temporarySymbols.ensureSymbol(lc, type, node);
     }
 
     private Symbol newInternal(final String name, final Type type) {
-        final Symbol iter = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
+        final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
         iter.setType(type); // NASHORN-73
         return iter;
     }
@@ -1705,10 +1699,6 @@
         localUses.peek().add(name);
     }
 
-    private Node ensureSymbol(final LexicalContext lc, final Type type, final Node node) {
-        return temporarySymbols.ensureSymbol(lc, type, node);
-    }
-
     /**
      * Pessimistically promote all symbols in current function node to Object types
      * This is done when the function contains unevaluated black boxes such as
@@ -1717,7 +1707,7 @@
      * @param body body for the function node we are leaving
      */
     private static void objectifySymbols(final Block body) {
-        body.accept(new NodeVisitor() {
+        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             private void toObject(final Block block) {
                 for (final Symbol symbol : block.getSymbols()) {
                     if (!symbol.isTemp()) {
@@ -1761,7 +1751,7 @@
                 append("] ").
                 append(printNode ? node.toString() : "").
                 append(" in '").
-                append(getLexicalContext().getCurrentFunction().getName()).
+                append(lc.getCurrentFunction().getName()).
                 append("'");
             LOG.info(sb);
             LOG.indent();
@@ -1787,7 +1777,7 @@
                 append("] ").
                 append(printNode ? node.toString() : "").
                 append(" in '").
-                append(getLexicalContext().getCurrentFunction().getName());
+                append(lc.getCurrentFunction().getName());
 
             if (node.getSymbol() == null) {
                 sb.append(" <NO SYMBOL>");
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -52,16 +52,13 @@
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
 
 import java.io.PrintWriter;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Deque;
 import java.util.EnumSet;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
+import java.util.Locale;
 import java.util.TreeMap;
 
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
@@ -83,11 +80,11 @@
 import jdk.nashorn.internal.ir.ExecuteNode;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
@@ -150,7 +147,7 @@
  * The CodeGenerator visits nodes only once, tags them as resolved and emits
  * bytecode for them.
  */
-final class CodeGenerator extends NodeOperatorVisitor {
+final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> {
 
     /** Name of the Global object, cannot be referred to as .class, @see CodeGenerator */
     private static final String GLOBAL_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "Global";
@@ -168,23 +165,12 @@
     /** How many regexp fields have been emitted */
     private int regexFieldCount;
 
-    /** Map of shared scope call sites */
-    private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>();
-
-    /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */
-    private final Deque<CompileUnit> compileUnits = new ArrayDeque<>();
-
-    /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
-    private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();
-
-    /** The discard stack - whenever we enter a discard node we keep track of its return value status -
-     *  i.e. should we keep it or throw it away */
-    private final Deque<Node> discard = new ArrayDeque<>();
-
-    // A stack tracking the next free local variable slot in the blocks. There's one entry for every block
-    // currently on the lexical context stack.
-    private int[] nextFreeSlots = new int[16];
-    private int nextFreeSlotsSize = 0;
+    /** Line number for last statement. If we encounter a new line number, line number bytecode information
+     *  needs to be generated */
+    private int lastLineNumber = -1;
+
+    /** When should we stop caching regexp expressions in fields to limit bytecode size? */
+    private static final int MAX_REGEX_FIELDS = 2 * 1024;
 
     /** Current method emitter */
     private MethodEmitter method;
@@ -192,20 +178,16 @@
     /** Current compile unit */
     private CompileUnit unit;
 
-    private int lastLineNumber = -1;
-
-    /** When should we stop caching regexp expressions in fields to limit bytecode size? */
-    private static final int MAX_REGEX_FIELDS = 2 * 1024;
-
     private static final DebugLogger LOG   = new DebugLogger("codegen", "nashorn.codegen.debug");
 
+
     /**
      * Constructor.
      *
      * @param compiler
      */
     CodeGenerator(final Compiler compiler) {
-        super(new DynamicScopeTrackingLexicalContext());
+        super(new CodeGeneratorLexicalContext());
         this.compiler      = compiler;
         this.callSiteFlags = compiler.getEnv()._callsite_flags;
     }
@@ -217,37 +199,7 @@
      * @return the correct flags for a call site in the current function
      */
     int getCallSiteFlags() {
-        return getLexicalContext().getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
-    }
-
-    private void pushMethodEmitter(final MethodEmitter newMethod) {
-        methodEmitters.push(newMethod);
-        this.method = newMethod;
-    }
-
-    private void popMethodEmitter(final MethodEmitter oldMethod) {
-        assert methodEmitters.peek() == oldMethod;
-        methodEmitters.pop();
-        if (!methodEmitters.isEmpty()) {
-            this.method = methodEmitters.peek();
-        } else {
-            this.method = null;
-        }
-    }
-
-    private void push(final CompileUnit newUnit) {
-        compileUnits.push(newUnit);
-        this.unit = newUnit;
-    }
-
-    private void pop(final CompileUnit oldUnit) {
-        assert compileUnits.peek() == oldUnit;
-        compileUnits.pop();
-        if (!compileUnits.isEmpty()) {
-            this.unit = compileUnits.peek();
-        } else {
-            this.unit = null;
-        }
+        return lc.getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
     }
 
     /**
@@ -265,7 +217,7 @@
         }
 
         final String name   = symbol.getName();
-        final Source source = getLexicalContext().getCurrentFunction().getSource();
+        final Source source = lc.getCurrentFunction().getSource();
 
         if (CompilerConstants.__FILE__.name().equals(name)) {
             return method.load(source.getName());
@@ -291,88 +243,43 @@
     }
 
     /**
-     * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new
-     * variables introduced into them at run time - a with block or a function directly containing an eval call.
-     */
-    private static class DynamicScopeTrackingLexicalContext extends LexicalContext {
-        int dynamicScopeCount = 0;
-
-        @Override
-        public <T extends LexicalContextNode> T push(T node) {
-            if(isDynamicScopeBoundary(node)) {
-                ++dynamicScopeCount;
-            }
-            return super.push(node);
-        }
-
-        @Override
-        public <T extends LexicalContextNode> T pop(T node) {
-            final T popped = super.pop(node);
-            if(isDynamicScopeBoundary(popped)) {
-                --dynamicScopeCount;
-            }
-            return popped;
-        }
-
-        private boolean isDynamicScopeBoundary(LexicalContextNode node) {
-            if(node instanceof Block) {
-                // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
-                // processing of WithNode.expression too, but it should be unaffected.
-                return !isEmpty() && peek() instanceof WithNode;
-            } else if(node instanceof FunctionNode) {
-                // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
-                // variable into the function's scope), and it isn't strict (as evals in strict functions get an
-                // isolated scope).
-                return isFunctionDynamicScope((FunctionNode)node);
-            }
-            return false;
-        }
-    }
-
-    boolean inDynamicScope() {
-        return ((DynamicScopeTrackingLexicalContext)getLexicalContext()).dynamicScopeCount > 0;
-    }
-
-    static boolean isFunctionDynamicScope(FunctionNode fn) {
-        return fn.hasEval() && !fn.isStrict();
-    }
-
-    /**
      * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load
      *
      * @param function function to check for fast scope
      * @return true if fast scope
      */
     private boolean isFastScope(final Symbol symbol) {
-        if(!symbol.isScope()) {
+        if (!symbol.isScope()) {
             return false;
         }
-        final LexicalContext lc = getLexicalContext();
-        if(!inDynamicScope()) {
+
+        if (!lc.inDynamicScope()) {
             // If there's no with or eval in context, and the symbol is marked as scoped, it is fast scoped. Such a
             // symbol must either be global, or its defining block must need scope.
             assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
             return true;
         }
-        if(symbol.isGlobal()) {
+
+        if (symbol.isGlobal()) {
             // Shortcut: if there's a with or eval in context, globals can't be fast scoped
             return false;
         }
+
         // Otherwise, check if there's a dynamic scope between use of the symbol and its definition
         final String name = symbol.getName();
         boolean previousWasBlock = false;
         for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
             final LexicalContextNode node = it.next();
-            if(node instanceof Block) {
+            if (node instanceof Block) {
                 // If this block defines the symbol, then we can fast scope the symbol.
                 final Block block = (Block)node;
-                if(block.getExistingSymbol(name) == symbol) {
+                if (block.getExistingSymbol(name) == symbol) {
                     assert block.needsScope();
                     return true;
                 }
                 previousWasBlock = true;
             } else {
-                if((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && isFunctionDynamicScope((FunctionNode)node))) {
+                if ((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && CodeGeneratorLexicalContext.isFunctionDynamicScope((FunctionNode)node))) {
                     // If we hit a scope that can have symbols introduced into it at run time before finding the defining
                     // block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
                     // before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
@@ -387,16 +294,14 @@
     }
 
     private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
-        method.load(isFastScope(symbol) ? getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol) : -1);
-        final SharedScopeCall scopeCall = getScopeGet(valueType, symbol, flags | CALLSITE_FAST_SCOPE);
-        scopeCall.generateInvoke(method);
-        return method;
+        method.load(isFastScope(symbol) ? getScopeProtoDepth(lc.getCurrentBlock(), symbol) : -1);
+        final SharedScopeCall scopeCall = lc.getScopeGet(unit, valueType, symbol, flags | CALLSITE_FAST_SCOPE);
+        return scopeCall.generateInvoke(method);
     }
 
     private MethodEmitter loadFastScopeVar(final Type valueType, final Symbol symbol, final int flags, final boolean isMethod) {
         loadFastScopeProto(symbol, false);
-        method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
-        return method;
+        return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
     }
 
     private MethodEmitter storeFastScopeVar(final Type valueType, final Symbol symbol, final int flags) {
@@ -408,7 +313,7 @@
     private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
         int depth = 0;
         final String name = symbol.getName();
-        for(final Iterator<Block> blocks = getLexicalContext().getBlocks(startingBlock); blocks.hasNext();) {
+        for(final Iterator<Block> blocks = lc.getBlocks(startingBlock); blocks.hasNext();) {
             final Block currentBlock = blocks.next();
             if (currentBlock.getExistingSymbol(name) == symbol) {
                 return depth;
@@ -421,7 +326,7 @@
     }
 
     private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
-        final int depth = getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol);
+        final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
         assert depth != -1;
         if (depth > 0) {
             if (swap) {
@@ -464,7 +369,7 @@
          */
         final CodeGenerator codegen = this;
 
-        node.accept(new NodeVisitor() {
+        node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterIdentNode(final IdentNode identNode) {
                 loadIdent(identNode);
@@ -538,7 +443,7 @@
             final boolean isInternal = symbol.isParam() || symbol.isInternal() || symbol.isThis() || !symbol.canBeUndefined();
 
             if (symbol.hasSlot() && !isInternal) {
-                assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + getLexicalContext().getCurrentFunction();
+                assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + lc.getCurrentFunction();
                 if (symbol.getSymbolType().isNumber()) {
                     numbers.add(symbol);
                 } else if (symbol.getSymbolType().isObject()) {
@@ -595,7 +500,6 @@
         if (block.needsScope() && !block.isTerminal()) {
             popBlockScope(block);
         }
-        --nextFreeSlotsSize;
         return block;
     }
 
@@ -624,11 +528,11 @@
     public boolean enterBreakNode(final BreakNode breakNode) {
         lineNumber(breakNode);
 
-        final BreakableNode breakFrom = getLexicalContext().getBreakable(breakNode.getLabel());
-        for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(breakFrom); i++) {
+        final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabel());
+        for (int i = 0; i < lc.getScopeNestingLevelTo(breakFrom); i++) {
             closeWith();
         }
-        method.splitAwareGoto(getLexicalContext(), breakFrom.getBreakLabel());
+        method.splitAwareGoto(lc, breakFrom.getBreakLabel());
 
         return false;
     }
@@ -672,11 +576,12 @@
 
         final List<Node>   args            = callNode.getArgs();
         final Node         function        = callNode.getFunction();
-        final Block        currentBlock    = getLexicalContext().getCurrentBlock();
-
-        function.accept(new NodeVisitor() {
-
-            private void sharedScopeCall(final IdentNode identNode, final int flags) {
+        final Block        currentBlock    = lc.getCurrentBlock();
+        final CodeGeneratorLexicalContext codegenLexicalContext = lc;
+
+        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+
+            private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
                 final Symbol symbol = identNode.getSymbol();
                 int    scopeCallFlags = flags;
                 method.loadCompilerConstant(SCOPE);
@@ -688,8 +593,8 @@
                 }
                 loadArgs(args);
                 final Type[] paramTypes = method.getTypesFromStack(args.size());
-                final SharedScopeCall scopeCall = getScopeCall(symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags);
-                scopeCall.generateInvoke(method);
+                final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags);
+                return scopeCall.generateInvoke(method);
             }
 
             private void scopeCall(final IdentNode node, final int flags) {
@@ -756,7 +661,7 @@
                         evalCall(node, flags);
                     } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
                             || (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD)
-                            || CodeGenerator.this.inDynamicScope()) {
+                            || CodeGenerator.this.lc.inDynamicScope()) {
                         scopeCall(node, flags);
                     } else {
                         sharedScopeCall(node, flags);
@@ -845,11 +750,11 @@
     public boolean enterContinueNode(final ContinueNode continueNode) {
         lineNumber(continueNode);
 
-        final LoopNode continueTo = getLexicalContext().getContinueTo(continueNode.getLabel());
-        for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(continueTo); i++) {
+        final LoopNode continueTo = lc.getContinueTo(continueNode.getLabel());
+        for (int i = 0; i < lc.getScopeNestingLevelTo(continueTo); i++) {
             closeWith();
         }
-        method.splitAwareGoto(getLexicalContext(), continueTo.getContinueLabel());
+        method.splitAwareGoto(lc, continueTo.getContinueLabel());
 
         return false;
     }
@@ -875,90 +780,89 @@
     public boolean enterForNode(final ForNode forNode) {
         lineNumber(forNode);
 
-        final Node  test   = forNode.getTest();
-        final Block body   = forNode.getBody();
-        final Node  modify = forNode.getModify();
-
-        final Label breakLabel    = forNode.getBreakLabel();
-        final Label continueLabel = forNode.getContinueLabel();
-        final Label loopLabel     = new Label("loop");
-
-        Node init = forNode.getInit();
-
         if (forNode.isForIn()) {
-            final Symbol iter = forNode.getIterator();
-
-            // We have to evaluate the optional initializer expression
-            // of the iterator variable of the for-in statement.
-            if (init instanceof VarNode) {
-                init.accept(this);
-                init = ((VarNode)init).getName();
-            }
-
-            load(modify);
-            assert modify.getType().isObject();
-            method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
-            method.store(iter);
-            method._goto(continueLabel);
-            method.label(loopLabel);
-
-            new Store<Node>(init) {
-                @Override
-                protected void storeNonDiscard() {
-                    return;
-                }
-                @Override
-                protected void evaluate() {
-                    method.load(iter);
-                    method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
-                }
-            }.store();
-
-            body.accept(this);
-
-            method.label(continueLabel);
-            method.load(iter);
-            method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
-            method.ifne(loopLabel);
-            method.label(breakLabel);
+            enterForIn(forNode);
         } else {
-            if (init != null) {
-                init.accept(this);
-            }
-
-            final Label testLabel = new Label("test");
-
-            method._goto(testLabel);
-            method.label(loopLabel);
-            body.accept(this);
-            method.label(continueLabel);
-
-            if (!body.isTerminal() && modify != null) {
-                load(modify);
-            }
-
-            method.label(testLabel);
-            if (test != null) {
-                new BranchOptimizer(this, method).execute(test, loopLabel, true);
-            } else {
-                method._goto(loopLabel);
-            }
-
-            method.label(breakLabel);
+            enterFor(forNode);
         }
 
         return false;
     }
 
-    private static int assignSlots(final Block block, final int firstSlot) {
-        int nextSlot = firstSlot;
-        for (final Symbol symbol : block.getSymbols()) {
-            if (symbol.hasSlot()) {
-                symbol.setSlot(nextSlot);
-                nextSlot += symbol.slotCount();
+    private void enterFor(final ForNode forNode) {
+        final Node  init   = forNode.getInit();
+        final Node  test   = forNode.getTest();
+        final Block body   = forNode.getBody();
+        final Node  modify = forNode.getModify();
+
+        if (init != null) {
+            init.accept(this);
+        }
+
+        final Label loopLabel = new Label("loop");
+        final Label testLabel = new Label("test");
+
+        method._goto(testLabel);
+        method.label(loopLabel);
+        body.accept(this);
+        method.label(forNode.getContinueLabel());
+
+        if (!body.isTerminal() && modify != null) {
+            load(modify);
+        }
+
+        method.label(testLabel);
+        if (test != null) {
+            new BranchOptimizer(this, method).execute(test, loopLabel, true);
+        } else {
+            method._goto(loopLabel);
+        }
+
+        method.label(forNode.getBreakLabel());
+    }
+
+    private void enterForIn(final ForNode forNode) {
+        final Block body   = forNode.getBody();
+        final Node  modify = forNode.getModify();
+
+        final Symbol iter      = forNode.getIterator();
+        final Label  loopLabel = new Label("loop");
+
+        Node init = forNode.getInit();
+
+        // We have to evaluate the optional initializer expression
+        // of the iterator variable of the for-in statement.
+        if (init instanceof VarNode) {
+            init.accept(this);
+            init = ((VarNode)init).getName();
+        }
+
+        load(modify);
+        assert modify.getType().isObject();
+        method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
+        method.store(iter);
+        method._goto(forNode.getContinueLabel());
+        method.label(loopLabel);
+
+        new Store<Node>(init) {
+            @Override
+            protected void storeNonDiscard() {
+                return;
             }
-        }
-        return nextSlot;
+            @Override
+            protected void evaluate() {
+                method.load(iter);
+                method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
+            }
+        }.store();
+
+        body.accept(this);
+
+        method.label(forNode.getContinueLabel());
+        method.load(iter);
+        method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
+        method.ifne(loopLabel);
+        method.label(forNode.getBreakLabel());
     }
 
     /**
@@ -967,24 +871,11 @@
      * @param block block with local vars.
      */
     private void initLocals(final Block block) {
-        final boolean isFunctionBody = getLexicalContext().isFunctionBody();
-
-        final int nextFreeSlot;
-        if (isFunctionBody) {
-            // On entry to function, start with slot 0
-            nextFreeSlot = 0;
-        } else {
-            // Otherwise, continue from previous block's first free slot
-            nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
-        }
-        if(nextFreeSlotsSize == nextFreeSlots.length) {
-            final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
-            System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
-            nextFreeSlots = newNextFreeSlots;
-        }
-        nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
-
-        final FunctionNode function = getLexicalContext().getCurrentFunction();
+        lc.nextFreeSlot(block);
+
+        final boolean isFunctionBody = lc.isFunctionBody();
+
+        final FunctionNode function = lc.getCurrentFunction();
         if (isFunctionBody) {
             /* Fix the predefined slots so they have numbers >= 0, like varargs. */
             if (function.needsParentScope()) {
@@ -1023,7 +914,7 @@
                 }
 
                 if (symbol.isVar()) {
-                    if(varsInScope || symbol.isScope()) {
+                    if (varsInScope || symbol.isScope()) {
                         nameList.add(symbol.getName());
                         newSymbols.add(symbol);
                         values.add(null);
@@ -1062,7 +953,7 @@
 
                 @Override
                 protected void loadScope(MethodEmitter m) {
-                    if(function.needsParentScope()) {
+                    if (function.needsParentScope()) {
                         m.loadCompilerConstant(SCOPE);
                     } else {
                         m.loadNull();
@@ -1096,7 +987,7 @@
 
     private void initArguments(final FunctionNode function) {
         method.loadCompilerConstant(VARARGS);
-        if(function.needsCallee()) {
+        if (function.needsCallee()) {
             method.loadCompilerConstant(CALLEE);
         } else {
             // If function is strict mode, "arguments.callee" is not populated, so we don't necessarily need the
@@ -1126,10 +1017,10 @@
         LOG.info("=== BEGIN ", functionNode.getName());
 
         assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode);
-        push(functionNode.getCompileUnit());
-        assert !compileUnits.isEmpty();
-
-        pushMethodEmitter(unit.getClassEmitter().method(functionNode));
+        unit = lc.pushCompileUnit(functionNode.getCompileUnit());
+        assert lc.hasCompileUnits();
+
+        method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
         // Mark end for variable tables.
         method.begin();
 
@@ -1140,11 +1031,11 @@
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         try {
             method.end(); // wrap up this method
-            pop(functionNode.getCompileUnit());
-            popMethodEmitter(method);
+            unit   = lc.popCompileUnit(functionNode.getCompileUnit());
+            method = lc.popMethodEmitter(method);
             LOG.info("=== END ", functionNode.getName());
 
-            final FunctionNode newFunctionNode = functionNode.setState(getLexicalContext(), CompilationState.EMITTED);
+            final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED);
 
             newFunctionObject(newFunctionNode, functionNode);
             return newFunctionNode;
@@ -1238,16 +1129,16 @@
             final MethodEmitter savedMethod = method;
 
             for (final ArrayUnit arrayUnit : units) {
-                push(arrayUnit.getCompileUnit());
+                unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
 
                 final String className = unit.getUnitClassName();
-                final String name      = getLexicalContext().getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName());
+                final String name      = lc.getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName());
                 final String signature = methodDescriptor(type, Object.class, ScriptFunction.class, ScriptObject.class, type);
 
                 final MethodEmitter me = unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature);
-                pushMethodEmitter(me);
-
-                method.setFunctionNode(getLexicalContext().getCurrentFunction());
+                method = lc.pushMethodEmitter(me);
+
+                method.setFunctionNode(lc.getCurrentFunction());
                 method.begin();
 
                 fixScopeSlot();
@@ -1260,7 +1151,7 @@
 
                 method._return();
                 method.end();
-                popMethodEmitter(me);
+                method = lc.popMethodEmitter(me);
 
                 assert method == savedMethod;
                 method.loadCompilerConstant(THIS);
@@ -1271,7 +1162,7 @@
                 method.swap();
                 method.invokestatic(className, name, signature);
 
-                pop(unit);
+                unit = lc.popCompileUnit(unit);
             }
 
             return method;
@@ -1407,7 +1298,7 @@
             return loadRegexToken(regexToken);
         }
         // emit field
-        final String       regexName    = getLexicalContext().getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
+        final String       regexName    = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
         final ClassEmitter classEmitter = unit.getClassEmitter();
 
         classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
@@ -1545,7 +1436,7 @@
 
         method.registerReturn();
 
-        final Type returnType = getLexicalContext().getCurrentFunction().getReturnType();
+        final Type returnType = lc.getCurrentFunction().getReturnType();
 
         final Node expression = returnNode.getExpression();
         if (expression != null) {
@@ -1756,7 +1647,7 @@
 
         final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
 
-        final FunctionNode fn   = getLexicalContext().getCurrentFunction();
+        final FunctionNode fn   = lc.getCurrentFunction();
         final String className  = splitCompileUnit.getUnitClassName();
         final String name       = splitNode.getName();
 
@@ -1767,7 +1658,7 @@
                 new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class};
 
         final MethodEmitter caller = method;
-        push(splitCompileUnit);
+        unit = lc.pushCompileUnit(splitCompileUnit);
 
         final Call splitCall = staticCallNoLookup(
             className,
@@ -1781,8 +1672,7 @@
                         rtype,
                         ptypes);
 
-        pushMethodEmitter(splitEmitter);
-
+        method = lc.pushMethodEmitter(splitEmitter);
         method.setFunctionNode(fn);
 
         if (fn.needsCallee()) {
@@ -1809,7 +1699,7 @@
     }
 
     private void fixScopeSlot() {
-        if (getLexicalContext().getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
+        if (lc.getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
             // TODO hack to move the scope to the expected slot (that's needed because split methods reuse the same slots as the root method)
             method.load(Type.typeFor(ScriptObject.class), SCOPE.slot());
             method.storeCompilerConstant(SCOPE);
@@ -1826,15 +1716,15 @@
             // Wrap up this method.
 
             method.loadCompilerConstant(RETURN);
-            method._return(getLexicalContext().getCurrentFunction().getReturnType());
+            method._return(lc.getCurrentFunction().getReturnType());
             method.end();
 
-            pop(splitNode.getCompileUnit());
-            popMethodEmitter(method);
+            unit   = lc.popCompileUnit(splitNode.getCompileUnit());
+            method = lc.popMethodEmitter(method);
 
         } catch (final Throwable t) {
             Context.printStackTrace(t);
-            final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + getLexicalContext().getCurrentFunction().getSource().getName());
+            final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + lc.getCurrentFunction().getSource().getName());
             e.initCause(t);
             throw e;
         }
@@ -1862,7 +1752,7 @@
             //has to be zero
             caller.label(new Label("split_return"));
             method.loadCompilerConstant(RETURN);
-            caller._return(getLexicalContext().getCurrentFunction().getReturnType());
+            caller._return(lc.getCurrentFunction().getReturnType());
             caller.label(breakLabel);
         } else {
             assert !targets.isEmpty();
@@ -1879,14 +1769,14 @@
                 caller.label(labels[i - low]);
                 if (i == 0) {
                     caller.loadCompilerConstant(RETURN);
-                    caller._return(getLexicalContext().getCurrentFunction().getReturnType());
+                    caller._return(lc.getCurrentFunction().getReturnType());
                 } else {
                     // Clear split state.
                     caller.loadCompilerConstant(SCOPE);
                     caller.checkcast(Scope.class);
                     caller.load(-1);
                     caller.invoke(Scope.SET_SPLIT_STATE);
-                    caller.splitAwareGoto(getLexicalContext(), targets.get(i - 1));
+                    caller.splitAwareGoto(lc, targets.get(i - 1));
                 }
             }
             caller.label(breakLabel);
@@ -2028,9 +1918,16 @@
     public boolean enterThrowNode(final ThrowNode throwNode) {
         lineNumber(throwNode);
 
+        if (throwNode.isSyntheticRethrow()) {
+            //do not wrap whatever this is in an ecma exception, just rethrow it
+            load(throwNode.getExpression());
+            method.athrow();
+            return false;
+        }
+
         method._new(ECMAException.class).dup();
 
-        final Source source     = getLexicalContext().getCurrentFunction().getSource();
+        final Source source     = lc.getCurrentFunction().getSource();
 
         final Node   expression = throwNode.getExpression();
         final int    position   = throwNode.position();
@@ -2081,7 +1978,7 @@
             //TODO this is very ugly - try not to call enter/leave methods directly
             //better to use the implicit lexical context scoping given by the visitor's
             //accept method.
-            getLexicalContext().push(catchBlock);
+            lc.push(catchBlock);
             enterBlock(catchBlock);
 
             final CatchNode catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
@@ -2094,15 +1991,19 @@
                 protected void storeNonDiscard() {
                     return;
                 }
+
                 @Override
                 protected void evaluate() {
+                    if (catchNode.isSyntheticRethrow()) {
+                        method.load(symbol);
+                        return;
+                    }
                     /*
                      * If caught object is an instance of ECMAException, then
                      * bind obj.thrown to the script catch var. Or else bind the
                      * caught object itself to the script catch var.
                      */
                     final Label notEcmaException = new Label("no_ecma_exception");
-
                     method.load(symbol).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
                     method.checkcast(ECMAException.class); //TODO is this necessary?
                     method.getField(ECMAException.THROWN);
@@ -2137,7 +2038,7 @@
             }
 
             leaveBlock(catchBlock);
-            getLexicalContext().pop(catchBlock);
+            lc.pop(catchBlock);
         }
 
         method.label(skip);
@@ -2234,7 +2135,7 @@
         final boolean hasScope = method.hasScope();
 
         final Label tryLabel;
-        if(hasScope) {
+        if (hasScope) {
             tryLabel = new Label("with_try");
             method.label(tryLabel);
             method.loadCompilerConstant(SCOPE);
@@ -2245,7 +2146,7 @@
         load(expression);
         assert expression.getType().isObject() : "with expression needs to be object: " + expression;
 
-        if(hasScope) {
+        if (hasScope) {
             // Construct a WithObject if we have a scope
             method.invoke(ScriptRuntime.OPEN_WITH);
             method.storeCompilerConstant(SCOPE);
@@ -2285,7 +2186,7 @@
     @Override
     public boolean enterADD(final UnaryNode unaryNode) {
         load(unaryNode.rhs());
-        assert unaryNode.rhs().getType().isNumber();
+        assert unaryNode.rhs().getType().isNumber() : unaryNode.rhs().getType() + " "+ unaryNode.getSymbol();
         method.store(unaryNode.getSymbol());
 
         return false;
@@ -2320,7 +2221,7 @@
                 }
                 method.convert(Type.OBJECT);
             } else if (value instanceof Boolean) {
-                method.getField(staticField(Boolean.class, value.toString().toUpperCase(), Boolean.class));
+                method.getField(staticField(Boolean.class, value.toString().toUpperCase(Locale.ENGLISH), Boolean.class));
             } else {
                 load(rhs);
                 method.convert(unaryNode.getType());
@@ -2387,13 +2288,13 @@
     public boolean enterDISCARD(final UnaryNode unaryNode) {
         final Node rhs = unaryNode.rhs();
 
-        discard.push(rhs);
+        lc.pushDiscard(rhs);
         load(rhs);
 
-        if (discard.peek() == rhs) {
+        if (lc.getCurrentDiscard() == rhs) {
             assert !rhs.isAssignment();
             method.pop();
-            discard.pop();
+            lc.popDiscard();
         }
 
         return false;
@@ -2445,7 +2346,7 @@
         assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs);
         load(lhs);
         load(rhs);
-        method.add();
+        method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
         method.store(symbol);
         return null;
     }
@@ -2989,53 +2890,12 @@
      * Generate all shared scope calls generated during codegen.
      */
     protected void generateScopeCalls() {
-        for (final SharedScopeCall scopeAccess : scopeCalls.values()) {
+        for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
             scopeAccess.generateScopeCall();
         }
     }
 
     /**
-     * Get a shared static method representing a dynamic scope callsite.
-     *
-     * @param symbol the symbol
-     * @param valueType the value type of the symbol
-     * @param returnType the return type
-     * @param paramTypes the parameter types
-     * @param flags the callsite flags
-     * @return an object representing a shared scope call
-     */
-    private SharedScopeCall getScopeCall(final Symbol symbol, final Type valueType, final Type returnType,
-                                         final Type[] paramTypes, final int flags) {
-
-        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags);
-        if (scopeCalls.containsKey(scopeCall)) {
-            return scopeCalls.get(scopeCall);
-        }
-        scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall"));
-        scopeCalls.put(scopeCall, scopeCall);
-        return scopeCall;
-    }
-
-    /**
-     * Get a shared static method representing a dynamic scope get access.
-     *
-     * @param type the type of the variable
-     * @param symbol the symbol
-     * @param flags the callsite flags
-     * @return an object representing a shared scope call
-     */
-    private SharedScopeCall getScopeGet(final Type type, final Symbol symbol, final int flags) {
-
-        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
-        if (scopeCalls.containsKey(scopeCall)) {
-            return scopeCalls.get(scopeCall);
-        }
-        scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall"));
-        scopeCalls.put(scopeCall, scopeCall);
-        return scopeCall;
-    }
-
-    /**
      * Debug code used to print symbols
      *
      * @param block the block we are in
@@ -3129,14 +2989,14 @@
 
         private void prologue() {
             final Symbol targetSymbol = target.getSymbol();
-            final Symbol scopeSymbol  = getLexicalContext().getCurrentFunction().compilerConstant(SCOPE);
+            final Symbol scopeSymbol  = lc.getCurrentFunction().compilerConstant(SCOPE);
 
             /**
              * This loads the parts of the target, e.g base and index. they are kept
              * on the stack throughout the store and used at the end to execute it
              */
 
-            target.accept(new NodeVisitor() {
+            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 public boolean enterIdentNode(final IdentNode node) {
                     if (targetSymbol.isScope()) {
@@ -3203,22 +3063,21 @@
          * @return the quick symbol
          */
         private Symbol quickSymbol(final Type type, final String prefix) {
-            final String name = getLexicalContext().getCurrentFunction().uniqueName(prefix);
+            final String name = lc.getCurrentFunction().uniqueName(prefix);
             final Symbol symbol = new Symbol(name, IS_TEMP | IS_INTERNAL);
 
             symbol.setType(type);
-            final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
-            nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
-            symbol.setSlot(quickSlot);
+
+            symbol.setSlot(lc.quickSlot(symbol));
 
             return symbol;
         }
 
         // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
         protected void storeNonDiscard() {
-            if (discard.peek() == assignNode) {
+            if (lc.getCurrentDiscard() == assignNode) {
                 assert assignNode.isAssignment();
-                discard.pop();
+                lc.popDiscard();
                 return;
             }
 
@@ -3246,7 +3105,7 @@
              */
             method.convert(target.getType());
 
-            target.accept(new NodeVisitor() {
+            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 protected boolean enterDefault(Node node) {
                     throw new AssertionError("Unexpected node " + node + " in store epilogue");
@@ -3308,7 +3167,6 @@
     }
 
     private void newFunctionObject(final FunctionNode functionNode, final FunctionNode originalFunctionNode) {
-        final LexicalContext lc = getLexicalContext();
         assert lc.peek() == functionNode;
         // We don't emit a ScriptFunction on stack for:
         // 1. the outermost compiled function (as there's no code being generated in its outer context that'd need it
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,235 @@
+/*
+ * 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.codegen;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.WithNode;
+
+/**
+ * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new
+ * variables introduced into them at run time - a with block or a function directly containing an eval call.
+ * Furthermore, this class keeps track of current discard state, which the current method emitter being used is,
+ * the current compile unit, and local variable indexes
+ */
+final class CodeGeneratorLexicalContext extends LexicalContext {
+    private int dynamicScopeCount;
+
+    /** Map of shared scope call sites */
+    private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>();
+
+    /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */
+    private final Deque<CompileUnit> compileUnits = new ArrayDeque<>();
+
+    /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
+    private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();
+
+    /** The discard stack - whenever we enter a discard node we keep track of its return value status -
+     *  i.e. should we keep it or throw it away */
+    private final Deque<Node> discard = new ArrayDeque<>();
+
+    /** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
+     *  currently on the lexical context stack. */
+    private int[] nextFreeSlots = new int[16];
+
+    /** size of next free slot vector */
+    private int nextFreeSlotsSize;
+
+    @Override
+    public <T extends LexicalContextNode> T push(final T node) {
+        if (isDynamicScopeBoundary(node)) {
+            ++dynamicScopeCount;
+        }
+        return super.push(node);
+    }
+
+    @Override
+    public <T extends LexicalContextNode> T pop(final T node) {
+        final T popped = super.pop(node);
+        if (isDynamicScopeBoundary(popped)) {
+            --dynamicScopeCount;
+        }
+        if (node instanceof Block) {
+            --nextFreeSlotsSize;
+        }
+        return popped;
+    }
+
+    private boolean isDynamicScopeBoundary(final LexicalContextNode node) {
+        if (node instanceof Block) {
+            // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
+            // processing of WithNode.expression too, but it should be unaffected.
+            return !isEmpty() && peek() instanceof WithNode;
+        } else if (node instanceof FunctionNode) {
+            // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
+            // variable into the function's scope), and it isn't strict (as evals in strict functions get an
+            // isolated scope).
+            return isFunctionDynamicScope((FunctionNode)node);
+        }
+        return false;
+    }
+
+    boolean inDynamicScope() {
+        return dynamicScopeCount > 0;
+    }
+
+    static boolean isFunctionDynamicScope(FunctionNode fn) {
+        return fn.hasEval() && !fn.isStrict();
+    }
+
+    MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
+        methodEmitters.push(newMethod);
+        return newMethod;
+    }
+
+    MethodEmitter popMethodEmitter(final MethodEmitter oldMethod) {
+        assert methodEmitters.peek() == oldMethod;
+        methodEmitters.pop();
+        return methodEmitters.isEmpty() ? null : methodEmitters.peek();
+    }
+
+    CompileUnit pushCompileUnit(final CompileUnit newUnit) {
+        compileUnits.push(newUnit);
+        return newUnit;
+    }
+
+    CompileUnit popCompileUnit(final CompileUnit oldUnit) {
+        assert compileUnits.peek() == oldUnit;
+        compileUnits.pop();
+        return compileUnits.isEmpty() ? null : compileUnits.peek();
+    }
+
+    boolean hasCompileUnits() {
+        return !compileUnits.isEmpty();
+    }
+
+    Collection<SharedScopeCall> getScopeCalls() {
+        return Collections.unmodifiableCollection(scopeCalls.values());
+    }
+
+    /**
+     * Get a shared static method representing a dynamic scope callsite.
+     *
+     * @param unit current compile unit
+     * @param symbol the symbol
+     * @param valueType the value type of the symbol
+     * @param returnType the return type
+     * @param paramTypes the parameter types
+     * @param flags the callsite flags
+     * @return an object representing a shared scope call
+     */
+    SharedScopeCall getScopeCall(final CompileUnit unit, final Symbol symbol, final Type valueType, final Type returnType, final Type[] paramTypes, final int flags) {
+        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags);
+        if (scopeCalls.containsKey(scopeCall)) {
+            return scopeCalls.get(scopeCall);
+        }
+        scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+        scopeCalls.put(scopeCall, scopeCall);
+        return scopeCall;
+    }
+
+    /**
+     * Get a shared static method representing a dynamic scope get access.
+     *
+     * @param unit current compile unit
+     * @param type the type of the variable
+     * @param symbol the symbol
+     * @param flags the callsite flags
+     * @return an object representing a shared scope call
+     */
+    SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) {
+        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
+        if (scopeCalls.containsKey(scopeCall)) {
+            return scopeCalls.get(scopeCall);
+        }
+        scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+        scopeCalls.put(scopeCall, scopeCall);
+        return scopeCall;
+    }
+
+
+    void nextFreeSlot(final Block block) {
+        final boolean isFunctionBody = isFunctionBody();
+
+        final int nextFreeSlot;
+        if (isFunctionBody) {
+            // On entry to function, start with slot 0
+            nextFreeSlot = 0;
+        } else {
+            // Otherwise, continue from previous block's first free slot
+            nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
+        }
+        if (nextFreeSlotsSize == nextFreeSlots.length) {
+            final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
+            System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
+            nextFreeSlots = newNextFreeSlots;
+        }
+        nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
+    }
+
+    private static int assignSlots(final Block block, final int firstSlot) {
+        int nextSlot = firstSlot;
+        for (final Symbol symbol : block.getSymbols()) {
+            if (symbol.hasSlot()) {
+                symbol.setSlot(nextSlot);
+                nextSlot += symbol.slotCount();
+            }
+        }
+        return nextSlot;
+    }
+
+    void pushDiscard(final Node node) {
+        discard.push(node);
+    }
+
+    Node popDiscard() {
+        return discard.pop();
+    }
+
+    Node getCurrentDiscard() {
+        return discard.peek();
+    }
+
+    int quickSlot(final Symbol symbol) {
+        final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
+        nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
+        return quickSlot;
+    }
+
+}
+
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Jul 05 18:57:52 2017 +0200
@@ -11,20 +11,27 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
+
+import jdk.nashorn.internal.codegen.types.Range;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.TemporarySymbols;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.ECMAErrors;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
@@ -66,7 +73,7 @@
 
             FunctionNode newFunctionNode = outermostFunctionNode;
 
-            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() {
+            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 // self references are done with invokestatic and thus cannot
                 // have trampolines - never lazy
                 @Override
@@ -99,10 +106,9 @@
                 lazy.remove(node);
             }
 
-            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeOperatorVisitor() {
+            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 public Node leaveFunctionNode(final FunctionNode functionNode) {
-                    final LexicalContext lc = getLexicalContext();
                     if (lazy.contains(functionNode)) {
                         Compiler.LOG.fine(
                                 "Marking ",
@@ -174,7 +180,7 @@
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
             final TemporarySymbols ts = compiler.getTemporarySymbols();
             final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
-            if(compiler.getEnv()._print_mem_usage) {
+            if (compiler.getEnv()._print_mem_usage) {
                 Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
             }
             return newFunctionNode;
@@ -186,12 +192,11 @@
          * @param functionNode node where to start iterating
          */
         private FunctionNode enterAttr(final FunctionNode functionNode, final TemporarySymbols ts) {
-            return (FunctionNode)functionNode.accept(new NodeVisitor() {
+            return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 public Node leaveFunctionNode(final FunctionNode node) {
-                    final LexicalContext lc = getLexicalContext();
                     if (node.isLazy()) {
-                        FunctionNode newNode = node.setReturnType(getLexicalContext(), Type.OBJECT);
+                        FunctionNode newNode = node.setReturnType(lc, Type.OBJECT);
                         return ts.ensureSymbol(lc, Type.OBJECT, newNode);
                     }
                     //node may have a reference here that needs to be nulled if it was referred to by
@@ -208,6 +213,89 @@
     },
 
     /*
+     * Range analysis
+     *    Conservatively prove that certain variables can be narrower than
+     *    the most generic number type
+     */
+    RANGE_ANALYSIS_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
+            if (!compiler.getEnv()._range_analysis) {
+                return fn;
+            }
+
+            FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
+            final List<ReturnNode> returns = new ArrayList<>();
+
+            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>();
+
+                @Override
+                public boolean enterFunctionNode(final FunctionNode functionNode) {
+                    returnStack.push(new ArrayList<ReturnNode>());
+                    return true;
+                }
+
+                @Override
+                public Node leaveFunctionNode(final FunctionNode functionNode) {
+                    Type returnType = Type.UNKNOWN;
+                    for (final ReturnNode ret : returnStack.pop()) {
+                        if (ret.getExpression() == null) {
+                            returnType = Type.OBJECT;
+                            break;
+                        }
+                        returnType = Type.widest(returnType, ret.getExpression().getType());
+                    }
+                    return functionNode.setReturnType(lc, returnType);
+                }
+
+                @Override
+                public Node leaveReturnNode(final ReturnNode returnNode) {
+                    final ReturnNode result = (ReturnNode)leaveDefault(returnNode);
+                    returns.add(result);
+                    return result;
+                }
+
+                @Override
+                public Node leaveDefault(final Node node) {
+                    final Symbol symbol = node.getSymbol();
+                    if (symbol != null) {
+                        final Range range  = symbol.getRange();
+                        final Type  symbolType = symbol.getSymbolType();
+                        if (!symbolType.isNumeric()) {
+                            return node;
+                        }
+                        final Type  rangeType  = range.getType();
+                        if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
+                            RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
+                            return node.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
+                        }
+                    }
+                    return node;
+                }
+            });
+
+            Type returnType = Type.UNKNOWN;
+            for (final ReturnNode node : returns) {
+                if (node.getExpression() != null) {
+                    returnType = Type.widest(returnType, node.getExpression().getType());
+                } else {
+                    returnType = Type.OBJECT;
+                    break;
+                }
+            }
+
+            return newFunctionNode.setReturnType(null, returnType);
+        }
+
+        @Override
+        public String toString() {
+            return "[Range Analysis]";
+        }
+    },
+
+
+    /*
      * Splitter Split the AST into several compile units based on a size
      * heuristic Splitter needs attributed AST for weight calculations (e.g. is
      * a + b a ScriptRuntime.ADD with call overhead or a dadd with much less).
@@ -218,7 +306,6 @@
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
             final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
 
-//            assert fn.isProgram() ;
             final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
 
             assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Jul 05 18:57:52 2017 +0200
@@ -99,7 +99,7 @@
 
     private boolean strict;
 
-    private CodeInstaller<ScriptEnvironment> installer;
+    private final CodeInstaller<ScriptEnvironment> installer;
 
     private final TemporarySymbols temporarySymbols = new TemporarySymbols();
 
@@ -219,6 +219,7 @@
         CompilationPhase.CONSTANT_FOLDING_PHASE,
         CompilationPhase.LOWERING_PHASE,
         CompilationPhase.ATTRIBUTION_PHASE,
+        CompilationPhase.RANGE_ANALYSIS_PHASE,
         CompilationPhase.SPLITTING_PHASE,
         CompilationPhase.TYPE_FINALIZATION_PHASE,
         CompilationPhase.BYTECODE_GENERATION_PHASE);
@@ -384,6 +385,8 @@
         if (info) {
             final StringBuilder sb = new StringBuilder();
             sb.append("Compile job for '").
+                append(newFunctionNode.getSource()).
+                append(':').
                 append(newFunctionNode.getName()).
                 append("' finished");
 
@@ -487,7 +490,7 @@
         }
 
         if (sb != null) {
-            LOG.info(sb);
+            LOG.fine(sb);
         }
 
         return rootClass;
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Wed Jul 05 18:57:52 2017 +0200
@@ -262,7 +262,7 @@
      * @return the internal descriptor for this type
      */
     public static String typeDescriptor(final Class<?> clazz) {
-        return Type.getDescriptor(clazz);
+        return Type.typeFor(clazz).getDescriptor();
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Wed Jul 05 18:57:52 2017 +0200
@@ -31,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.Assignment;
@@ -84,13 +85,14 @@
  * and frame optimizations
  */
 
-final class FinalizeTypes extends NodeOperatorVisitor {
+final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
 
     private static final DebugLogger LOG = new DebugLogger("finalize");
 
     private final TemporarySymbols temporarySymbols;
 
     FinalizeTypes(final TemporarySymbols temporarySymbols) {
+        super(new LexicalContext());
         this.temporarySymbols = temporarySymbols;
     }
 
@@ -233,7 +235,7 @@
 
     private boolean symbolIsInteger(Node node) {
         final Symbol symbol = node.getSymbol();
-        assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + getLexicalContext().getCurrentFunction().getSource();
+        assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource();
         return true;
     }
 
@@ -382,12 +384,10 @@
         final Node test   = forNode.getTest();
         final Node modify = forNode.getModify();
 
-        final LexicalContext lc = getLexicalContext();
-
         if (forNode.isForIn()) {
             return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400
         }
-        assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + getLexicalContext().getCurrentFunction();
+        assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
 
         return forNode.
             setInit(lc, init == null ? null : discard(init)).
@@ -419,7 +419,7 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-        return functionNode.setState(getLexicalContext(), CompilationState.FINALIZED);
+        return functionNode.setState(lc, CompilationState.FINALIZED);
     }
 
     @Override
@@ -450,7 +450,7 @@
     public Node leaveReturnNode(final ReturnNode returnNode) {
         final Node expr = returnNode.getExpression();
         if (expr != null) {
-            return returnNode.setExpression(convert(expr, getLexicalContext().getCurrentFunction().getReturnType()));
+            return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType()));
         }
         return returnNode;
     }
@@ -482,8 +482,8 @@
         }
 
         return switchNode.
-            setExpression(getLexicalContext(), convert(expression, Type.OBJECT)).
-            setCases(getLexicalContext(), newCases);
+            setExpression(lc, convert(expression, Type.OBJECT)).
+            setCases(lc, newCases);
     }
 
     @Override
@@ -519,14 +519,14 @@
     public Node leaveWhileNode(final WhileNode whileNode) {
         final Node test = whileNode.getTest();
         if (test != null) {
-            return whileNode.setTest(getLexicalContext(), convert(test, Type.BOOLEAN));
+            return whileNode.setTest(lc, convert(test, Type.BOOLEAN));
         }
         return whileNode;
     }
 
     @Override
     public Node leaveWithNode(final WithNode withNode) {
-        return withNode.setExpression(getLexicalContext(), convert(withNode.getExpression(), Type.OBJECT));
+        return withNode.setExpression(lc, convert(withNode.getExpression(), Type.OBJECT));
     }
 
     private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
@@ -550,7 +550,6 @@
             return; // nothing to do
         }
 
-        final LexicalContext lc             = getLexicalContext();
         final FunctionNode   functionNode   = lc.getFunction(block);
         final boolean        allVarsInScope = functionNode.allVarsInScope();
         final boolean        isVarArg       = functionNode.isVarArg();
@@ -652,7 +651,7 @@
     private static void setCanBePrimitive(final Node node, final Type to) {
         final HashSet<Node> exclude = new HashSet<>();
 
-        node.accept(new NodeVisitor() {
+        node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             private void setCanBePrimitive(final Symbol symbol) {
                 LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol));
                 symbol.setCanBePrimitive(to);
@@ -762,7 +761,7 @@
             }
         }
         LOG.info("Type override for lhs in '", node, "' => ", to);
-        return ((TypeOverride<T>)node).setType(temporarySymbols, getLexicalContext(), to);
+        return ((TypeOverride<T>)node).setType(temporarySymbols, lc, to);
     }
 
     /**
@@ -785,8 +784,8 @@
     private Node convert(final Node node, final Type to) {
         assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass();
         assert node != null : "node is null";
-        assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + getLexicalContext().getCurrentFunction();
-        assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + getLexicalContext().getCurrentFunction();
+        assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction();
+        assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + lc.getCurrentFunction();
 
         final Type from = node.getType();
 
@@ -800,7 +799,7 @@
 
         Node resultNode = node;
 
-        if (node instanceof LiteralNode && !to.isObject()) {
+        if (node instanceof LiteralNode && !(node instanceof ArrayLiteralNode) && !to.isObject()) {
             final LiteralNode<?> newNode = new LiteralNodeConstantEvaluator((LiteralNode<?>)node, to).eval();
             if (newNode != null) {
                 resultNode = newNode;
@@ -817,7 +816,6 @@
 
         assert !node.isTerminal();
 
-        final LexicalContext lc = getLexicalContext();
         //This is the only place in this file that can create new temporaries
         //FinalizeTypes may not introduce ANY node that is not a conversion.
         return temporarySymbols.ensureSymbol(lc, to, resultNode);
@@ -854,7 +852,7 @@
             symbol = symbol.setTypeOverrideShared(to, temporarySymbols);
             LOG.info("Type override for temporary in '", node, "' => ", to);
         }
-        return node.setSymbol(getLexicalContext(), symbol);
+        return node.setSymbol(lc, symbol);
     }
 
     /**
@@ -907,7 +905,7 @@
 
             if (literalNode != null) {
                 //inherit literal symbol for attr.
-                literalNode = (LiteralNode<?>)literalNode.setSymbol(getLexicalContext(), parent.getSymbol());
+                literalNode = (LiteralNode<?>)literalNode.setSymbol(lc, parent.getSymbol());
             }
 
             return literalNode;
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Wed Jul 05 18:57:52 2017 +0200
@@ -33,7 +33,9 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
@@ -45,11 +47,12 @@
 /**
  * Simple constant folding pass, executed before IR is starting to be lowered.
  */
-final class FoldConstants extends NodeVisitor {
+final class FoldConstants extends NodeVisitor<LexicalContext> {
 
     private static final DebugLogger LOG = new DebugLogger("fold");
 
     FoldConstants() {
+        super(new LexicalContext());
     }
 
     @Override
@@ -79,7 +82,7 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-        return functionNode.setState(getLexicalContext(), CompilationState.CONSTANT_FOLDED);
+        return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
     }
 
     @Override
@@ -141,6 +144,10 @@
                 return null;
             }
 
+            if (rhsNode instanceof ArrayLiteralNode) {
+                return null;
+            }
+
             final LiteralNode<?> rhs = (LiteralNode<?>)rhsNode;
             final boolean rhsInteger = rhs.getType().isInteger();
 
@@ -212,6 +219,10 @@
             final LiteralNode<?> lhs = (LiteralNode<?>)parent.lhs();
             final LiteralNode<?> rhs = (LiteralNode<?>)parent.rhs();
 
+            if (lhs instanceof ArrayLiteralNode || rhs instanceof ArrayLiteralNode) {
+                return null;
+            }
+
             final Type widest = Type.widest(lhs.getType(), rhs.getType());
 
             boolean isInteger = widest.isInteger();
@@ -279,9 +290,9 @@
             isLong    &= value != 0.0 && JSType.isRepresentableAsLong(value);
 
             if (isInteger) {
-                return LiteralNode.newInstance(token, finish, JSType.toInt32(value));
+                return LiteralNode.newInstance(token, finish, (int)value);
             } else if (isLong) {
-                return LiteralNode.newInstance(token, finish, JSType.toLong(value));
+                return LiteralNode.newInstance(token, finish, (long)value);
             }
 
             return LiteralNode.newInstance(token, finish, value);
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Wed Jul 05 18:57:52 2017 +0200
@@ -80,7 +80,7 @@
  * finalized.
  */
 
-final class Lower extends NodeOperatorVisitor {
+final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
 
     private static final DebugLogger LOG = new DebugLogger("lower");
 
@@ -105,7 +105,7 @@
                             terminated = true;
                         }
                     } else {
-                        statement.accept(new NodeVisitor() {
+                        statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                             @Override
                             public boolean enterVarNode(final VarNode varNode) {
                                 newStatements.add(varNode.setInit(null));
@@ -121,7 +121,6 @@
 
     @Override
     public boolean enterBlock(final Block block) {
-        final LexicalContext lc = getLexicalContext();
         final FunctionNode   function = lc.getCurrentFunction();
         if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) {
             new ExecuteNode(block.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
@@ -134,12 +133,10 @@
         //now we have committed the entire statement list to the block, but we need to truncate
         //whatever is after the last terminal. block append won't append past it
 
-        final BlockLexicalContext lc = (BlockLexicalContext)getLexicalContext();
-
         Statement last = lc.getLastStatement();
 
         if (lc.isFunctionBody()) {
-            final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+            final FunctionNode currentFunction = lc.getCurrentFunction();
             final boolean isProgram = currentFunction.isProgram();
             final ReturnNode returnNode = new ReturnNode(
                 last == null ? block.getLineNumber() : last.getLineNumber(), //TODO?
@@ -191,7 +188,7 @@
         final Node expr = executeNode.getExpression();
         ExecuteNode node = executeNode;
 
-        final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+        final FunctionNode currentFunction = lc.getCurrentFunction();
 
         if (currentFunction.isProgram()) {
             if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function
@@ -216,7 +213,7 @@
 
         final Node  test = forNode.getTest();
         if (!forNode.isForIn() && conservativeAlwaysTrue(test)) {
-            newForNode = forNode.setTest(getLexicalContext(), null);
+            newForNode = forNode.setTest(lc, null);
         }
 
         return addStatement(checkEscape(newForNode));
@@ -230,7 +227,7 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         LOG.info("END FunctionNode: ", functionNode.getName());
-        return functionNode.setState(getLexicalContext(), CompilationState.LOWERED);
+        return functionNode.setState(lc, CompilationState.LOWERED);
     }
 
     @Override
@@ -261,19 +258,25 @@
         return throwNode;
     }
 
-    private static Node ensureUniqueLabelsIn(final Node node) {
-        return node.accept(new NodeVisitor() {
-           @Override
-           public Node leaveDefault(final Node labelledNode) {
-               return labelledNode.ensureUniqueLabels(getLexicalContext());
-           }
+    private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) {
+        return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public Node leaveFunctionNode(final FunctionNode functionNode) {
+                final String name = functionNode.getName();
+                return functionNode.setName(lc, lc.getCurrentFunction().uniqueName(name));
+            }
+
+            @Override
+            public Node leaveDefault(final Node labelledNode) {
+                return labelledNode.ensureUniqueLabels(lc);
+            }
         });
     }
 
-    private static List<Statement> copyFinally(final Block finallyBody) {
+    private static List<Statement> copyFinally(final LexicalContext lc, final Block finallyBody) {
         final List<Statement> newStatements = new ArrayList<>();
         for (final Statement statement : finallyBody.getStatements()) {
-            newStatements.add((Statement)ensureUniqueLabelsIn(statement));
+            newStatements.add((Statement)ensureUniqueNamesIn(lc, statement));
             if (statement.hasTerminalFlags()) {
                 return newStatements;
             }
@@ -286,12 +289,12 @@
         final long token      = tryNode.getToken();
         final int  finish     = tryNode.getFinish();
 
-        final IdentNode exception = new IdentNode(token, finish, getLexicalContext().getCurrentFunction().uniqueName("catch_all"));
+        final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all"));
 
-        final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception))).
-                setIsTerminal(getLexicalContext(), true); //ends with throw, so terminal
+        final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)).
+                setIsTerminal(lc, true); //ends with throw, so terminal
 
-        final CatchNode catchAllNode  = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody);
+        final CatchNode catchAllNode  = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW);
         final Block     catchAllBlock = new Block(lineNumber, token, finish, catchAllNode);
 
         //catchallblock -> catchallnode (catchnode) -> exception -> throw
@@ -300,7 +303,7 @@
     }
 
     private IdentNode compilerConstant(final CompilerConstants cc) {
-        final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+        final FunctionNode functionNode = lc.getCurrentFunction();
         return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName());
     }
 
@@ -316,11 +319,10 @@
      * @return new try node after splicing finally code (same if nop)
      */
     private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
-        final int finish = tryNode.getFinish();
+        assert tryNode.getFinallyBody() == null;
+        final int            finish = tryNode.getFinish();
 
-        assert tryNode.getFinallyBody() == null;
-
-        final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() {
+        final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             final List<Node> insideTry = new ArrayList<>();
 
             @Override
@@ -338,7 +340,7 @@
             @Override
             public Node leaveThrowNode(final ThrowNode throwNode) {
                 if (rethrows.contains(throwNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
+                    final List<Statement> newStatements = copyFinally(lc, finallyBody);
                     if (!isTerminal(newStatements)) {
                         newStatements.add(throwNode);
                     }
@@ -349,12 +351,12 @@
 
             @Override
             public Node leaveBreakNode(final BreakNode breakNode) {
-                return copy(breakNode, Lower.this.getLexicalContext().getBreakable(breakNode.getLabel()));
+                return copy(breakNode, Lower.this.lc.getBreakable(breakNode.getLabel()));
             }
 
             @Override
             public Node leaveContinueNode(final ContinueNode continueNode) {
-                return copy(continueNode, Lower.this.getLexicalContext().getContinueTo(continueNode.getLabel()));
+                return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabel()));
             }
 
             @Override
@@ -372,17 +374,17 @@
                     resultNode = null;
                 }
 
-                newStatements.addAll(copyFinally(finallyBody));
+                newStatements.addAll(copyFinally(lc, finallyBody));
                 if (!isTerminal(newStatements)) {
                     newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
                 }
 
-                return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), getLexicalContext().getCurrentBlock().getFinish(), newStatements));
+                return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), lc.getCurrentBlock().getFinish(), newStatements));
             }
 
             private Node copy(final Statement endpoint, final Node targetNode) {
                 if (!insideTry.contains(targetNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
+                    final List<Statement> newStatements = copyFinally(lc, finallyBody);
                     if (!isTerminal(newStatements)) {
                         newStatements.add(endpoint);
                     }
@@ -436,7 +438,7 @@
         final Block catchAll = catchAllBlock(tryNode);
 
         final List<ThrowNode> rethrows = new ArrayList<>();
-        catchAll.accept(new NodeVisitor() {
+        catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterThrowNode(final ThrowNode throwNode) {
                 rethrows.add(throwNode);
@@ -464,7 +466,7 @@
     @Override
     public Node leaveVarNode(final VarNode varNode) {
         addStatement(varNode);
-        if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && getLexicalContext().getCurrentFunction().isProgram()) {
+        if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) {
             new ExecuteNode(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this);
         }
         return varNode;
@@ -478,7 +480,7 @@
         if (conservativeAlwaysTrue(test)) {
             //turn it into a for node without a test.
             final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), null, null, body, null, ForNode.IS_FOR).accept(this);
-            getLexicalContext().replace(whileNode, forNode);
+            lc.replace(whileNode, forNode);
             return forNode;
         }
 
@@ -513,7 +515,7 @@
      * @return eval location
      */
     private String evalLocation(final IdentNode node) {
-        final Source source = getLexicalContext().getCurrentFunction().getSource();
+        final Source source = lc.getCurrentFunction().getSource();
         return new StringBuilder().
             append(source.getName()).
             append('#').
@@ -545,10 +547,10 @@
 
             // 'eval' call with at least one argument
             if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
-                final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+                final FunctionNode currentFunction = lc.getCurrentFunction();
                 return callNode.setEvalArgs(
                     new CallNode.EvalArgs(
-                        ensureUniqueLabelsIn(args.get(0)).accept(this),
+                        ensureUniqueNamesIn(lc, args.get(0)).accept(this),
                         compilerConstant(THIS),
                         evalLocation(callee),
                         currentFunction.isStrict()));
@@ -574,7 +576,7 @@
     private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) {
         final List<Node> escapes = new ArrayList<>();
 
-        loopBody.accept(new NodeVisitor() {
+        loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public Node leaveBreakNode(final BreakNode node) {
                 escapes.add(node);
@@ -595,7 +597,6 @@
     }
 
     private LoopNode checkEscape(final LoopNode loopNode) {
-        final LexicalContext lc = getLexicalContext();
         final boolean escapes = controlFlowEscapes(lc, loopNode.getBody());
         if (escapes) {
             return loopNode.
@@ -607,7 +608,7 @@
 
 
     private Node addStatement(final Statement statement) {
-        ((BlockLexicalContext)getLexicalContext()).appendStatement(statement);
+        lc.appendStatement(statement);
         return statement;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -2081,7 +2081,9 @@
      * @param args debug information to print
      */
     private void debug(final Object... args) {
-        debug(30, args);
+        if (DEBUG) {
+            debug(30, args);
+        }
     }
 
     /**
@@ -2091,7 +2093,9 @@
      * @param args debug information to print
      */
     private void debug_label(final Object... args) {
-        debug(26, args);
+        if (DEBUG) {
+            debug(22, args);
+        }
     }
 
     private void debug(final int padConstant, final Object... args) {
@@ -2164,7 +2168,6 @@
                     new Throwable().printStackTrace(LOG.getOutputStream());
                 }
             }
-
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,476 @@
+/*
+ * 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.codegen;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import jdk.nashorn.internal.codegen.types.Range;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Assignment;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.DebugLogger;
+
+/**
+ * Range analysis and narrowing of type where it can be proven
+ * that there is no spillover, e.g.
+ *
+ *  function func(c) {
+ *    var v = c & 0xfff;
+ *    var w = c & 0xeee;
+ *    var x = v * w;
+ *    return x;
+ *  }
+ *
+ *  Proves that the multiplication never exceeds 24 bits and can thus be an int
+ */
+final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
+    static final DebugLogger LOG = new DebugLogger("ranges");
+
+    private static final Range.Functionality RANGE = new Range.Functionality(LOG);
+
+    private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
+
+    RangeAnalyzer() {
+        super(new LexicalContext());
+    }
+
+    @Override
+    public boolean enterForNode(final ForNode forNode) {
+        //conservatively attempt to identify the loop counter. Null means that it wasn't
+        //properly identified and that no optimizations can be made with it - its range is
+        //simply unknown in that case, if it is assigned in the loop
+        final Symbol counter = findLoopCounter(forNode);
+        LOG.fine("Entering forNode " + forNode + " counter = " + counter);
+        if (counter != null && !assignedInLoop(forNode,  counter)) {
+            loopCounters.put(forNode, counter);
+        }
+        return true;
+    }
+
+    //destination visited
+    private Symbol setRange(final Node dest, final Range range) {
+        if (range.isUnknown()) {
+            return null;
+        }
+
+        final Symbol symbol = dest.getSymbol();
+        assert symbol != null : dest + " " + dest.getClass() + " has no symbol";
+        assert symbol.getRange() != null : symbol + " has no range";
+        final Range symRange = RANGE.join(symbol.getRange(), range);
+
+        //anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
+        if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) {
+            symbol.setRange(Range.createGenericRange());
+            return symbol;
+        }
+
+        if (!symRange.equals(symbol.getRange())) {
+            LOG.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
+            symbol.setRange(symRange);
+        }
+
+        return null;
+    }
+
+    @Override
+    public Node leaveADD(final BinaryNode node) {
+        setRange(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveSUB(final BinaryNode node) {
+        setRange(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveMUL(final BinaryNode node) {
+        setRange(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveDIV(final BinaryNode node) {
+        setRange(node, RANGE.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveMOD(final BinaryNode node) {
+        setRange(node, RANGE.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveBIT_AND(final BinaryNode node) {
+        setRange(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveBIT_OR(final BinaryNode node) {
+        setRange(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveBIT_XOR(final BinaryNode node) {
+        setRange(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveSAR(final BinaryNode node) {
+        setRange(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveSHL(final BinaryNode node) {
+        setRange(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveSHR(final BinaryNode node) {
+        setRange(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    private Node leaveCmp(final BinaryNode node) {
+        setRange(node, Range.createTypeRange(Type.BOOLEAN));
+        return node;
+    }
+
+    @Override
+    public Node leaveEQ(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveEQ_STRICT(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveNE(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveNE_STRICT(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveLT(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveLE(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveGT(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveGE(final BinaryNode node) {
+        return leaveCmp(node);
+    }
+
+    @Override
+    public Node leaveASSIGN(final BinaryNode node) {
+        Range range = node.rhs().getSymbol().getRange();
+        if (range.isUnknown()) {
+            range = Range.createGenericRange();
+        }
+
+        setRange(node.lhs(), range);
+        setRange(node, range);
+
+        return node;
+    }
+
+    private Node leaveSelfModifyingAssign(final BinaryNode node, final Range range) {
+        setRange(node.lhs(), range);
+        setRange(node, range);
+        return node;
+    }
+
+    private Node leaveSelfModifyingAssign(final UnaryNode node, final Range range) {
+        setRange(node.rhs(), range);
+        setRange(node, range);
+        return node;
+    }
+
+    @Override
+    public Node leaveASSIGN_ADD(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_SUB(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_MUL(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_DIV(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
+    }
+
+    @Override
+    public Node leaveASSIGN_MOD(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
+    }
+
+    @Override
+    public Node leaveASSIGN_BIT_AND(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_BIT_OR(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_BIT_XOR(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_SAR(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_SHR(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveASSIGN_SHL(final BinaryNode node) {
+        return leaveSelfModifyingAssign(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+    }
+
+    @Override
+    public Node leaveDECINC(final UnaryNode node) {
+        switch (node.tokenType()) {
+        case DECPREFIX:
+        case DECPOSTFIX:
+            return leaveSelfModifyingAssign(node, RANGE.sub(node.rhs().getSymbol().getRange(), Range.createRange(1)));
+        case INCPREFIX:
+        case INCPOSTFIX:
+            return leaveSelfModifyingAssign(node, RANGE.add(node.rhs().getSymbol().getRange(), Range.createRange(1)));
+        default:
+            assert false;
+            return node;
+        }
+    }
+
+    @Override
+    public Node leaveADD(final UnaryNode node) {
+        Range range = node.rhs().getSymbol().getRange();
+        if (!range.getType().isNumeric()) {
+           range = Range.createTypeRange(Type.NUMBER);
+        }
+        setRange(node, range);
+        return node;
+    }
+
+    @Override
+    public Node leaveBIT_NOT(final UnaryNode node) {
+        setRange(node, Range.createTypeRange(Type.INT));
+        return node;
+    }
+
+    @Override
+    public Node leaveNOT(final UnaryNode node) {
+        setRange(node, Range.createTypeRange(Type.BOOLEAN));
+        return node;
+    }
+
+    @Override
+    public Node leaveSUB(final UnaryNode node) {
+        setRange(node, RANGE.neg(node.rhs().getSymbol().getRange()));
+        return node;
+    }
+
+    @Override
+    public Node leaveVarNode(final VarNode node) {
+        if (node.isAssignment()) {
+            Range range = node.getInit().getSymbol().getRange();
+            range = range.isUnknown() ? Range.createGenericRange() : range;
+
+            setRange(node.getName(), range);
+            setRange(node, range);
+        }
+
+        return node;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public boolean enterLiteralNode(final LiteralNode node) {
+        // ignore array literals
+        return !(node instanceof ArrayLiteralNode);
+    }
+
+    @Override
+    public Node leaveLiteralNode(@SuppressWarnings("rawtypes") final LiteralNode node) {
+        if (node.getType().isInteger()) {
+            setRange(node, Range.createRange(node.getInt32()));
+        } else if (node.getType().isNumber()) {
+            setRange(node, Range.createRange(node.getNumber()));
+        } else if (node.getType().isLong()) {
+            setRange(node, Range.createRange(node.getLong()));
+        } else if (node.getType().isBoolean()) {
+            setRange(node, Range.createTypeRange(Type.BOOLEAN));
+        } else {
+            setRange(node, Range.createGenericRange());
+        }
+        return node;
+    }
+
+    @Override
+    public boolean enterRuntimeNode(final RuntimeNode node) {
+        // a runtime node that cannot be specialized is no point entering
+        return node.getRequest().canSpecialize();
+    }
+
+    /**
+     * Check whether a symbol is unsafely assigned in a loop - i.e. repeteadly assigned and
+     * not being identified as the loop counter. That means we don't really know anything
+     * about its range.
+     * @param loopNode loop node
+     * @param symbol   symbol
+     * @return true if assigned in loop
+     */
+    // TODO - this currently checks for nodes only - needs to be augmented for while nodes
+    // assignment analysis is also very conservative
+    private static boolean assignedInLoop(final LoopNode loopNode, final Symbol symbol) {
+        final HashSet<Node> skip = new HashSet<>();
+        final HashSet<Node> assignmentsInLoop = new HashSet<>();
+
+        loopNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            private boolean assigns(final Node node, final Symbol s) {
+                return node.isAssignment() && ((Assignment<?>)node).getAssignmentDest().getSymbol() == s;
+            }
+
+            @Override
+            public boolean enterForNode(final ForNode forNode) {
+                if (forNode.getInit() != null) {
+                    skip.add(forNode.getInit());
+                }
+                if (forNode.getModify() != null) {
+                    skip.add(forNode.getModify());
+                }
+                return true;
+            }
+
+            @Override
+            public Node leaveDefault(final Node node) {
+                //if this is an assignment to symbol
+                if (!skip.contains(node) && assigns(node, symbol)) {
+                    assignmentsInLoop.add(node);
+                }
+                return node;
+            }
+        });
+
+        return !assignmentsInLoop.isEmpty();
+    }
+
+    /**
+     * Check for a loop counter. This is currently quite conservative, in that it only handles
+     * x <= counter and x < counter.
+     *
+     * @param node loop node to check
+     * @return
+     */
+    private static Symbol findLoopCounter(final LoopNode node) {
+        final Node test = node.getTest();
+
+        if (test != null && test.isComparison()) {
+            final BinaryNode binaryNode = (BinaryNode)test;
+            final Node lhs = binaryNode.lhs();
+            final Node rhs = binaryNode.rhs();
+
+            //detect ident cmp int_literal
+            if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode<?>)rhs).getType().isInteger()) {
+                final Symbol    symbol = lhs.getSymbol();
+                final int       margin = ((LiteralNode<?>)rhs).getInt32();
+                final TokenType op     = test.tokenType();
+
+                switch (op) {
+                case LT:
+                case LE:
+                    symbol.setRange(RANGE.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
+                    return symbol;
+                case GT:
+                case GE:
+                    //setRange(lhs, Range.createRange(op == TokenType.GT ? margin + 1 : margin));
+                    //return symbol;
+                default:
+                    break;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isLoopCounter(final LoopNode loopNode, final Symbol symbol) {
+        //this only works if loop nodes aren't replaced by other ones during this transform, but they are not
+        return loopCounters.get(loopNode) == symbol;
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Wed Jul 05 18:57:52 2017 +0200
@@ -116,9 +116,10 @@
     /**
      * Generate the invoke instruction for this shared scope call.
      * @param method the method emitter
+     * @return the method emitter
      */
-    public void generateInvoke(final MethodEmitter method) {
-        method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature());
+    public MethodEmitter generateInvoke(final MethodEmitter method) {
+        return method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature());
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -49,12 +49,12 @@
 /**
  * Split the IR into smaller compile units.
  */
-final class Splitter extends NodeVisitor {
+final class Splitter extends NodeVisitor<LexicalContext> {
     /** Current compiler. */
     private final Compiler compiler;
 
     /** IR to be broken down. */
-    private FunctionNode outermost;
+    private final FunctionNode outermost;
 
     /** Compile unit for the main script. */
     private final CompileUnit outermostCompileUnit;
@@ -75,6 +75,7 @@
      * @param outermostCompileUnit  compile unit for outermost function, if non-lazy this is the script's compile unit
      */
     public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
+        super(new LexicalContext());
         this.compiler             = compiler;
         this.outermost            = functionNode;
         this.outermostCompileUnit = outermostCompileUnit;
@@ -93,8 +94,6 @@
 
         LOG.finest("Initiating split of '", functionNode.getName(), "'");
 
-        final LexicalContext lc = getLexicalContext();
-
         long weight = WeighNodes.weigh(functionNode);
         final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost;
 
@@ -127,7 +126,7 @@
         final Block body = functionNode.getBody();
         final List<FunctionNode> dc = directChildren(functionNode);
 
-        final Block newBody = (Block)body.accept(new NodeVisitor() {
+        final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterFunctionNode(final FunctionNode nestedFunction) {
                 return dc.contains(nestedFunction);
@@ -136,7 +135,7 @@
             @Override
             public Node leaveFunctionNode(final FunctionNode nestedFunction) {
                 FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction);
-                getLexicalContext().replace(nestedFunction, split);
+                lc.replace(nestedFunction, split);
                 return split;
             }
         });
@@ -149,13 +148,13 @@
 
     private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
         final List<FunctionNode> dc = new ArrayList<>();
-        functionNode.accept(new NodeVisitor() {
+        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterFunctionNode(final FunctionNode child) {
                 if (child == functionNode) {
                     return true;
                 }
-                if (getLexicalContext().getParentFunction(child) == functionNode) {
+                if (lc.getParentFunction(child) == functionNode) {
                     dc.add(child);
                 }
                 return false;
@@ -181,7 +180,7 @@
      * @return new weight for the resulting block.
      */
     private Block splitBlock(final Block block, final FunctionNode function) {
-        getLexicalContext().setFlag(getLexicalContext().getCurrentFunction(), FunctionNode.IS_SPLIT);
+        lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_SPLIT);
 
         final List<Statement> splits = new ArrayList<>();
         List<Statement> statements = new ArrayList<>();
@@ -210,7 +209,7 @@
             splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
         }
 
-        return block.setStatements(getLexicalContext(), splits);
+        return block.setStatements(lc, splits);
     }
 
     /**
@@ -258,7 +257,7 @@
         // been split already, so weigh again before splitting.
         long weight = WeighNodes.weigh(block, weightCache);
         if (weight >= SPLIT_THRESHOLD) {
-            newBlock = splitBlock(block, getLexicalContext().getFunction(block));
+            newBlock = splitBlock(block, lc.getFunction(block));
             weight   = WeighNodes.weigh(newBlock, weightCache);
         }
         weightCache.put(newBlock, weight);
@@ -274,9 +273,9 @@
             return literal;
         }
 
-        final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+        final FunctionNode functionNode = lc.getCurrentFunction();
 
-        getLexicalContext().setFlag(functionNode, FunctionNode.IS_SPLIT);
+        lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
 
         if (literal instanceof ArrayLiteralNode) {
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
--- a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java	Wed Jul 05 18:57:52 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.util.List;
 import java.util.Map;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
@@ -41,6 +42,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
@@ -63,7 +65,7 @@
  * Computes the "byte code" weight of an AST segment. This is used
  * for Splitting too large class files
  */
-final class WeighNodes extends NodeOperatorVisitor {
+final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
     /*
      * Weight constants.
      */
@@ -100,7 +102,7 @@
      * @param weightCache cache of already calculated block weights
      */
     private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) {
-        super();
+        super(new LexicalContext());
         this.topFunction = topFunction;
         this.weightCache = weightCache;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,705 @@
+/*
+ * 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.codegen.types;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * Represents the value range of a symbol.
+ */
+public abstract class Range {
+
+    private static final Range GENERIC_RANGE = new Range() {
+        @Override
+        public Type getType() {
+            return Type.OBJECT;
+        }
+    };
+
+    private static final Range NUMBER_RANGE = new Range() {
+        @Override
+        public Type getType() {
+            return Type.NUMBER;
+        }
+    };
+
+    private static final Range UNKNOWN_RANGE = new Range() {
+        @Override
+        public Type getType() {
+            return Type.UNKNOWN;
+        }
+
+        @Override
+        public boolean isUnknown() {
+            return true;
+        }
+    };
+
+    private static class IntegerRange extends Range {
+        private final long min;
+        private final long max;
+        private final Type type;
+
+        private IntegerRange(final long min, final long max) {
+            assert min <= max;
+            this.min  = min;
+            this.max  = max;
+            this.type = typeFromRange(min, max);
+        }
+
+        private static Type typeFromRange(final long from, final long to) {
+            if (from >= Integer.MIN_VALUE && to <= Integer.MAX_VALUE) {
+                return Type.INT;
+            }
+            return Type.LONG;
+        }
+
+        @Override
+        public Type getType() {
+            return type;
+        }
+
+        public long getMin() {
+            return min;
+        }
+
+        public long getMax() {
+            return max;
+        }
+
+        @Override
+        public boolean isIntegerConst() {
+            return getMin() == getMax();
+        }
+
+        private long getBitMask() {
+            if (min == max) {
+                return min;
+            }
+
+            if (min < 0) {
+                return ~0L;
+            }
+
+            long mask = 1;
+            while (mask < max) {
+                mask = (mask << 1) | 1;
+            }
+            return mask;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (obj instanceof IntegerRange) {
+                final IntegerRange other = (IntegerRange)obj;
+                return this.type == other.type && this.min == other.min && this.max == other.max;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Long.hashCode(min) ^ Long.hashCode(max);
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + "[" + min +", " + max + "]";
+        }
+    }
+
+    /**
+     * Get narrowest type for this range
+     * @return type
+     */
+    public abstract Type getType();
+
+    /**
+     * Is this range unknown
+     * @return true if unknown
+     */
+    public boolean isUnknown() {
+        return false;
+    }
+
+    /**
+     * Check if an integer is enough to span this range
+     * @return true if integer is enough
+     */
+    public boolean isIntegerType() {
+        return this instanceof IntegerRange;
+    }
+
+    /**
+     * Check if an integer is enough to span this range
+     * @return true if integer is enough
+     */
+    public boolean isIntegerConst() {
+        return false;
+    }
+
+    /**
+     * Create an unknown range - this is most likely a singleton object
+     * and it represents "we have no known range information"
+     * @return the range
+     */
+    public static Range createUnknownRange() {
+        return UNKNOWN_RANGE;
+    }
+
+    /**
+     * Create a constant range: [value, value]
+     * @param value value
+     * @return the range
+     */
+    public static Range createRange(final int value) {
+        return createIntegerRange(value, value);
+    }
+
+    /**
+     * Create a constant range: [value, value]
+     * @param value value
+     * @return the range
+     */
+    public static Range createRange(final long value) {
+        return createIntegerRange(value, value);
+    }
+
+    /**
+     * Create a constant range: [value, value]
+     * @param value value
+     * @return the range
+     */
+    public static Range createRange(final double value) {
+        if (isRepresentableAsLong(value)) {
+            return createIntegerRange((long) value, (long) value);
+        }
+        return createNumberRange();
+    }
+
+    /**
+     * Create a constant range: [value, value]
+     * @param value value
+     * @return the range
+     */
+    public static Range createRange(final Object value) {
+        if (value instanceof Integer) {
+            return createRange((int)value);
+        } else if (value instanceof Long) {
+            return createRange((long)value);
+        } else if (value instanceof Double) {
+            return createRange((double)value);
+        }
+
+        return createGenericRange();
+    }
+
+    /**
+     * Create a generic range - object symbol that carries no range
+     * information
+     * @return the range
+     */
+    public static Range createGenericRange() {
+        return GENERIC_RANGE;
+    }
+
+    /**
+     * Create a number range - number symbol that carries no range
+     * information
+     * @return the range
+     */
+    public static Range createNumberRange() {
+        return NUMBER_RANGE;
+    }
+
+    /**
+     * Create an integer range [min, max]
+     * @param min minimum value, inclusive
+     * @param max maximum value, inclusive
+     * @return the range
+     */
+    public static IntegerRange createIntegerRange(final long min, final long max) {
+        return new IntegerRange(min, max);
+    }
+
+    /**
+     * Create an integer range of maximum type width for the given type
+     * @param type the type
+     * @return the range
+     */
+    public static IntegerRange createIntegerRange(final Type type) {
+        assert type.isNumeric() && !type.isNumber();
+        final long min;
+        final long max;
+        if (type.isInteger()) {
+            min = Integer.MIN_VALUE;
+            max = Integer.MAX_VALUE;
+        } else if (type.isLong()) {
+            min = Long.MIN_VALUE;
+            max = Long.MAX_VALUE;
+        } else {
+            throw new AssertionError(); //type incompatible with integer range
+        }
+        return new IntegerRange(min, max);
+    }
+
+    /**
+     * Create an range of maximum type width for the given type
+     * @param type the type
+     * @return the range
+     */
+    public static Range createTypeRange(final Type type) {
+        if (type.isNumber()) {
+            return createNumberRange();
+        } else if (type.isNumeric()) {
+            return createIntegerRange(type);
+        } else {
+            return createGenericRange();
+        }
+    }
+
+    // check that add doesn't overflow
+    private static boolean checkAdd(final long a, final long b) {
+        final long result = a + b;
+        return ((a ^ result) & (b ^ result)) >= 0;
+    }
+
+    // check that sub doesn't overflow
+    private static boolean checkSub(final long a, final long b) {
+        final long result = a - b;
+        return ((a ^ result) & (b ^ result)) >= 0;
+    }
+
+    private static boolean checkMul(final long a, final long b) {
+        // TODO correct overflow check
+        return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE && b >= Integer.MIN_VALUE && b <= Integer.MAX_VALUE;
+    }
+
+    /**
+     * The range functionality class responsible for merging ranges and drawing
+     * range conclusions from operations executed
+     */
+    public static class Functionality {
+        /** logger */
+        protected final DebugLogger log;
+
+        /**
+         * Constructor
+         * @param log logger
+         */
+        public Functionality(final DebugLogger log) {
+            this.log = log;
+        }
+
+        /**
+         * Join two ranges
+         * @param a first range
+         * @param b second range
+         * @return the joined range
+         */
+        public Range join(final Range a, final Range b) {
+            if (a.equals(b)) {
+                return a;
+            }
+
+            Type joinedType = a.getType();
+            if (a.getType() != b.getType()) {
+                if (a.isUnknown()) {
+                    return b;
+                }
+                if (b.isUnknown()) {
+                    return a;
+                }
+
+                joinedType = Type.widest(a.getType(), b.getType());
+            }
+
+            if (joinedType.isInteger() || joinedType.isLong()) {
+                return createIntegerRange(
+                        Math.min(((IntegerRange) a).getMin(), ((IntegerRange) b).getMin()),
+                        Math.max(((IntegerRange) a).getMax(), ((IntegerRange) b).getMax()));
+            }
+
+            return createTypeRange(joinedType);
+        }
+
+        /**
+         * Add operation
+         * @param a range of first symbol to be added
+         * @param b range of second symbol to be added
+         * @return resulting range representing the value range after add
+         */
+        public Range add(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final IntegerRange lhs = (IntegerRange)a;
+                final IntegerRange rhs = (IntegerRange)b;
+                if (checkAdd(lhs.getMin(), rhs.getMin()) && checkAdd(lhs.getMax(), rhs.getMax())) {
+                    return createIntegerRange(lhs.getMin() + rhs.getMin(), lhs.getMax() + rhs.getMax());
+                }
+            }
+
+            if (a.getType().isNumeric() && b.getType().isNumeric()) {
+                return createNumberRange();
+            }
+
+            return createGenericRange();
+        }
+
+        /**
+         * Sub operation
+         * @param a range of first symbol to be subtracted
+         * @param b range of second symbol to be subtracted
+         * @return resulting range representing the value range after subtraction
+         */
+        public Range sub(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final IntegerRange lhs = (IntegerRange)a;
+                final IntegerRange rhs = (IntegerRange)b;
+                if (checkSub(lhs.getMin(), rhs.getMax()) && checkSub(lhs.getMax(), rhs.getMin())) {
+                    return createIntegerRange(lhs.getMin() - rhs.getMax(), lhs.getMax() - rhs.getMin());
+                }
+            }
+
+            if (a.getType().isNumeric() && b.getType().isNumeric()) {
+                return createNumberRange();
+            }
+
+            return createGenericRange();
+        }
+
+        /**
+         * Mul operation
+         * @param a range of first symbol to be multiplied
+         * @param b range of second symbol to be multiplied
+         * @return resulting range representing the value range after multiplication
+         */
+        public Range mul(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final IntegerRange lhs = (IntegerRange)a;
+                final IntegerRange rhs = (IntegerRange)b;
+
+                //ensure that nothing ever overflows or underflows
+                if (checkMul(lhs.getMin(), rhs.getMin()) &&
+                    checkMul(lhs.getMax(), rhs.getMax()) &&
+                    checkMul(lhs.getMin(), rhs.getMax()) &&
+                    checkMul(lhs.getMax(), rhs.getMin())) {
+
+                    final List<Long> results =
+                        Arrays.asList(
+                            lhs.getMin() * rhs.getMin(),
+                            lhs.getMin() * rhs.getMax(),
+                            lhs.getMax() * rhs.getMin(),
+                            lhs.getMax() * rhs.getMax());
+                    return createIntegerRange(Collections.min(results), Collections.max(results));
+                }
+            }
+
+            if (a.getType().isNumeric() && b.getType().isNumeric()) {
+                return createNumberRange();
+            }
+
+            return createGenericRange();
+        }
+
+        /**
+         * Neg operation
+         * @param a range of value symbol to be negated
+         * @return resulting range representing the value range after neg
+         */
+        public Range neg(final Range a) {
+            if (a.isIntegerType()) {
+                final IntegerRange rhs = (IntegerRange)a;
+                if (rhs.getMin() != Long.MIN_VALUE && rhs.getMax() != Long.MIN_VALUE) {
+                    return createIntegerRange(-rhs.getMax(), -rhs.getMin());
+                }
+            }
+
+            if (a.getType().isNumeric()) {
+                return createNumberRange();
+            }
+
+            return createGenericRange();
+        }
+
+        /**
+         * Bitwise and operation
+         * @param a range of first symbol to be and:ed
+         * @param b range of second symbol to be and:ed
+         * @return resulting range representing the value range after and
+         */
+        public Range and(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final int resultMask = (int) (((IntegerRange)a).getBitMask() & ((IntegerRange)b).getBitMask());
+                if (resultMask >= 0) {
+                    return createIntegerRange(0, resultMask);
+                }
+            } else if (a.isUnknown() && b.isIntegerType()) {
+                final long operandMask = ((IntegerRange)b).getBitMask();
+                if (operandMask >= 0) {
+                    return createIntegerRange(0, operandMask);
+                }
+            } else if (a.isIntegerType() && b.isUnknown()) {
+                final long operandMask = ((IntegerRange)a).getBitMask();
+                if (operandMask >= 0) {
+                    return createIntegerRange(0, operandMask);
+                }
+            }
+
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Bitwise or operation
+         * @param a range of first symbol to be or:ed
+         * @param b range of second symbol to be or:ed
+         * @return resulting range representing the value range after or
+         */
+        public Range or(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
+                if (resultMask >= 0) {
+                    return createIntegerRange(0, resultMask);
+                }
+            }
+
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Bitwise xor operation
+         * @param a range of first symbol to be xor:ed
+         * @param b range of second symbol to be xor:ed
+         * @return resulting range representing the value range after and
+         */
+        public Range xor(final Range a, final Range b) {
+            if (a.isIntegerConst() && b.isIntegerConst()) {
+                return createRange(((IntegerRange)a).getMin() ^ ((IntegerRange)b).getMin());
+            }
+
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
+                if (resultMask >= 0) {
+                    return createIntegerRange(0, createIntegerRange(0, resultMask).getBitMask());
+                }
+            }
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Bitwise shl operation
+         * @param a range of first symbol to be shl:ed
+         * @param b range of second symbol to be shl:ed
+         * @return resulting range representing the value range after shl
+         */
+        public Range shl(final Range a, final Range b) {
+            if (b.isIntegerType() && b.isIntegerConst()) {
+                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+                final int          shift = (int)((IntegerRange) b).getMin() & 0x1f;
+                final int          min   = (int)left.getMin() << shift;
+                final int          max   = (int)left.getMax() << shift;
+                if (min >> shift == left.getMin() && max >> shift == left.getMax()) {
+                    return createIntegerRange(min, max);
+                }
+            }
+
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Bitwise shr operation
+         * @param a range of first symbol to be shr:ed
+         * @param b range of second symbol to be shr:ed
+         * @return resulting range representing the value range after shr
+         */
+        public Range shr(final Range a, final Range b) {
+            if (b.isIntegerType() && b.isIntegerConst()) {
+                final long         shift = ((IntegerRange) b).getMin() & 0x1f;
+                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+                if (left.getMin() >= 0) {
+                    long min = left.getMin() >>> shift;
+                    long max = left.getMax() >>> shift;
+                    return createIntegerRange(min, max);
+                } else if (shift >= 1) {
+                    return createIntegerRange(0, JSType.MAX_UINT >>> shift);
+                }
+            }
+
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Bitwise sar operation
+         * @param a range of first symbol to be sar:ed
+         * @param b range of second symbol to be sar:ed
+         * @return resulting range representing the value range after sar
+         */
+        public Range sar(final Range a, final Range b) {
+            if (b.isIntegerType() && b.isIntegerConst()) {
+                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+                final long         shift = ((IntegerRange) b).getMin() & 0x1f;
+                final long         min   = left.getMin() >> shift;
+                final long         max   = left.getMax() >> shift;
+                return createIntegerRange(min, max);
+            }
+
+            return createTypeRange(Type.INT);
+        }
+
+        /**
+         * Modulo operation
+         * @param a range of first symbol to the mod operation
+         * @param b range of second symbol to be mod operation
+         * @return resulting range representing the value range after mod
+         */
+        public Range mod(final Range a, final Range b) {
+            if (a.isIntegerType() && b.isIntegerType()) {
+                final IntegerRange rhs = (IntegerRange) b;
+                if (rhs.getMin() > 0 || rhs.getMax() < 0) { // divisor range must not include 0
+                    final long absmax = Math.max(Math.abs(rhs.getMin()), Math.abs(rhs.getMax())) - 1;
+                    return createIntegerRange(rhs.getMin() > 0 ? 0 : -absmax, rhs.getMax() < 0 ? 0 : +absmax);
+                }
+            }
+            return createTypeRange(Type.NUMBER);
+        }
+
+        /**
+         * Division operation
+         * @param a range of first symbol to the division
+         * @param b range of second symbol to be division
+         * @return resulting range representing the value range after division
+         */
+        public Range div(final Range a, final Range b) {
+            // TODO
+            return createTypeRange(Type.NUMBER);
+        }
+    }
+
+    /**
+     * Simple trace functionality that will log range creation
+     */
+    public static class TraceFunctionality extends Functionality {
+        TraceFunctionality(final DebugLogger log) {
+            super(log);
+        }
+
+        private Range trace(final Range result, final String operation, final Range... operands) {
+            log.fine("range::" + operation + Arrays.toString(operands) + " => " + result);
+            return result;
+        }
+
+        @Override
+        public Range join(final Range a, final Range b) {
+            final Range result = super.join(a, b);
+            if (!a.equals(b)) {
+                trace(result, "join", a, b);
+            }
+            return result;
+        }
+
+        @Override
+        public Range add(final Range a, final Range b) {
+            return trace(super.add(a, b), "add", a, b);
+        }
+
+        @Override
+        public Range sub(final Range a, final Range b) {
+            return trace(super.sub(a, b), "sub", a, b);
+        }
+
+        @Override
+        public Range mul(final Range a, final Range b) {
+            return trace(super.mul(a, b), "mul", a, b);
+        }
+
+        @Override
+        public Range neg(final Range a) {
+            return trace(super.neg(a), "neg", a);
+        }
+
+        @Override
+        public Range and(final Range a, final Range b) {
+            return trace(super.and(a, b), "and", a, b);
+        }
+
+        @Override
+        public Range or(final Range a, final Range b) {
+            return trace(super.or(a, b), "or", a, b);
+        }
+
+        @Override
+        public Range xor(final Range a, final Range b) {
+            return trace(super.xor(a, b), "xor", a, b);
+        }
+
+        @Override
+        public Range shl(final Range a, final Range b) {
+            return trace(super.shl(a, b), "shl", a, b);
+        }
+
+        @Override
+        public Range shr(final Range a, final Range b) {
+            return trace(super.shr(a, b), "shr", a, b);
+        }
+
+        @Override
+        public Range sar(final Range a, final Range b) {
+            return trace(super.sar(a, b), "sar", a, b);
+        }
+
+        @Override
+        public Range mod(final Range a, final Range b) {
+            return trace(super.mod(a, b), "mod", a, b);
+        }
+
+        @Override
+        public Range div(final Range a, final Range b) {
+            return trace(super.div(a, b), "div", a, b);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.valueOf(getType());
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean isRepresentableAsInt(final double number) {
+        return (int)number == number && !isNegativeZero(number);
+    }
+
+    private static boolean isRepresentableAsLong(final double number) {
+        return (long)number == number && !isNegativeZero(number);
+    }
+
+    private static boolean isNegativeZero(final double number) {
+        return Double.doubleToLongBits(number) == Double.doubleToLongBits(-0.0);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java	Wed Jul 05 18:57:52 2017 +0200
@@ -106,23 +106,13 @@
     Type(final String name, final Class<?> clazz, final int weight, final int slots) {
         this.name       = name;
         this.clazz      = clazz;
-        this.descriptor = Type.getDescriptor(clazz);
+        this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
         this.weight     = weight;
         assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight;
         this.slots      = slots;
     }
 
     /**
-     * Return an internal descriptor for a type
-     *
-     * @param type the type
-     * @return descriptor string
-     */
-    public static String getDescriptor(final Class<?> type) {
-        return jdk.internal.org.objectweb.asm.Type.getDescriptor(type);
-    }
-
-    /**
      * Get the weight of this type - use this e.g. for sorting method descriptors
      * @return the weight
      */
--- a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -60,7 +60,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterAccessNode(this)) {
             return visitor.leaveAccessNode(
                 setBase(base.accept(visitor)).
@@ -110,7 +110,6 @@
         return new AccessNode(this, base, property, isFunction(), hasCallSiteType());
     }
 
-
     private AccessNode setProperty(final IdentNode property) {
         if (this.property == property) {
             return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -59,6 +59,23 @@
         this.rhs = rhs;
     }
 
+    @Override
+    public boolean isComparison() {
+        switch (tokenType()) {
+        case EQ:
+        case EQ_STRICT:
+        case NE:
+        case NE_STRICT:
+        case LE:
+        case LT:
+        case GE:
+        case GT:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     /**
      * Return the widest possible type for this operation. This is used for compile time
      * static type inference
@@ -143,7 +160,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBinaryNode(this)) {
             return visitor.leaveBinaryNode(setLHS(lhs.accept(visitor)).setRHS(rhs.accept(visitor)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/Block.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java	Wed Jul 05 18:57:52 2017 +0200
@@ -131,7 +131,7 @@
      * @return new or same node
      */
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBlock(this)) {
             return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -59,7 +59,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBreakNode(this)) {
             return visitor.leaveBreakNode(this);
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.util.Collections;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -194,7 +195,7 @@
      * @return node or replacement
      */
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterCallNode(this)) {
             final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
                     setFunction(function.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -78,7 +78,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterCaseNode(this)) {
             final Node  newTest = test == null ? null : test.accept(visitor);
             final Block newBody = body == null ? null : (Block)body.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,6 +42,11 @@
     /** Catch body. */
     private final Block body;
 
+    private final int flags;
+
+    /** Is this block a synthethic rethrow created by finally inlining? */
+    public static final int IS_SYNTHETIC_RETHROW = 1;
+
     /**
      * Constructors
      *
@@ -51,19 +56,22 @@
      * @param exception          variable name of exception
      * @param exceptionCondition exception condition
      * @param body               catch body
+     * @param flags              flags
      */
-    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Node exceptionCondition, final Block body) {
+    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Node exceptionCondition, final Block body, final int flags) {
         super(lineNumber, token, finish);
         this.exception          = exception;
         this.exceptionCondition = exceptionCondition;
         this.body               = body;
+        this.flags              = flags;
     }
 
-    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Node exceptionCondition, final Block body) {
+    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Node exceptionCondition, final Block body, final int flags) {
         super(catchNode);
         this.exception          = exception;
         this.exceptionCondition = exceptionCondition;
         this.body               = body;
+        this.flags              = flags;
     }
 
     /**
@@ -71,7 +79,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterCatchNode(this)) {
             return visitor.leaveCatchNode(
                 setException((IdentNode)exception.accept(visitor)).
@@ -124,7 +132,7 @@
         if (this.exceptionCondition == exceptionCondition) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body);
+        return new CatchNode(this, exception, exceptionCondition, body, flags);
     }
 
     /**
@@ -144,13 +152,25 @@
         if (this.exception == exception) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body);
+        return new CatchNode(this, exception, exceptionCondition, body, flags);
     }
 
     private CatchNode setBody(final Block body) {
         if (this.body == body) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body);
+        return new CatchNode(this, exception, exceptionCondition, body, flags);
     }
+
+    /**
+     * Is this catch block a non-JavaScript constructor, for example created as
+     * part of the rethrow mechanism of a finally block in Lower? Then we just
+     * pass the exception on and need not unwrap whatever is in the ECMAException
+     * object catch symbol
+     * @return true if a finally synthetic rethrow
+     */
+    public boolean isSyntheticRethrow() {
+        return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
+    }
+
 }
--- a/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterContinueNode(this)) {
             return visitor.leaveContinueNode(this);
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -56,7 +56,7 @@
 
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterEmptyNode(this)) {
             return visitor.leaveEmptyNode(this);
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterExecuteNode(this)) {
             return visitor.leaveExecuteNode(setExpression(expression.accept(visitor)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -86,7 +86,7 @@
     }
 
     @Override
-    protected Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterForNode(this)) {
             return visitor.leaveForNode(
                 setInit(lc, init == null ? null : init.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -250,6 +250,7 @@
         final FunctionNode functionNode,
         final long lastToken,
         final int flags,
+        final String name,
         final Type returnType,
         final CompileUnit compileUnit,
         final EnumSet<CompilationState> compilationState,
@@ -260,6 +261,7 @@
         super(functionNode);
 
         this.flags            = flags;
+        this.name             = name;
         this.returnType       = returnType;
         this.compileUnit      = compileUnit;
         this.lastToken        = lastToken;
@@ -271,7 +273,6 @@
 
         // the fields below never change - they are final and assigned in constructor
         this.source          = functionNode.source;
-        this.name            = functionNode.name;
         this.ident           = functionNode.ident;
         this.namespace       = functionNode.namespace;
         this.declaredSymbols = functionNode.declaredSymbols;
@@ -280,7 +281,7 @@
     }
 
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterFunctionNode(this)) {
             return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
         }
@@ -315,7 +316,7 @@
         if (this.snapshot == null) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, null, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
     }
 
     /**
@@ -331,7 +332,7 @@
         if (isProgram() || parameters.isEmpty()) {
             return this; //never specialize anything that won't be recompiled
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, this, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
     }
 
     /**
@@ -339,7 +340,7 @@
      * @return true if specialization is possible
      */
     public boolean canSpecialize() {
-        return getFlag(CAN_SPECIALIZE);
+        return snapshot != null && getFlag(CAN_SPECIALIZE);
     }
 
     /**
@@ -389,7 +390,7 @@
         }
         final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
         newState.add(state);
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
     }
 
     /**
@@ -410,7 +411,7 @@
         if (this.hints == hints) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     /**
@@ -463,7 +464,7 @@
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     @Override
@@ -529,7 +530,7 @@
     }
 
     /**
-     * Get the identifier for this function
+     * Get the identifier for this function, this is its symbol.
      * @return the identifier as an IdentityNode
      */
     public IdentNode getIdent() {
@@ -572,7 +573,7 @@
         if(this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     /**
@@ -640,7 +641,7 @@
         if (this.lastToken == lastToken) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     /**
@@ -651,6 +652,20 @@
         return name;
     }
 
+
+    /**
+     * Set the internal name for this function
+     * @param lc    lexical context
+     * @param name new name
+     * @return new function node if changed, otherwise the same
+     */
+    public FunctionNode setName(final LexicalContext lc, final String name) {
+        if (this.name.equals(name)) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+    }
+
     /**
      * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and
      * functions having with and/or eval blocks are such.
@@ -698,7 +713,7 @@
         if (this.parameters == parameters) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     /**
@@ -762,6 +777,7 @@
                 this,
                 lastToken,
                 flags,
+                name,
                 Type.widest(this.returnType, returnType.isObject() ?
                     Type.OBJECT :
                     returnType),
@@ -801,7 +817,7 @@
         if (this.compileUnit == compileUnit) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,7 +29,6 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
-
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -119,7 +118,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterIdentNode(this)) {
             return visitor.leaveIdentNode(this);
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/IfNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterIfNode(this)) {
             return visitor.leaveIfNode(
                 setTest(test.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -56,19 +56,12 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterIndexNode(this)) {
-            final Node      newBase  = base.accept(visitor);
-            final Node      newIndex = index.accept(visitor);
-            final IndexNode newNode;
-            if (newBase != base || newIndex != index) {
-                newNode = new IndexNode(this, newBase, newIndex, isFunction(), hasCallSiteType());
-            } else {
-                newNode = this;
-            }
-            return visitor.leaveIndexNode(newNode);
+            return visitor.leaveIndexNode(
+                setBase(base.accept(visitor)).
+                setIndex(index.accept(visitor)));
         }
-
         return this;
     }
 
@@ -106,6 +99,13 @@
         return index;
     }
 
+    private IndexNode setBase(final Node base) {
+        if (this.base == base) {
+            return this;
+        }
+        return new IndexNode(this, base, index, isFunction(), hasCallSiteType());
+    }
+
     /**
      * Set the index expression for this node
      * @param index new index expression
--- a/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -67,11 +67,11 @@
     }
 
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterLabelNode(this)) {
             return visitor.leaveLabelNode(
-                setLabel(visitor.getLexicalContext(), (IdentNode)label.accept(visitor)).
-                setBody(visitor.getLexicalContext(), (Block)body.accept(visitor)));
+                setLabel(lc, (IdentNode)label.accept(visitor)).
+                setBody(lc, (Block)body.accept(visitor)));
         }
 
         return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java	Wed Jul 05 18:57:52 2017 +0200
@@ -440,6 +440,23 @@
     }
 
     /**
+     * Check whether the lexical context is currently inside a loop
+     * @return true if inside a loop
+     */
+    public boolean inLoop() {
+        return getCurrentLoop() != null;
+    }
+
+    /**
+     * Returns the loop header of the current loop, or null if not inside a loop
+     * @return loop header
+     */
+    public LoopNode getCurrentLoop() {
+        final Iterator<LoopNode> iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
+        return iter.hasNext() ? iter.next() : null;
+    }
+
+    /**
      * Find the breakable node corresponding to this label.
      * @param label label to search for, if null the closest breakable node will be returned unconditionally, e.g. a while loop with no label
      * @return closest breakable node
@@ -461,8 +478,7 @@
     }
 
     private LoopNode getContinueTo() {
-        final Iterator<LoopNode> iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
-        return iter.hasNext() ? iter.next() : null;
+        return getCurrentLoop();
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -60,10 +60,10 @@
      *
      * @return new node or same node depending on state change
      */
-    protected abstract Node accept(final LexicalContext lc, final NodeVisitor visitor);
+    protected abstract Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor);
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         final LexicalContext lc = visitor.getLexicalContext();
         lc.push(this);
         final LexicalContextNode newNode = (LexicalContextNode)accept(lc, visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,6 +28,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -208,7 +209,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterLiteralNode(this)) {
             return visitor.leaveLiteralNode(this);
         }
@@ -514,7 +515,7 @@
         }
 
         @Override
-        public Node accept(final NodeVisitor visitor) {
+        public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
             if (visitor.enterLiteralNode(this)) {
                 if (value != null) {
                     final Node newValue = value.accept(visitor);
@@ -840,7 +841,7 @@
         }
 
         @Override
-        public Node accept(final NodeVisitor visitor) {
+        public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
             if (visitor.enterLiteralNode(this)) {
                 final List<Node> oldValue = Arrays.asList(value);
                 final List<Node> newValue = Node.accept(visitor, Node.class, oldValue);
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java	Wed Jul 05 18:57:52 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
@@ -153,6 +154,14 @@
     }
 
     /**
+     * Returns true if this node represents a comparison operator
+     * @return true if comparison
+     */
+    public boolean isComparison() {
+        return false;
+    }
+
+    /**
      * For reference copies - ensure that labels in the copy node are unique
      * using an appropriate copy constructor
      * @param lc lexical context
@@ -167,7 +176,7 @@
      * @param visitor Node visitor.
      * @return node the node or its replacement after visitation, null if no further visitations are required
      */
-    public abstract Node accept(NodeVisitor visitor);
+    public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
 
     @Override
     public String toString() {
@@ -329,7 +338,7 @@
     }
 
     //on change, we have to replace the entire list, that's we can't simple do ListIterator.set
-    static <T extends Node> List<T> accept(final NodeVisitor visitor, final Class<T> clazz, final List<T> list) {
+    static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) {
         boolean changed = false;
         final List<T> newList = new ArrayList<>();
 
--- a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterObjectNode(this)) {
             return visitor.leaveObjectNode(setElements(Node.accept(visitor, Node.class, elements)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -81,7 +81,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterPropertyNode(this)) {
             return visitor.leavePropertyNode(
                 setKey((PropertyKey)((Node)key).accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -86,7 +86,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterReturnNode(this)) {
             if (expression != null) {
                 return visitor.leaveReturnNode(setExpression(expression.accept(visitor)));
--- a/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,6 +29,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -407,7 +408,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterRuntimeNode(this)) {
             final List<Node> newArgs = new ArrayList<>();
             for (final Node arg : args) {
--- a/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -81,7 +81,7 @@
     }
 
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterSplitNode(this)) {
             return visitor.leaveSplitNode(setBody(lc, body.accept(visitor)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -100,11 +100,11 @@
     }
 
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterSwitchNode(this)) {
             return visitor.leaveSwitchNode(
-                setExpression(visitor.getLexicalContext(), expression.accept(visitor)).
-                setCases(visitor.getLexicalContext(), Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
+                setExpression(lc, expression.accept(visitor)).
+                setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
         }
 
         return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,6 +29,8 @@
 import java.util.HashSet;
 import java.util.Set;
 import java.util.StringTokenizer;
+
+import jdk.nashorn.internal.codegen.types.Range;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
@@ -89,6 +91,9 @@
     /** Number of times this symbol is used in code */
     private int useCount;
 
+    /** Range for symbol */
+    private Range range;
+
     /** Debugging option - dump info and stack trace when symbols with given names are manipulated */
     private static final Set<String> TRACE_SYMBOLS;
     private static final Set<String> TRACE_SYMBOLS_STACKTRACE;
@@ -131,6 +136,7 @@
         this.type       = type;
         this.slot       = slot;
         this.fieldIndex = -1;
+        this.range      = Range.createUnknownRange();
         trace("CREATE SYMBOL");
     }
 
@@ -157,12 +163,13 @@
 
     private Symbol(final Symbol base, final String name, final int flags) {
         this.flags = flags;
-        this.name = name;
+        this.name  = name;
 
         this.fieldIndex = base.fieldIndex;
-        this.slot = base.slot;
-        this.type = base.type;
-        this.useCount = base.useCount;
+        this.slot       = base.slot;
+        this.type       = base.type;
+        this.useCount   = base.useCount;
+        this.range      = base.range;
     }
 
     private static String align(final String string, final int max) {
@@ -276,7 +283,7 @@
 
     @Override
     public String toString() {
-        final StringBuilder sb   = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
 
         sb.append(name).
             append(' ').
@@ -410,6 +417,22 @@
     }
 
     /**
+     * Get the range for this symbol
+     * @return range for symbol
+     */
+    public Range getRange() {
+        return range;
+    }
+
+    /**
+     * Set the range for this symbol
+     * @param range range
+     */
+    public void setRange(final Range range) {
+        this.range = range;
+    }
+
+    /**
      * Check if this symbol is a function parameter of known
      * narrowest type
      * @return true if parameter
--- a/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTernaryNode(this)) {
             final Node newLhs = lhs().accept(visitor);
             final Node newRhs = rhs().accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,6 +36,11 @@
     /** Exception expression. */
     private final Node expression;
 
+    private final int flags;
+
+    /** Is this block a synthethic rethrow created by finally inlining? */
+    public static final int IS_SYNTHETIC_RETHROW = 1;
+
     /**
      * Constructor
      *
@@ -43,15 +48,18 @@
      * @param token      token
      * @param finish     finish
      * @param expression expression to throw
+     * @param flags      flags
      */
-    public ThrowNode(final int lineNumber, final long token, final int finish, final Node expression) {
+    public ThrowNode(final int lineNumber, final long token, final int finish, final Node expression, final int flags) {
         super(lineNumber, token, finish);
         this.expression = expression;
+        this.flags = flags;
     }
 
-    private ThrowNode(final ThrowNode node, final Node expression) {
+    private ThrowNode(final ThrowNode node, final Node expression, final int flags) {
         super(node);
         this.expression = expression;
+        this.flags = flags;
     }
 
     @Override
@@ -64,7 +72,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterThrowNode(this)) {
             return visitor.leaveThrowNode(setExpression(expression.accept(visitor)));
         }
@@ -98,7 +106,17 @@
         if (this.expression == expression) {
             return this;
         }
-        return new ThrowNode(this, expression);
+        return new ThrowNode(this, expression, flags);
+    }
+
+    /**
+     * Is this a throw a synthetic rethrow in a synthetic catch-all block
+     * created when inlining finally statements? In that case we never
+     * wrap whatever is thrown into an ECMAException, just rethrow it.
+     * @return true if synthetic throw node
+     */
+    public boolean isSyntheticRethrow() {
+        return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
     }
 
 }
--- a/nashorn/src/jdk/nashorn/internal/ir/TryNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -106,7 +106,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTryNode(this)) {
             // Need to do finallybody first for termination analysis. TODO still necessary?
             final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,7 +29,6 @@
 import static jdk.nashorn.internal.parser.TokenType.CONVERT;
 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -121,7 +120,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterUnaryNode(this)) {
             return visitor.leaveUnaryNode(setRHS(rhs.accept(visitor)));
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/VarNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -121,7 +121,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterVarNode(this)) {
             final IdentNode newName = (IdentNode)name.accept(visitor);
             final Node      newInit = init == null ? null : init.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -75,7 +75,7 @@
     }
 
     @Override
-    protected Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterWhileNode(this)) {
             if (isDoWhile()) {
                 return visitor.leaveWhileNode(
--- a/nashorn/src/jdk/nashorn/internal/ir/WithNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -64,7 +64,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterWithNode(this)) {
              return visitor.leaveWithNode(
                 setExpression(lc, expression.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -45,6 +45,7 @@
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
@@ -74,7 +75,8 @@
 /**
  * This IR writer produces a JSON string that represents AST as a JSON string.
  */
-public final class JSONWriter extends NodeVisitor {
+public final class JSONWriter extends NodeVisitor<LexicalContext> {
+
     /**
      * Returns AST as JSON compatible string.
      *
@@ -867,7 +869,8 @@
     // Internals below
 
     private JSONWriter(final boolean includeLocation) {
-        this.buf = new StringBuilder();
+        super(new LexicalContext());
+        this.buf             = new StringBuilder();
         this.includeLocation = includeLocation;
     }
 
@@ -963,7 +966,7 @@
             objectStart("loc");
 
             // source name
-            final Source src = getLexicalContext().getCurrentFunction().getSource();
+            final Source src = lc.getCurrentFunction().getSource();
             property("source", src.getName());
             comma();
 
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,6 +36,7 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Statement;
@@ -53,7 +54,7 @@
  *
  * see the flags --print-parse and --print-lower-parse
  */
-public final class PrintVisitor extends NodeVisitor {
+public final class PrintVisitor extends NodeVisitor<LexicalContext> {
     /** Tab width */
     private static final int TABWIDTH = 4;
 
@@ -84,6 +85,7 @@
      * @param printLineNumbers  should line number nodes be included in the output?
      */
     public PrintVisitor(final boolean printLineNumbers) {
+        super(new LexicalContext());
         this.EOLN             = System.lineSeparator();
         this.sb               = new StringBuilder();
         this.printLineNumbers = printLineNumbers;
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Wed Jul 05 18:57:52 2017 +0200
@@ -32,21 +32,15 @@
 
 /**
  * Like NodeVisitor but navigating further into operators.
+ * @param <T> Lexical context class for this NodeOperatorVisitor
  */
-public class NodeOperatorVisitor extends NodeVisitor {
-    /**
-     * Constructor
-     */
-    public NodeOperatorVisitor() {
-        super();
-    }
-
+public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
     /**
      * Constructor
      *
      * @param lc a custom lexical context
      */
-    public NodeOperatorVisitor(final LexicalContext lc) {
+    public NodeOperatorVisitor(final T lc) {
         super(lc);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Wed Jul 05 18:57:52 2017 +0200
@@ -60,23 +60,18 @@
 
 /**
  * Visitor used to navigate the IR.
+ * @param <T> lexical context class used by this visitor
  */
-public abstract class NodeVisitor {
-    private final LexicalContext lc;
-
-    /**
-     * Constructor
-     */
-    public NodeVisitor() {
-        this(new LexicalContext());
-    }
+public abstract class NodeVisitor<T extends LexicalContext> {
+    /** lexical context in use */
+    protected final T lc;
 
     /**
      * Constructor
      *
      * @param lc a custom lexical context
      */
-    public NodeVisitor(final LexicalContext lc) {
+    public NodeVisitor(final T lc) {
         this.lc = lc;
     }
 
@@ -84,7 +79,7 @@
      * Get the lexical context of this node visitor
      * @return lexical context
      */
-    public LexicalContext getLexicalContext() {
+    public T getLexicalContext() {
         return lc;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Wed Jul 05 18:57:52 2017 +0200
@@ -59,11 +59,6 @@
     }
 
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
-    public static Object BYTES_PER_ELEMENT(final Object self) {
-        return ((ArrayBufferView)self).bytesPerElement();
-    }
-
-    @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
     public static Object buffer(final Object self) {
         return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
     }
--- a/nashorn/src/jdk/nashorn/internal/objects/DateParser.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/DateParser.java	Wed Jul 05 18:57:52 2017 +0200
@@ -32,6 +32,7 @@
 import static java.lang.Character.UPPERCASE_LETTER;
 
 import java.util.HashMap;
+import java.util.Locale;
 
 /**
  * JavaScript date parser. This class first tries to parse a date string
@@ -486,7 +487,7 @@
         while (pos < limit && isAsciiLetter(string.charAt(pos))) {
             pos++;
         }
-        final String key = string.substring(start, pos).toLowerCase();
+        final String key = string.substring(start, pos).toLowerCase(Locale.ENGLISH);
         final Name name = names.get(key);
         // then advance to end of name
         while (pos < length && isAsciiLetter(string.charAt(pos))) {
@@ -683,7 +684,7 @@
 
         Name(final String name, final int type, final int value) {
             assert name != null;
-            assert name.equals(name.toLowerCase());
+            assert name.equals(name.toLowerCase(Locale.ENGLISH));
 
             this.name = name;
             // use first three characters as lookup key
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java	Wed Jul 05 18:57:52 2017 +0200
@@ -603,6 +603,11 @@
         }
     }
 
+    @Override
+    public Object getLength() {
+        return length;
+    }
+
     private Object getArgumentsLength() {
         return length;
     }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 18:57:52 2017 +0200
@@ -754,25 +754,11 @@
         final Object       obj                 = Global.toObject(self);
         final ScriptObject sobj                = (ScriptObject)obj;
         final long         len                 = JSType.toUint32(sobj.getLength());
-        final double       startNum            = JSType.toNumber(start);
-        final long         relativeStartUint32 = JSType.toUint32(startNum);
-        final long         relativeStart       = JSType.toInteger(startNum);
-
-        long k = relativeStart < 0 ?
-                Math.max(len + relativeStart, 0) :
-                Math.min(
-                    Math.max(relativeStartUint32, relativeStart),
-                    len);
+        final long         relativeStart       = JSType.toLong(start);
+        final long         relativeEnd         = (end == ScriptRuntime.UNDEFINED) ? len : JSType.toLong(end);
 
-        final double endNum = (end == ScriptRuntime.UNDEFINED)? Double.NaN : JSType.toNumber(end);
-        final long relativeEndUint32 = (end == ScriptRuntime.UNDEFINED)? len : JSType.toUint32(endNum);
-        final long relativeEnd       = (end == ScriptRuntime.UNDEFINED)? len : JSType.toInteger(endNum);
-
-        final long finale = relativeEnd < 0 ?
-                Math.max(len + relativeEnd, 0) :
-                Math.min(
-                    Math.max(relativeEndUint32, relativeEnd),
-                    len);
+        long k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
+        final long finale = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
 
         if (k >= finale) {
             return new NativeArray(0);
@@ -909,21 +895,10 @@
         final ScriptObject sobj                = (ScriptObject)obj;
         final boolean      strict              = Global.isStrict();
         final long         len                 = JSType.toUint32(sobj.getLength());
-        final double       startNum            = JSType.toNumber(start);
-        final long         relativeStartUint32 = JSType.toUint32(startNum);
-        final long         relativeStart       = JSType.toInteger(startNum);
+        final long         relativeStart       = JSType.toLong(start);
 
-        //TODO: workaround overflow of relativeStart for start > Integer.MAX_VALUE
-        final long actualStart = relativeStart < 0 ?
-            Math.max(len + relativeStart, 0) :
-            Math.min(
-                Math.max(relativeStartUint32, relativeStart),
-                len);
-
-        final long actualDeleteCount =
-            Math.min(
-                Math.max(JSType.toInteger(deleteCount), 0),
-                len - actualStart);
+        final long actualStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
+        final long actualDeleteCount = Math.min(Math.max(JSType.toLong(deleteCount), 0), len - actualStart);
 
         final NativeArray array = new NativeArray(actualDeleteCount);
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -770,7 +770,7 @@
             nd.setTime(NaN);
             return nd.getTime();
         }
-        int yearInt = JSType.toInteger(yearNum);
+        int yearInt = (int)yearNum;
         if (0 <= yearInt && yearInt <= 99) {
             yearInt += 1900;
         }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,12 @@
  */
 @ScriptClass("Float32Array")
 public final class NativeFloat32Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 4;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 4;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,12 @@
  */
 @ScriptClass("Float64Array")
 public final class NativeFloat64Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 8;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 8;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
@@ -37,7 +39,12 @@
  */
 @ScriptClass("Int16Array")
 public final class NativeInt16Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 2;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 2;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
@@ -37,7 +39,12 @@
  */
 @ScriptClass("Int32Array")
 public final class NativeInt32Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 4;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 4;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
@@ -37,7 +39,12 @@
  */
 @ScriptClass("Int8Array")
 public final class NativeInt8Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 1;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 1;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,6 +30,8 @@
 
 import java.lang.reflect.Array;
 import java.util.Collection;
+import java.util.Deque;
+import java.util.List;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -37,6 +39,7 @@
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ListAdapter;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
 
@@ -240,39 +243,56 @@
     }
 
     /**
-     * Given a JavaScript array and a Java type, returns a Java array with the same initial contents, and with the
-     * specified component type. Example:
+     * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
+     * performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
      * <pre>
      * var anArray = [1, "13", false]
-     * var javaIntArray = Java.toJavaArray(anArray, "int")
+     * var javaIntArray = Java.to(anArray, "int[]")
      * print(javaIntArray[0]) // prints 1
      * print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
      * print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
      * </pre>
      * @param self not used
-     * @param objArray the JavaScript array. Can be null.
-     * @param objType either a {@link #type(Object, Object) type object} or a String describing the component type of
-     * the Java array to create. Can not be null. If undefined, Object is assumed (allowing the argument to be omitted).
-     * @return a Java array with the copy of JavaScript array's contents, converted to the appropriate Java component
-     * type. Returns null if objArray is null.
+     * @param obj the script object. Can be null.
+     * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
+     * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
+     * omitted).
+     * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
+     * target types, returns a Java array of the same type with contents converted to the array's component type. Does
+     * not recursively convert for multidimensional arrays. For {@link List} or {@link Deque}, returns a live wrapper
+     * around the object, see {@link ListAdapter} for details. Returns null if obj is null.
      * @throws ClassNotFoundException if the class described by objType is not found
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object toJavaArray(final Object self, final Object objArray, final Object objType) throws ClassNotFoundException {
-        final StaticClass componentType =
-            objType instanceof StaticClass ?
-                (StaticClass)objType :
-                objType == UNDEFINED ?
-                    StaticClass.forClass(Object.class) :
-                    type(objType);
-
-        if (objArray == null) {
+    public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException {
+        if (obj == null) {
             return null;
         }
 
-        Global.checkObject(objArray);
+        Global.checkObject(obj);
 
-        return ((ScriptObject)objArray).getArray().asArrayOfType(componentType.getRepresentedClass());
+        final Class<?> targetClass;
+        if(objType == UNDEFINED) {
+            targetClass = Object[].class;
+        } else {
+            final StaticClass targetType;
+            if(objType instanceof StaticClass) {
+                targetType = (StaticClass)objType;
+            } else {
+                targetType = type(objType);
+            }
+            targetClass = targetType.getRepresentedClass();
+        }
+
+        if(targetClass.isArray()) {
+            return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType());
+        }
+
+        if(targetClass == List.class || targetClass == Deque.class) {
+            return new ListAdapter((ScriptObject)obj);
+        }
+
+        throw typeError("unsupported.java.to.type", targetClass.getName());
     }
 
     /**
@@ -283,7 +303,7 @@
      * <pre>
      * var File = Java.type("java.io.File")
      * var listHomeDir = new File("~").listFiles()
-     * var jsListHome = Java.toJavaScriptArray(listHomeDir)
+     * var jsListHome = Java.from(listHomeDir)
      * var jpegModifiedDates = jsListHome
      *     .filter(function(val) { return val.getName().endsWith(".jpg") })
      *     .map(function(val) { return val.lastModified() })
@@ -294,7 +314,7 @@
      * null.
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object toJavaScriptArray(final Object self, final Object objArray) {
+    public static Object from(final Object self, final Object objArray) {
         if (objArray == null) {
             return null;
         } else if (objArray instanceof Collection) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java	Wed Jul 05 18:57:52 2017 +0200
@@ -611,13 +611,11 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object round(final Object self, final Object x) {
-        if (GlobalFunctions.isNaN(self, x)) {
-            return Double.NaN;
-        } else if (!GlobalFunctions.isFinite(self, x)) {
-            return x;
+        final double d = JSType.toNumber(x);
+        if (Math.getExponent(d) >= 52) {
+            return d;
         }
-
-        return Math.round(JSType.toNumber(x));
+        return Math.copySign(Math.floor(d + 0.5), d);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java	Wed Jul 05 18:57:52 2017 +0200
@@ -38,6 +38,7 @@
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Locale;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -630,17 +631,24 @@
 
         final String str       = checkObjectToString(self);
         final String searchStr = JSType.toString(search);
+        final int length       = str.length();
 
-        int from;
+        int end;
 
         if (pos == UNDEFINED) {
-            from = str.length();
+            end = length;
         } else {
             final double numPos = JSType.toNumber(pos);
-            from = !Double.isNaN(numPos) ? (int)numPos : (int)Double.POSITIVE_INFINITY;
+            end = Double.isNaN(numPos) ? length : (int)numPos;
+            if (end < 0) {
+                end = 0;
+            } else if (end > length) {
+                end = length;
+            }
         }
 
-        return str.lastIndexOf(searchStr, from);
+
+        return str.lastIndexOf(searchStr, end);
     }
 
     /**
@@ -997,7 +1005,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object toLowerCase(final Object self) {
-        return checkObjectToString(self).toLowerCase();
+        return checkObjectToString(self).toLowerCase(Locale.ROOT);
     }
 
     /**
@@ -1017,7 +1025,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object toUpperCase(final Object self) {
-        return checkObjectToString(self).toUpperCase();
+        return checkObjectToString(self).toUpperCase(Locale.ROOT);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
@@ -37,7 +39,12 @@
  */
 @ScriptClass("Uint16Array")
 public final class NativeUint16Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 2;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 2;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,12 @@
  */
 @ScriptClass("Uint32Array")
 public final class NativeUint32Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 4;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 4;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteBegin, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
@@ -37,7 +39,12 @@
  */
 @ScriptClass("Uint8Array")
 public final class NativeUint8Array extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 1;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 1;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,7 +28,9 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,12 @@
  */
 @ScriptClass("Uint8ClampedArray")
 public final class NativeUint8ClampedArray extends ArrayBufferView {
-    private static final int BYTES_PER_ELEMENT = 1;
+    /**
+     * The size in bytes of each element in the array.
+     */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+    public static final int BYTES_PER_ELEMENT = 1;
+
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
         @Override
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 18:57:52 2017 +0200
@@ -1537,7 +1537,7 @@
 
         endOfLine();
 
-        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression));
+        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, 0));
     }
 
     /**
@@ -1597,7 +1597,7 @@
                 try {
                     // Get CATCH body.
                     final Block catchBody = getBlock(true);
-                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody);
+                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, 0);
                     appendStatement(catchNode);
                 } finally {
                     catchBlock = restoreBlock(catchBlock);
--- a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.parser;
 
+import java.util.Locale;
 import static jdk.nashorn.internal.parser.TokenKind.BINARY;
 import static jdk.nashorn.internal.parser.TokenKind.BRACKET;
 import static jdk.nashorn.internal.parser.TokenKind.FUTURE;
@@ -249,7 +250,7 @@
     }
 
     public String getNameOrType() {
-        return name == null ? super.name().toLowerCase() : name;
+        return name == null ? super.name().toLowerCase(Locale.ENGLISH) : name;
     }
 
     public TokenType getNext() {
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Jul 05 18:57:52 2017 +0200
@@ -75,7 +75,23 @@
 
     private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
     private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
-    private static final MethodHandle SPILLGETTER = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), Lookup.GET_OBJECT_TYPE);
+    private static final MethodHandle SPILL_ELEMENT_GETTER;
+    private static final MethodHandle SPILL_ELEMENT_SETTER;
+
+    private static final int SPILL_CACHE_SIZE = 8;
+    private static final MethodHandle[] SPILL_ACCESSORS = new MethodHandle[SPILL_CACHE_SIZE * 2];
+
+    static {
+        for (int i = 0; i < NOOF_TYPES; i++) {
+            final Type type = ACCESSOR_TYPES.get(i);
+            ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class);
+            ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass());
+        }
+
+        final MethodHandle spillGetter = MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class);
+        SPILL_ELEMENT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, spillGetter);
+        SPILL_ELEMENT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, spillGetter);
+    }
 
     /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
     private MethodHandle primitiveGetter;
@@ -96,14 +112,6 @@
      */
     private Class<?> currentType;
 
-    static {
-        for (int i = 0; i < NOOF_TYPES; i++) {
-            final Type type = ACCESSOR_TYPES.get(i);
-            ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class);
-            ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass());
-        }
-    }
-
     /**
      * Delegate constructor. This is used when adding properties to the Global scope, which
      * is necessary for outermost levels in a script (the ScriptObject is represented by
@@ -114,19 +122,31 @@
      * @param delegate  delegate script object to rebind receiver to
      */
     public AccessorProperty(final AccessorProperty property, final ScriptObject delegate) {
-        this(property);
-
-        this.getters = new MethodHandle[NOOF_TYPES];
+        super(property);
 
-        this.primitiveGetter = bindTo(primitiveGetter, delegate);
-        this.primitiveSetter = bindTo(primitiveSetter, delegate);
-        this.objectGetter    = bindTo(objectGetter, delegate);
-        this.objectSetter    = bindTo(objectSetter, delegate);
+        this.primitiveGetter = bindTo(property.primitiveGetter, delegate);
+        this.primitiveSetter = bindTo(property.primitiveSetter, delegate);
+        this.objectGetter    = bindTo(property.objectGetter, delegate);
+        this.objectSetter    = bindTo(property.objectSetter, delegate);
 
         setCurrentType(property.getCurrentType());
     }
 
     /**
+     * Constructor for spill properties. Array getters and setters will be created on demand.
+     *
+     * @param key    the property key
+     * @param flags  the property flags
+     * @param slot   spill slot
+     */
+    public AccessorProperty(final String key, final int flags, final int slot) {
+        super(key, flags, slot);
+        assert (flags & IS_SPILL) == IS_SPILL;
+
+        setCurrentType(Object.class);
+    }
+
+    /**
      * Constructor. Similar to the constructor with both primitive getters and setters, the difference
      * here being that only one getter and setter (setter is optional for non writable fields) is given
      * to the constructor, and the rest are created from those. Used e.g. by Nasgen classes
@@ -268,7 +288,40 @@
     }
 
     @Override
+    protected void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict)  {
+        if (isSpill()) {
+            self.spill[getSlot()] = value;
+        } else {
+            try {
+                getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
+            } catch (final Error|RuntimeException e) {
+                throw e;
+            } catch (final Throwable e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    protected Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
+        if (isSpill()) {
+            return self.spill[getSlot()];
+        }
+
+        try {
+            return getGetter(Object.class).invokeExact((Object)self);
+        } catch (final Error|RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
     public MethodHandle getGetter(final Class<?> type) {
+        if (isSpill() && objectGetter == null) {
+            objectGetter = getSpillGetter();
+        }
         final int i = getAccessorTypeIndex(type);
         if (getters[i] == null) {
             getters[i] = debug(
@@ -284,7 +337,7 @@
                 "get");
         }
 
-        return isSpill() ? MH.filterArguments(getters[i], 0, SPILLGETTER) : getters[i];
+        return getters[i];
     }
 
     private Property getWiderProperty(final Class<?> type) {
@@ -313,6 +366,9 @@
     }
 
     private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
+        if (isSpill() && objectSetter == null) {
+            objectSetter = getSpillSetter();
+        }
         MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter);
         mh = MH.asType(mh, ACCESSOR_SETTER_TYPES[getAccessorTypeIndex(type)]); //has to be the case for invokeexact to work in ScriptObject
         mh = debug(mh, currentType, type, "set");
@@ -343,7 +399,7 @@
             mh = generateSetter(forType, type);
         }
 
-        return isSpill() ? MH.filterArguments(mh, 0, SPILLGETTER) : mh;
+        return mh;
     }
 
     @Override
@@ -363,6 +419,30 @@
         setCurrentType(newType);
     }
 
+    private MethodHandle getSpillGetter() {
+        final int slot = getSlot();
+        MethodHandle getter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2] : null;
+        if (getter == null) {
+            getter = MH.asType(MH.insertArguments(SPILL_ELEMENT_GETTER, 1, slot), Lookup.GET_OBJECT_TYPE);
+            if (slot < SPILL_CACHE_SIZE) {
+                SPILL_ACCESSORS[slot * 2] = getter;
+            }
+        }
+        return getter;
+    }
+
+    private MethodHandle getSpillSetter() {
+        final int slot = getSlot();
+        MethodHandle setter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2 + 1] : null;
+        if (setter == null) {
+            setter = MH.asType(MH.insertArguments(SPILL_ELEMENT_SETTER, 1, slot), Lookup.SET_OBJECT_TYPE);
+            if (slot < SPILL_CACHE_SIZE) {
+                SPILL_ACCESSORS[slot * 2 + 1] = setter;
+            }
+        }
+        return setter;
+    }
+
     private static void finest(final String str) {
         if (DEBUG_FIELDS) {
             LOG.finest(str);
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Jul 05 18:57:52 2017 +0200
@@ -35,21 +35,27 @@
  */
 final class CompiledFunction implements Comparable<CompiledFunction> {
 
+    /** The method type may be more specific than the invoker, if. e.g.
+     *  the invoker is guarded, and a guard with a generic object only
+     *  fallback, while the target is more specific, we still need the
+     *  more specific type for sorting */
+    private final MethodType   type;
     private final MethodHandle invoker;
     private MethodHandle constructor;
 
-    CompiledFunction(final MethodHandle invoker) {
-        this(invoker, null);
+    CompiledFunction(final MethodType type, final MethodHandle invoker) {
+        this(type, invoker, null);
     }
 
-    CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) {
-        this.invoker = invoker;
-        this.constructor = constructor; //isConstructor
+    CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
+        this.type        = type;
+        this.invoker     = invoker;
+        this.constructor = constructor;
     }
 
     @Override
     public String toString() {
-        return "<invoker=" + invoker + " ctor=" + constructor + ">";
+        return "<callSiteType= " + type + " invoker=" + invoker + " ctor=" + constructor + ">";
     }
 
     MethodHandle getInvoker() {
@@ -69,7 +75,7 @@
     }
 
     MethodType type() {
-        return invoker.type();
+        return type;
     }
 
     @Override
@@ -103,8 +109,8 @@
         return weight() > o.weight();
     }
 
-    boolean moreGenericThan(final MethodType type) {
-        return weight() > weight(type);
+    boolean moreGenericThan(final MethodType mt) {
+        return weight() > weight(mt);
     }
 
     /**
@@ -112,15 +118,15 @@
      * It is compatible if the types are narrower than the invocation type so that
      * a semantically equivalent linkage can be performed.
      *
-     * @param typesc
+     * @param mt type to check against
      * @return
      */
-    boolean typeCompatible(final MethodType type) {
-        final Class<?>[] wantedParams   = type.parameterArray();
+    boolean typeCompatible(final MethodType mt) {
+        final Class<?>[] wantedParams   = mt.parameterArray();
         final Class<?>[] existingParams = type().parameterArray();
 
         //if we are not examining a varargs type, the number of parameters must be the same
-        if (wantedParams.length != existingParams.length && !isVarArgsType(type)) {
+        if (wantedParams.length != existingParams.length && !isVarArgsType(mt)) {
             return false;
         }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java	Wed Jul 05 18:57:52 2017 +0200
@@ -35,7 +35,6 @@
  */
 
 public final class DebugLogger {
-    @SuppressWarnings("NonConstantLogger")
     private final Logger  logger;
     private final boolean isEnabled;
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java	Wed Jul 05 18:57:52 2017 +0200
@@ -78,9 +78,9 @@
             //only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor
             //is too conservative a check. However, isConstructor(mh) always implies isConstructor param
             assert isConstructor();
-            code.add(new CompiledFunction(MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor
+            code.add(new CompiledFunction(mh.type(), MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor
         } else {
-            code.add(new CompiledFunction(mh));
+            code.add(new CompiledFunction(mh.type(), mh));
         }
     }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jul 05 18:57:52 2017 +0200
@@ -153,5 +153,24 @@
         return prototype.isScope();
     }
 
+    /**
+     * Get the property value from self as object.
+     *
+     * @return the property value
+     */
+    public Object getObjectValue() {
+        return property.getObjectValue(getGetterReceiver(), getOwner());
+    }
+
+    /**
+     * Set the property value in self.
+     *
+     * @param value the new value
+     * @param strict strict flag
+     */
+    public void setObjectValue(final Object value, final boolean strict) {
+        property.setObjectValue(getSetterReceiver(), getOwner(), value, strict);
+    }
+
 }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,6 +30,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.util.Locale;
 
 /**
  * Utilities used by Global class.
@@ -373,10 +374,10 @@
             } else if (ch < 256) {
                 sb.append('%');
                 final byte b = (byte)ch;
-                sb.append(Integer.toHexString(b & 0xFF).toUpperCase());
+                sb.append(Integer.toHexString(b & 0xFF).toUpperCase(Locale.ENGLISH));
             } else {
                 sb.append("%u");
-                sb.append(Integer.toHexString(ch & 0xFFFF).toUpperCase());
+                sb.append(Integer.toHexString(ch & 0xFFFF).toUpperCase(Locale.ENGLISH));
             }
         }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,6 +36,8 @@
 import jdk.nashorn.internal.parser.JSONParser;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
 /**
  * Utilities used by "JSON" object implementation.
@@ -94,7 +96,7 @@
         if (reviver instanceof ScriptFunction) {
             assert global instanceof GlobalObject;
             final ScriptObject root = ((GlobalObject)global).newObject();
-            root.set("", unfiltered, root.isStrictContext());
+            root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
             return walk(root, "", (ScriptFunction)reviver);
         }
         return unfiltered;
@@ -115,7 +117,7 @@
                 if (newElement == ScriptRuntime.UNDEFINED) {
                     valueObj.delete(key, strict);
                 } else {
-                    valueObj.set(key, newElement, strict);
+                    setPropertyValue(valueObj, key, newElement, strict);
                 }
             }
         }
@@ -175,7 +177,9 @@
                 final PropertyNode pNode     = (PropertyNode) elem;
                 final Node         valueNode = pNode.getValue();
 
-                object.set(pNode.getKeyName(), convertNode(global, valueNode), strict);
+                final String name = pNode.getKeyName();
+                final Object value = convertNode(global, valueNode);
+                setPropertyValue(object, name, value, strict);
             }
 
             return object;
@@ -188,6 +192,21 @@
         }
     }
 
+    // add a new property if does not exist already, or else set old property
+    private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
+        final int index = getArrayIndexNoThrow(name);
+        if (isValidArrayIndex(index)) {
+            // array index key
+            sobj.defineOwnProperty(index, value);
+        } else if (sobj.getMap().findProperty(name) != null) {
+            // pre-existing non-inherited property, call set
+            sobj.set(name, value, strict);
+        } else {
+            // add new property
+            sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
+        }
+    }
+
     // does the given IR node represent a numeric array?
     private static boolean isNumericArray(final Node[] values) {
         for (final Node node : values) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
+import java.util.Locale;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.parser.Lexer;
@@ -111,7 +112,7 @@
      */
     public final String typeName() {
         // For NULL, "object" has to be returned!
-        return ((this == NULL) ? OBJECT : this).name().toLowerCase();
+        return ((this == NULL) ? OBJECT : this).name().toLowerCase(Locale.ENGLISH);
     }
 
     /**
@@ -565,8 +566,11 @@
     }
 
     /**
-     * JavaScript compliant Object to integer conversion
-     * See ECMA 9.4 ToInteger
+     * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger
+     *
+     * <p>Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE}
+     * for double values that exceed the int range, including positive and negative Infinity. It is the
+     * caller's responsibility to handle such values correctly.</p>
      *
      * @param obj  an object
      * @return an integer
@@ -576,8 +580,11 @@
     }
 
     /**
-     * JavaScript compliant Object to long conversion
-     * See ECMA 9.4 ToInteger
+     * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger
+     *
+     * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE}
+     * for double values that exceed the long range, including positive and negative Infinity. It is the
+     * caller's responsibility to handle such values correctly.</p>
      *
      * @param obj  an object
      * @return a long
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,337 @@
+package jdk.nashorn.internal.runtime;
+
+import java.util.AbstractList;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import java.util.RandomAccess;
+import jdk.nashorn.internal.runtime.linker.InvokeByName;
+
+/**
+ * An adapter that can wrap any ECMAScript Array-like object (that adheres to the array rules for the property
+ * {@code length} and having conforming {@code push}, {@code pop}, {@code shift}, {@code unshift}, and {@code splice}
+ * methods) and expose it as both a Java list and double-ended queue. While script arrays aren't necessarily efficient
+ * as dequeues, it's still slightly more efficient to be able to translate dequeue operations into pushes, pops, shifts,
+ * and unshifts, than to blindly translate all list's add/remove operations into splices. Also, it is conceivable that a
+ * custom script object that implements an Array-like API can have a background data representation that is optimized
+ * for dequeue-like access. Note that with ECMAScript arrays, {@code push} and {@pop} operate at the end of the array,
+ * while in Java {@code Deque} they operate on the front of the queue and as such the Java dequeue {@link #push(Object)}
+ * and {@link #pop()} operations will translate to {@code unshift} and {@code shift} script operations respectively,
+ * while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and {@code pop}.
+ */
+public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
+    // These add to the back and front of the list
+    private static final InvokeByName PUSH    = new InvokeByName("push",    ScriptObject.class, void.class, Object.class);
+    private static final InvokeByName UNSHIFT = new InvokeByName("unshift", ScriptObject.class, void.class, Object.class);
+
+    // These remove from the back and front of the list
+    private static final InvokeByName POP   = new InvokeByName("pop",   ScriptObject.class, Object.class);
+    private static final InvokeByName SHIFT = new InvokeByName("shift", ScriptObject.class, Object.class);
+
+    // These insert and remove in the middle of the list
+    private static final InvokeByName SPLICE_ADD    = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class);
+    private static final InvokeByName SPLICE_REMOVE = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class);
+
+    private final ScriptObject obj;
+
+    /**
+     * Creates a new list wrapper for the specified script object.
+     * @param obj script the object to wrap
+     */
+    public ListAdapter(ScriptObject obj) {
+        this.obj = obj;
+    }
+
+    @Override
+    public int size() {
+        return JSType.toInt32(obj.getLength());
+    }
+
+    @Override
+    public Object get(int index) {
+        checkRange(index);
+        return obj.get(index);
+    }
+
+    @Override
+    public Object set(int index, Object element) {
+        checkRange(index);
+        final Object prevValue = get(index);
+        obj.set(index, element, false);
+        return prevValue;
+    }
+
+    private void checkRange(int index) {
+        if(index < 0 || index >= size()) {
+            throw invalidIndex(index);
+        }
+    }
+
+    @Override
+    public void push(Object e) {
+        addFirst(e);
+    }
+
+    @Override
+    public boolean add(Object e) {
+        addLast(e);
+        return true;
+    }
+
+    @Override
+    public void addFirst(Object e) {
+        try {
+            final Object fn = UNSHIFT.getGetter().invokeExact(obj);
+            checkFunction(fn, UNSHIFT);
+            UNSHIFT.getInvoker().invokeExact(fn, obj, e);
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    @Override
+    public void addLast(Object e) {
+        try {
+            final Object fn = PUSH.getGetter().invokeExact(obj);
+            checkFunction(fn, PUSH);
+            PUSH.getInvoker().invokeExact(fn, obj, e);
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    @Override
+    public void add(int index, Object e) {
+        try {
+            if(index < 0) {
+                throw invalidIndex(index);
+            } else if(index == 0) {
+                addFirst(e);
+            } else {
+                final int size = size();
+                if(index < size) {
+                    final Object fn = SPLICE_ADD.getGetter().invokeExact(obj);
+                    checkFunction(fn, SPLICE_ADD);
+                    SPLICE_ADD.getInvoker().invokeExact(fn, obj, index, 0, e);
+                } else if(index == size) {
+                    addLast(e);
+                } else {
+                    throw invalidIndex(index);
+                }
+            }
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+    private static void checkFunction(Object fn, InvokeByName invoke) {
+        if(!(fn instanceof ScriptFunction)) {
+            throw new UnsupportedOperationException("The script object doesn't have a function named " + invoke.getName());
+        }
+    }
+
+    private static IndexOutOfBoundsException invalidIndex(int index) {
+        return new IndexOutOfBoundsException(String.valueOf(index));
+    }
+
+    @Override
+    public boolean offer(Object e) {
+        return offerLast(e);
+    }
+
+    @Override
+    public boolean offerFirst(Object e) {
+        addFirst(e);
+        return true;
+    }
+
+    @Override
+    public boolean offerLast(Object e) {
+        addLast(e);
+        return true;
+    }
+
+    @Override
+    public Object pop() {
+        return removeFirst();
+    }
+
+    @Override
+    public Object remove() {
+        return removeFirst();
+    }
+
+    @Override
+    public Object removeFirst() {
+        checkNonEmpty();
+        return invokeShift();
+    }
+
+    @Override
+    public Object removeLast() {
+        checkNonEmpty();
+        return invokePop();
+    }
+
+    private void checkNonEmpty() {
+        if(isEmpty()) {
+            throw new NoSuchElementException();
+        }
+    }
+
+    @Override
+    public Object remove(int index) {
+        if(index < 0) {
+            throw invalidIndex(index);
+        } else if (index == 0) {
+            return invokeShift();
+        } else {
+            final int maxIndex = size() - 1;
+            if(index < maxIndex) {
+                final Object prevValue = get(index);
+                invokeSpliceRemove(index, 1);
+                return prevValue;
+            } else if(index == maxIndex) {
+                return invokePop();
+            } else {
+                throw invalidIndex(index);
+            }
+        }
+    }
+
+    private Object invokeShift() {
+        try {
+            final Object fn = SHIFT.getGetter().invokeExact(obj);
+            checkFunction(fn, SHIFT);
+            return SHIFT.getInvoker().invokeExact(fn, obj);
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    private Object invokePop() {
+        try {
+            final Object fn = POP.getGetter().invokeExact(obj);
+            checkFunction(fn, POP);
+            return POP.getInvoker().invokeExact(fn, obj);
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    @Override
+    protected void removeRange(int fromIndex, int toIndex) {
+        invokeSpliceRemove(fromIndex, toIndex - fromIndex);
+    }
+
+    private void invokeSpliceRemove(int fromIndex, int count) {
+        try {
+            final Object fn = SPLICE_REMOVE.getGetter().invokeExact(obj);
+            checkFunction(fn, SPLICE_REMOVE);
+            SPLICE_REMOVE.getInvoker().invokeExact(fn, obj, fromIndex, count);
+        } catch(RuntimeException | Error ex) {
+            throw ex;
+        } catch(Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    @Override
+    public Object poll() {
+        return pollFirst();
+    }
+
+    @Override
+    public Object pollFirst() {
+        return isEmpty() ? null : invokeShift();
+    }
+
+    @Override
+    public Object pollLast() {
+        return isEmpty() ? null : invokePop();
+    }
+
+    @Override
+    public Object peek() {
+        return peekFirst();
+    }
+
+    @Override
+    public Object peekFirst() {
+        return isEmpty() ? null : get(0);
+    }
+
+    @Override
+    public Object peekLast() {
+        return isEmpty() ? null : get(size() - 1);
+    }
+
+    @Override
+    public Object element() {
+        return getFirst();
+    }
+
+    @Override
+    public Object getFirst() {
+        checkNonEmpty();
+        return get(0);
+    }
+
+    @Override
+    public Object getLast() {
+        checkNonEmpty();
+        return get(size() - 1);
+    }
+
+    @Override
+    public Iterator<Object> descendingIterator() {
+        final ListIterator<Object> it = listIterator(size());
+        return new Iterator<Object>() {
+            @Override
+            public boolean hasNext() {
+                return it.hasPrevious();
+            }
+
+            @Override
+            public Object next() {
+                return it.previous();
+            }
+
+            @Override
+            public void remove() {
+                it.remove();
+            }
+        };
+    }
+
+    @Override
+    public boolean removeFirstOccurrence(Object o) {
+        return removeOccurrence(o, iterator());
+    }
+
+    @Override
+    public boolean removeLastOccurrence(Object o) {
+        return removeOccurrence(o, descendingIterator());
+    }
+
+    private static boolean removeOccurrence(Object o, Iterator<Object> it) {
+        while(it.hasNext()) {
+            final Object e = it.next();
+            if(o == null ? e == null : o.equals(e)) {
+                it.remove();
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/runtime/Logging.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Logging.java	Wed Jul 05 18:57:52 2017 +0200
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.logging.ConsoleHandler;
@@ -117,7 +118,7 @@
                 if ("".equals(value)) {
                     level = Level.INFO;
                 } else {
-                    level = Level.parse(value.toUpperCase());
+                    level = Level.parse(value.toUpperCase(Locale.ENGLISH));
                 }
 
                 final String name = Logging.lastPart(key);
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,10 +25,16 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.objects.NativeJava;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -65,6 +71,10 @@
  * </pre>
  */
 public final class NativeJavaPackage extends ScriptObject {
+    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+    private static final MethodHandle CLASS_NOT_FOUND = findOwnMH("classNotFound", Void.TYPE, NativeJavaPackage.class);
+    private static final MethodHandle TYPE_GUARD = Guards.getClassGuard(NativeJavaPackage.class);
+
     /** Full name of package (includes path.) */
     private final String name;
 
@@ -123,6 +133,30 @@
         return super.getDefaultValue(hint);
     }
 
+    @Override
+    protected GuardedInvocation findNewMethod(CallSiteDescriptor desc) {
+        return createClassNotFoundInvocation(desc);
+    }
+
+    @Override
+    protected GuardedInvocation findCallMethod(CallSiteDescriptor desc, LinkRequest request) {
+        return createClassNotFoundInvocation(desc);
+    }
+
+    private static GuardedInvocation createClassNotFoundInvocation(final CallSiteDescriptor desc) {
+        // If NativeJavaPackage is invoked either as a constructor or as a function, throw a ClassNotFoundException as
+        // we can assume the user attempted to instantiate a non-existent class.
+        final MethodType type = desc.getMethodType();
+        return new GuardedInvocation(
+                MH.dropArguments(CLASS_NOT_FOUND, 1, type.parameterList().subList(1, type.parameterCount())),
+                type.parameterType(0) == NativeJavaPackage.class ? null : TYPE_GUARD);
+    }
+
+    @SuppressWarnings("unused")
+    private static void classNotFound(final NativeJavaPackage pkg) throws ClassNotFoundException {
+        throw new ClassNotFoundException(pkg.name);
+    }
+
     /**
      * "No such property" call placeholder.
      *
@@ -188,4 +222,7 @@
         return noSuchProperty(desc, request);
     }
 
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
+    }
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Wed Jul 05 18:57:52 2017 +0200
@@ -52,6 +52,9 @@
      * we can use leave flag byte initialized with (the default) zero value.
      */
 
+    /** Mask for property being both writable, enumerable and configurable */
+    public static final int WRITABLE_ENUMERABLE_CONFIGURABLE = 0b0000_0000_0000;
+
     /** ECMA 8.6.1 - Is this property not writable? */
     public static final int NOT_WRITABLE     = 0b0000_0000_0001;
 
@@ -352,6 +355,27 @@
     }
 
     /**
+     * Set the value of this property in {@code owner}. This allows to bypass creation of the
+     * setter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner object
+     * @param value the new property value
+     * @param strict is this a strict setter?
+     */
+    protected abstract void setObjectValue(ScriptObject self, ScriptObject owner, Object value, boolean strict);
+
+    /**
+     * Set the Object value of this property from {@code owner}. This allows to bypass creation of the
+     * getter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner object
+     * @return  the property value
+     */
+    protected abstract Object getObjectValue(ScriptObject self, ScriptObject owner);
+
+    /**
      * Abstract method for retrieving the setter for the property. We do not know
      * anything about the internal representation when we request the setter, we only
      * know that the setter will take the property as a parameter of the given type.
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,6 +30,8 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.LinkedList;
 
 import jdk.nashorn.internal.codegen.Compiler;
@@ -49,9 +51,16 @@
  */
 public final class RecompilableScriptFunctionData extends ScriptFunctionData {
 
+    /** FunctionNode with the code for this ScriptFunction */
     private FunctionNode functionNode;
-    private final PropertyMap  allocatorMap;
+
+    /** Allocator map from makeMap() */
+    private final PropertyMap allocatorMap;
+
+    /** Code installer used for all further recompilation/specialization of this ScriptFunction */
     private final CodeInstaller<ScriptEnvironment> installer;
+
+    /** Name of class where allocator function resides */
     private final String allocatorClassName;
 
     /** lazily generated allocator */
@@ -60,6 +69,23 @@
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
     /**
+     * Used for specialization based on runtime arguments. Whenever we specialize on
+     * callsite parameter types at runtime, we need to use a parameter type guard to
+     * ensure that the specialized version of the script function continues to be
+     * applicable for a particular callsite *
+     */
+    private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class,  Object[].class);
+
+    /**
+     * It is usually a good gamble whever we detect a runtime callsite with a double
+     * (or java.lang.Number instance) to specialize the parameter to an integer, if the
+     * parameter in question can be represented as one. The double typically only exists
+     * because the compiler doesn't know any better than "a number type" and conservatively
+     * picks doubles when it can't prove that an integer addition wouldn't overflow
+     */
+    private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
+
+    /**
      * Constructor - public as scripts use it
      *
      * @param functionNode       functionNode that represents this function code
@@ -141,14 +167,6 @@
              return; // nothing to do, we have code, at least some.
          }
 
-         // check if function node is lazy, need to compile it.
-         // note that currently function cloning is not working completely, which
-         // means that the compiler will mutate the function node it has been given
-         // once it has been compiled, it cannot be recompiled. This means that
-         // lazy compilation works (not compiled yet) but e.g. specializations won't
-         // until the copy-on-write changes for IR are in, making cloning meaningless.
-         // therefore, currently method specialization is disabled. TODO
-
          if (functionNode.isLazy()) {
              Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
              final Compiler compiler = new Compiler(installer);
@@ -156,38 +174,55 @@
              assert !functionNode.isLazy();
              compiler.install(functionNode);
 
-             // we don't need to update any flags - varArgs and needsCallee are instrincic
-             // in the function world we need to get a destination node from the compile instead
-             // and replace it with our function node. TODO
+             /*
+              * We don't need to update any flags - varArgs and needsCallee are instrincic
+              * in the function world we need to get a destination node from the compile instead
+              * and replace it with our function node. TODO
+              */
          }
 
-         // we can't get here unless we have bytecode, either from eager compilation or from
-         // running a lazy compile on the lines above
+         /*
+          * We can't get to this program point unless we have bytecode, either from
+          * eager compilation or from running a lazy compile on the lines above
+          */
 
          assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
 
          // code exists - look it up and add it into the automatically sorted invoker list
-         addCode(functionNode, null, null);
+         addCode(functionNode);
     }
 
-    private MethodHandle addCode(final FunctionNode fn, final MethodHandle guard, final MethodHandle fallback) {
-        final MethodHandle target =
+    private MethodHandle addCode(final FunctionNode fn) {
+        return addCode(fn, null, null, null);
+    }
+
+    private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
+        final MethodType targetType = new FunctionSignature(fn).getMethodType();
+        MethodHandle target =
             MH.findStatic(
                     LOOKUP,
                     fn.getCompileUnit().getCode(),
                     fn.getName(),
-                    new FunctionSignature(fn).
-                        getMethodType());
-        MethodHandle mh = target;
-        if (guard != null) {
-            try {
-                mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
-            } catch (Throwable e) {
-                e.printStackTrace();
+                    targetType);
+
+        /*
+         * For any integer argument. a double that is representable as an integer is OK.
+         * otherwise the guard would have failed. in that case introduce a filter that
+         * casts the double to an integer, which we know will preserve all precision.
+         */
+        for (int i = 0; i < targetType.parameterCount(); i++) {
+            if (targetType.parameterType(i) == int.class) {
+                //representable as int
+                target = MH.filterArguments(target, i, ENSURE_INT);
             }
         }
 
-        final CompiledFunction cf = new CompiledFunction(mh);
+        MethodHandle mh = target;
+        if (guard != null) {
+            mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
+        }
+
+        final CompiledFunction cf = new CompiledFunction(runtimeType == null ? targetType : runtimeType, mh);
         code.add(cf);
 
         return cf.getInvoker();
@@ -212,69 +247,162 @@
         return Type.OBJECT;
     }
 
-    @SuppressWarnings("unused")
-    private static boolean paramTypeGuard(final Type[] compileTimeTypes, final Type[] runtimeTypes, Object... args) {
-        //System.err.println("Param type guard " + Arrays.asList(args));
+    private static boolean canCoerce(final Object arg, final Type type) {
+        Type argType = runtimeType(arg);
+        if (Type.widest(argType, type) == type || arg == ScriptRuntime.UNDEFINED) {
+            return true;
+        }
+        System.err.println(arg + " does not fit in "+ argType + " " + type + " " + arg.getClass());
+        new Throwable().printStackTrace();
         return false;
     }
 
-    private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Type[].class, Object[].class);
+    @SuppressWarnings("unused")
+    private static boolean paramTypeGuard(final Type[] paramTypes, final Object... args) {
+        final int length = args.length;
+        assert args.length >= paramTypes.length;
+
+        //i==start, skip the this, callee params etc
+        int start = args.length - paramTypes.length;
+        for (int i = start; i < args.length; i++) {
+            final Object arg = args[i];
+            if (!canCoerce(arg, paramTypes[i - start])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @SuppressWarnings("unused")
+    private static int ensureInt(final Object arg) {
+        if (arg instanceof Number) {
+            return ((Number)arg).intValue();
+        } else if (arg instanceof Undefined) {
+            return 0;
+        }
+        throw new AssertionError(arg);
+    }
+
+    /**
+     * Given the runtime callsite args, compute a method type that is equivalent to what
+     * was passed - this is typically a lot more specific that what the compiler has been
+     * able to deduce
+     * @param callSiteType callsite type for the compiled callsite target
+     * @param args runtime arguments to the compiled callsite target
+     * @return adjusted method type, narrowed as to conform to runtime callsite type instead
+     */
+    private static MethodType runtimeType(final MethodType callSiteType, final Object[] args) {
+        if (args == null) {
+            //for example bound, or otherwise runtime arguments to callsite unavailable, then
+            //do not change the type
+            return callSiteType;
+        }
+        final Class<?>[] paramTypes = new Class<?>[callSiteType.parameterCount()];
+        final int        start      = args.length - callSiteType.parameterCount();
+        for (int i = start; i < args.length; i++) {
+            paramTypes[i - start] = runtimeType(args[i]).getTypeClass();
+        }
+        return MH.type(callSiteType.returnType(), paramTypes);
+    }
+
+    private static ArrayList<Type> runtimeType(final MethodType mt) {
+        final ArrayList<Type> type = new ArrayList<>();
+        for (int i = 0; i < mt.parameterCount(); i++) {
+            type.add(Type.typeFor(mt.parameterType(i)));
+        }
+        return type;
+    }
 
     @Override
     MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
-        final MethodHandle mh = super.getBestInvoker(callSiteType, args);
+        final MethodType runtimeType = runtimeType(callSiteType, args);
+        assert runtimeType.parameterCount() == callSiteType.parameterCount();
+
+        final MethodHandle mh = super.getBestInvoker(runtimeType, args);
 
-        if (!functionNode.canSpecialize() || !code.isLessSpecificThan(callSiteType)) {
+        /*
+         * Not all functions can be specialized, for example, if we deemed memory
+         * footprint too large to store a parse snapshot, or if it is meaningless
+         * to do so, such as e.g. for runScript
+         */
+        if (!functionNode.canSpecialize()) {
             return mh;
         }
 
-        final FunctionNode snapshot = functionNode.getSnapshot();
-        if (snapshot == null) {
+        /*
+         * Check if best invoker is equally specific or more specific than runtime
+         * type. In that case, we don't need further specialization, but can use
+         * whatever we have already. We know that it will match callSiteType, or it
+         * would not have been returned from getBestInvoker
+         */
+        if (!code.isLessSpecificThan(runtimeType)) {
             return mh;
         }
 
         int i;
+        final FunctionNode snapshot = functionNode.getSnapshot();
+        assert snapshot != null;
 
-        //classes known at runtime
-        final LinkedList<Type> runtimeArgs = new LinkedList<>();
-        for (i = args.length - 1; i >= args.length - snapshot.getParameters().size(); i--) {
-            runtimeArgs.addLast(runtimeType(args[i]));
-        }
-
-        //classes known at compile time
+        /*
+         * Create a list of the arg types that the compiler knows about
+         * typically, the runtime args are a lot more specific, and we should aggressively
+         * try to use those whenever possible
+         * We WILL try to make an aggressive guess as possible, and add guards if needed.
+         * For example, if the compiler can deduce that we have a number type, but the runtime
+         * passes and int, we might still want to keep it an int, and the gamble to
+         * check that whatever is passed is int representable usually pays off
+         * If the compiler only knows that a parameter is an "Object", it is still worth
+         * it to try to specialize it by looking at the runtime arg.
+         */
         final LinkedList<Type> compileTimeArgs = new LinkedList<>();
         for (i = callSiteType.parameterCount() - 1; i >= 0 && compileTimeArgs.size() < snapshot.getParameters().size(); i--) {
-            compileTimeArgs.addLast(Type.typeFor(callSiteType.parameterType(i)));
+            compileTimeArgs.addFirst(Type.typeFor(callSiteType.parameterType(i)));
         }
 
-        //the classes known at compile time are a safe to generate as primitives without parameter guards
-        //the classes known at runtime are safe to generate as primitives IFF there are parameter guards
+        /*
+         * The classes known at compile time are a safe to generate as primitives without parameter guards
+         * But the classes known at runtime (if more specific than compile time types) are safe to generate as primitives
+         * IFF there are parameter guards
+         */
         MethodHandle guard = null;
+        final ArrayList<Type> runtimeParamTypes = runtimeType(runtimeType);
+        while (runtimeParamTypes.size() > functionNode.getParameters().size()) {
+            runtimeParamTypes.remove(0);
+        }
         for (i = 0; i < compileTimeArgs.size(); i++) {
-            final Type runtimeType = runtimeArgs.get(i);
-            final Type compileType = compileTimeArgs.get(i);
+            final Type rparam = Type.typeFor(runtimeType.parameterType(i));
+            final Type cparam = compileTimeArgs.get(i);
 
-            if (compileType.isObject() && !runtimeType.isObject()) {
+            if (cparam.isObject() && !rparam.isObject()) {
+                //check that the runtime object is still coercible to the runtime type, because compiler can't prove it's always primitive
                 if (guard == null) {
-                    guard = PARAM_TYPE_GUARD;
-                    guard = MH.insertArguments(guard, 0, compileTimeArgs.toArray(new Type[compileTimeArgs.size()]), runtimeArgs.toArray(new Type[runtimeArgs.size()]));
+                    guard = MH.insertArguments(PARAM_TYPE_GUARD, 0, (Object)runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]));
                 }
             }
         }
 
-        //System.err.println("Specialized " + name + " " + runtimeArgs + " known=" + compileTimeArgs);
+        Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
 
         assert snapshot != null;
         assert snapshot != functionNode;
 
         final Compiler compiler = new Compiler(installer);
-        final FunctionNode compiledSnapshot = compiler.compile(snapshot.setHints(null, new Compiler.Hints(compileTimeArgs.toArray(new Type[compileTimeArgs.size()]))));
+
+        final FunctionNode compiledSnapshot = compiler.compile(
+            snapshot.setHints(
+                null,
+                new Compiler.Hints(runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]))));
 
+        /*
+         * No matter how narrow your types were, they can never be narrower than Attr during recompile made them. I.e. you
+         * can put an int into the function here, if you see it as a runtime type, but if the function uses a multiplication
+         * on it, it will still need to be a double. At least until we have overflow checks. Similarly, if an int is
+         * passed but it is used as a string, it makes no sense to make the parameter narrower than Object. At least until
+         * the "different types for one symbol in difference places" work is done
+         */
         compiler.install(compiledSnapshot);
 
-        final MethodHandle nmh = addCode(compiledSnapshot, guard, mh);
-
-        return nmh;
+        return addCode(compiledSnapshot, runtimeType, guard, mh);
     }
 
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Wed Jul 05 18:57:52 2017 +0200
@@ -54,7 +54,7 @@
     private final Namespace namespace;
 
     /** Current Options object. */
-    private Options options;
+    private final Options options;
 
     /** Always allow functions as statements */
     public final boolean _anon_functions;
@@ -155,6 +155,9 @@
     /** print symbols and their contents for the script */
     public final boolean _print_symbols;
 
+    /** range analysis for known types */
+    public final boolean _range_analysis;
+
     /** is this environment in scripting mode? */
     public final boolean _scripting;
 
@@ -183,7 +186,7 @@
      * @param out output print writer
      * @param err error print writer
      */
-    ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
+    public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
         this.out = out;
         this.err = err;
         this.namespace = new Namespace();
@@ -219,6 +222,7 @@
         _print_parse          = options.getBoolean("print.parse");
         _print_lower_parse    = options.getBoolean("print.lower.parse");
         _print_symbols        = options.getBoolean("print.symbols");
+        _range_analysis       = options.getBoolean("range.analysis");
         _scripting            = options.getBoolean("scripting");
         _strict               = options.getBoolean("strict");
         _version              = options.getBoolean("version");
@@ -258,14 +262,19 @@
         }
         this._callsite_flags = callSiteFlags;
 
-        final Option<?> option = options.get("timezone");
-        if (option != null) {
-            this._timezone = (TimeZone)option.getValue();
+        final Option<?> timezoneOption = options.get("timezone");
+        if (timezoneOption != null) {
+            this._timezone = (TimeZone)timezoneOption.getValue();
         } else {
             this._timezone  = TimeZone.getDefault();
         }
 
-        this._locale = Locale.getDefault();
+        final Option<?> localeOption = options.get("locale");
+        if (localeOption != null) {
+            this._locale = (Locale)localeOption.getValue();
+        } else {
+            this._locale = Locale.getDefault();
+        }
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,14 +25,13 @@
 
 package jdk.nashorn.internal.runtime;
 
+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.lookup.Lookup.MH;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
 
 /**
@@ -92,12 +91,13 @@
     CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
         final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args);
 
+        //TODO the boundinvoker.type() could actually be more specific here
         if (isConstructor()) {
             ensureConstructor(originalInv);
-            return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
+            return new CompiledFunction(boundInvoker.type(), boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
         }
 
-        return new CompiledFunction(boundInvoker);
+        return new CompiledFunction(boundInvoker.type(), boundInvoker);
     }
 
     /**
@@ -389,7 +389,9 @@
                 boundInvoker = noArgBoundInvoker;
             }
         } else {
-            final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount(), args.length + (isTargetBound ? 0 : (needsCallee  ? 2 : 1)))];
+            // If target is already bound, insert additional bound arguments after "this" argument, at position 1.
+            final int argInsertPos = isTargetBound ? 1 : 0;
+            final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : (needsCallee  ? 2 : 1)))];
             int next = 0;
             if (!isTargetBound) {
                 if (needsCallee) {
@@ -403,7 +405,7 @@
             // "this" will get dropped anyway by the target invoker. We previously asserted that already bound functions
             // don't take a callee parameter, so we can know that the signature is (this[, args...]) therefore args
             // start at position 1. If the function is not bound, we start inserting arguments at position 0.
-            boundInvoker = MH.insertArguments(originalInvoker, isTargetBound ? 1 : 0, boundArgs);
+            boundInvoker = MH.insertArguments(originalInvoker, argInsertPos, boundArgs);
         }
 
         if (isTargetBound) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
@@ -151,17 +150,6 @@
     /** Method handle for setting the user accessors of a ScriptObject */
     public static final Call SET_USER_ACCESSORS = virtualCall(ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 
-    /** Method handle for getter for {@link UserAccessorProperty}, given a slot */
-    static final Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), ScriptObject.class, "userAccessorGetter", Object.class, ScriptObject.class, int.class, Object.class);
-
-    /** Method handle for setter for {@link UserAccessorProperty}, given a slot */
-    static final Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), ScriptObject.class, "userAccessorSetter", void.class, ScriptObject.class, int.class, String.class, Object.class, Object.class);
-
-    private static final MethodHandle INVOKE_UA_GETTER = Bootstrap.createDynamicInvoker("dyn:call", Object.class,
-            Object.class, Object.class);
-    private static final MethodHandle INVOKE_UA_SETTER = Bootstrap.createDynamicInvoker("dyn:call", void.class,
-            Object.class, Object.class, Object.class);
-
     /**
      * Constructor
      */
@@ -699,17 +687,9 @@
      * @return New property.
      */
     public final Property addOwnProperty(final String key, final int propertyFlags, final Object value) {
-        final MethodHandle setter = addSpill(key, propertyFlags);
-
-        try {
-            setter.invokeExact((Object)this, value);
-        } catch (final Error|RuntimeException e) {
-            throw e;
-        } catch (final Throwable e) {
-            throw new RuntimeException(e);
-        }
-
-        return getMap().findProperty(key);
+        final Property property = addSpillProperty(key, propertyFlags);
+        property.setObjectValue(this, this, value, false);
+        return property;
     }
 
     /**
@@ -744,15 +724,7 @@
         // Erase the property field value with undefined. If the property is defined
         // by user-defined accessors, we don't want to call the setter!!
         if (!(property instanceof UserAccessorProperty)) {
-            try {
-                // make the property value to be undefined
-                //TODO specproperties
-                property.getSetter(Object.class, getMap()).invokeExact((Object)this, (Object)UNDEFINED);
-            } catch (final RuntimeException | Error e) {
-                throw e;
-            } catch (final Throwable t) {
-                throw new RuntimeException(t);
-            }
+            property.setObjectValue(this, this, UNDEFINED, false);
         }
     }
 
@@ -948,18 +920,7 @@
       * @return the value of the property
       */
     protected static Object getObjectValue(final FindProperty find) {
-        final MethodHandle getter = find.getGetter(Object.class);
-        if (getter != null) {
-            try {
-                return getter.invokeExact((Object)find.getGetterReceiver());
-            } catch (final Error|RuntimeException e) {
-                throw e;
-            } catch (final Throwable e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        return UNDEFINED;
+        return find.getObjectValue();
     }
 
     /**
@@ -2087,11 +2048,7 @@
             property = addOwnProperty(property);
         } else {
             int i = getMap().getSpillLength();
-            MethodHandle getter = MH.arrayElementGetter(Object[].class);
-            MethodHandle setter = MH.arrayElementSetter(Object[].class);
-            getter = MH.asType(MH.insertArguments(getter, 1, i), Lookup.GET_OBJECT_TYPE);
-            setter = MH.asType(MH.insertArguments(setter, 1, i), Lookup.SET_OBJECT_TYPE);
-            property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i, getter, setter);
+            property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
             notifyPropertyAdded(this, property);
             property = addOwnProperty(property);
             i = property.getSlot();
@@ -2115,20 +2072,15 @@
 
     /**
      * Add a spill entry for the given key.
-     * @param key           Property key.
-     * @param propertyFlags Property flags.
+     * @param key Property key.
      * @return Setter method handle.
      */
-    private MethodHandle addSpill(final String key, final int propertyFlags) {
-        final Property spillProperty = addSpillProperty(key, propertyFlags);
+    MethodHandle addSpill(final String key) {
+        final Property spillProperty = addSpillProperty(key, 0);
         final Class<?> type = Object.class;
         return spillProperty.getSetter(type, getMap()); //TODO specfields
     }
 
-    MethodHandle addSpill(final String key) {
-        return addSpill(key, 0);
-    }
-
     /**
      * Make sure arguments are paired correctly, with respect to more parameters than declared,
      * fewer parameters than declared and other things that JavaScript allows. This might involve
@@ -2659,14 +2611,8 @@
                 return;
             }
 
-            try {
-                final MethodHandle setter = f.getSetter(Object.class, strict); //TODO specfields
-                setter.invokeExact((Object)f.getSetterReceiver(), value);
-            } catch (final Error|RuntimeException e) {
-                throw e;
-            } catch (final Throwable e) {
-                throw new RuntimeException(e);
-            }
+            f.setObjectValue(value, strict);
+
         } else if (!isExtensible()) {
             if (strict) {
                 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
@@ -2677,13 +2623,7 @@
     }
 
     private void spill(final String key, final Object value) {
-        try {
-            addSpill(key).invokeExact((Object)this, value);
-        } catch (final Error|RuntimeException e) {
-            throw e;
-        } catch (final Throwable e) {
-            throw new RuntimeException(e);
-        }
+        addSpillProperty(key, 0).setObjectValue(this, this, value, false);
     }
 
 
@@ -3217,46 +3157,6 @@
         return (index < 0 || (index >= spill.length)) ? null : spill[index];
     }
 
-    // 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.
-    @SuppressWarnings("unused")
-    private static Object userAccessorGetter(final ScriptObject proto, final int slot, final Object self) {
-        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
-        final Object       func      = container.getSpill(slot);
-
-        if (func instanceof ScriptFunction) {
-            try {
-                return INVOKE_UA_GETTER.invokeExact(func, self);
-            } catch(final Error|RuntimeException t) {
-                throw t;
-            } catch(final Throwable t) {
-                throw new RuntimeException(t);
-            }
-        }
-
-        return UNDEFINED;
-    }
-
-    @SuppressWarnings("unused")
-    private static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
-        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
-        final Object       func      = container.getSpill(slot);
-
-        if (func instanceof ScriptFunction) {
-            try {
-                INVOKE_UA_SETTER.invokeExact(func, self, value);
-            } catch(final Error|RuntimeException t) {
-                throw t;
-            } catch(final Throwable t) {
-                throw new RuntimeException(t);
-            }
-        }  else if (name != null) {
-            throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
-        }
-    }
-
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         final Class<?>   own = ScriptObject.class;
         final MethodType mt  = MH.type(rtype, types);
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Jul 05 18:57:52 2017 +0200
@@ -36,6 +36,7 @@
 import java.lang.reflect.Array;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import jdk.internal.dynalink.beans.StaticClass;
@@ -788,7 +789,7 @@
             return false;
         }
 
-        throw typeError("in.with.non.object", rvalType.toString().toLowerCase());
+        throw typeError("in.with.non.object", rvalType.toString().toLowerCase(Locale.ENGLISH));
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Wed Jul 05 18:57:52 2017 +0200
@@ -46,7 +46,7 @@
 public final class ScriptingFunctions {
 
     /** Handle to implementation of {@link ScriptingFunctions#readLine} - Nashorn extension */
-    public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class);
+    public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class, Object.class);
 
     /** Handle to implementation of {@link ScriptingFunctions#readFully} - Nashorn extension */
     public static final MethodHandle READFULLY = findOwnMH("readFully",     Object.class, Object.class, Object.class);
@@ -78,13 +78,17 @@
      * Nashorn extension: global.readLine (scripting-mode-only)
      * Read one line of input from the standard input.
      *
-     * @param self self reference
+     * @param self   self reference
+     * @param prompt String used as input prompt
      *
      * @return line that was read
      *
      * @throws IOException if an exception occurs
      */
-    public static Object readLine(final Object self) throws IOException {
+    public static Object readLine(final Object self, final Object prompt) throws IOException {
+        if (prompt != UNDEFINED) {
+            System.out.print(JSType.toString(prompt));
+        }
         final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
         return reader.readLine();
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -183,17 +183,10 @@
     private SetMethod createNewSpillPropertySetter() {
         final int nextSpill = getMap().getSpillLength();
 
-        final Property property = createSpillProperty(nextSpill);
+        final Property property = new AccessorProperty(getName(), Property.IS_SPILL, nextSpill);
         return new SetMethod(createSpillMethodHandle(nextSpill, property), property);
     }
 
-    private Property createSpillProperty(final int nextSpill) {
-        final MethodHandle getter = MH.asType(MH.insertArguments(MH.arrayElementGetter(Object[].class), 1, nextSpill), Lookup.GET_OBJECT_TYPE);
-        final MethodHandle setter = MH.asType(MH.insertArguments(MH.arrayElementSetter(Object[].class), 1, nextSpill), Lookup.SET_OBJECT_TYPE);
-
-        return new AccessorProperty(getName(), Property.IS_SPILL, nextSpill, getter, setter);
-    }
-
     private MethodHandle createSpillMethodHandle(final int nextSpill, Property property) {
         final PropertyMap oldMap = getMap();
         final PropertyMap newMap = getNewMap(property);
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Jul 05 18:57:52 2017 +0200
@@ -26,7 +26,15 @@
 package jdk.nashorn.internal.runtime;
 
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 /**
  * Property with user defined getters/setters. Actual getter and setter
@@ -51,6 +59,22 @@
     /** User defined setter function slot. */
     private final int setterSlot;
 
+    /** Getter method handle */
+    private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
+            "userAccessorGetter", Object.class, ScriptObject.class, int.class, Object.class);
+
+    /** Setter method handle */
+    private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
+            "userAccessorSetter", void.class, ScriptObject.class, int.class, String.class, Object.class, Object.class);
+
+    /** Dynamic invoker for getter */
+    private static final MethodHandle INVOKE_UA_GETTER = Bootstrap.createDynamicInvoker("dyn:call", Object.class,
+            Object.class, Object.class);
+
+    /** Dynamic invoker for setter */
+    private static final MethodHandle INVOKE_UA_SETTER = Bootstrap.createDynamicInvoker("dyn:call", void.class,
+            Object.class, Object.class, Object.class);
+
     /**
      * Constructor
      *
@@ -134,8 +158,18 @@
     }
 
     @Override
+    protected Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
+        return userAccessorGetter(owner, getGetterSlot(), self);
+    }
+
+    @Override
+    protected void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
+        userAccessorSetter(owner, getSetterSlot(), strict ? getKey() : null, self, value);
+    }
+
+    @Override
     public MethodHandle getGetter(final Class<?> type) {
-        return Lookup.filterReturnType(ScriptObject.USER_ACCESSOR_GETTER.methodHandle(), type);
+        return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type);
     }
 
     @Override
@@ -146,7 +180,7 @@
 
     @Override
     public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
-        return ScriptObject.USER_ACCESSOR_SETTER.methodHandle();
+        return USER_ACCESSOR_SETTER.methodHandle();
     }
 
     @Override
@@ -155,4 +189,42 @@
         return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
     }
 
+    // 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 ScriptObject proto, final int slot, final Object self) {
+        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
+        final Object       func      = container.getSpill(slot);
+
+        if (func instanceof ScriptFunction) {
+            try {
+                return INVOKE_UA_GETTER.invokeExact(func, self);
+            } catch(final Error|RuntimeException t) {
+                throw t;
+            } catch(final Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }
+
+        return UNDEFINED;
+    }
+
+    static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
+        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
+        final Object       func      = container.getSpill(slot);
+
+        if (func instanceof ScriptFunction) {
+            try {
+                INVOKE_UA_SETTER.invokeExact(func, self, value);
+            } catch(final Error|RuntimeException t) {
+                throw t;
+            } catch(final Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }  else if (name != null) {
+            throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
+        }
+    }
+
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,7 +40,7 @@
  *     private static final InvokeByName TO_JSON = new InvokeByName("toJSON", Object.class, Object.class, Object.class);
  *     ...
  *     final Object toJSONFn = TO_JSON.getGetter().invokeExact(obj);
- *     value = TO_JSON.getInvoker().invokeExact(toJSON, obj, key);
+ *     value = TO_JSON.getInvoker().invokeExact(toJSONFn, obj, key);
  * </pre>
  * In practice, you can have stronger type assumptions if it makes sense for your code, just remember that you must use
  * the same parameter types as the formal types of the arguments for {@code invokeExact} to work:
@@ -50,7 +50,7 @@
  *     final ScriptObject sobj = (ScriptObject)obj;
  *     final Object toJSONFn = TO_JSON.getGetter().invokeExact(sobj);
  *     if(toJSONFn instanceof ScriptFunction) {
- *         value = TO_JSON.getInvoker().invokeExact(toJSON, sobj, key);
+ *         value = TO_JSON.getInvoker().invokeExact(toJSONFn, sobj, key);
  *     }
  * </pre>
  * Note that in general you will not want to reuse a single instance of this class for implementing more than one call
@@ -59,6 +59,7 @@
  * separate instance of this class for every place.
  */
 public class InvokeByName {
+    private final String name;
     private final MethodHandle getter;
     private final MethodHandle invoker;
 
@@ -81,6 +82,7 @@
      * @param ptypes the parameter types of the function.
      */
     public InvokeByName(final String name, final Class<?> targetClass, final Class<?> rtype, final Class<?>... ptypes) {
+        this.name = name;
         getter  = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getItem:" + name, Object.class, targetClass);
 
         final Class<?>[] finalPtypes;
@@ -97,6 +99,14 @@
     }
 
     /**
+     * Returns the name of the function retrieved through this invoker.
+     * @return the name of the function retrieved through this invoker.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
      * Returns the property getter that can be invoked on an object to retrieve the function object that will be
      * subsequently invoked by the invoker returned by {@link #getInvoker()}.
      * @return the property getter method handle for the function.
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Wed Jul 05 18:57:52 2017 +0200
@@ -38,7 +38,7 @@
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.nashorn.internal.runtime.JSType;
-import netscape.javascript.JSObject;
+import jdk.nashorn.api.scripting.JSObject;
 
 /**
  * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Wed Jul 05 18:57:52 2017 +0200
@@ -310,7 +310,34 @@
                 Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
 
         mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR);
-        // Assign MethodHandle fields through invoking getHandle()
+        final Label initGlobal;
+        if(samName != null) {
+            // If the class is a SAM, allow having a ScriptFunction passed as class overrides
+            final Label notAFunction = new Label();
+            mv.dup();
+            mv.instanceOf(SCRIPT_FUNCTION_TYPE);
+            mv.ifeq(notAFunction);
+            mv.checkcast(SCRIPT_FUNCTION_TYPE);
+
+            // Assign MethodHandle fields through invoking getHandle() for a ScriptFunction, only assigning the SAM
+            // method(s).
+            for (final MethodInfo mi : methodInfos) {
+                if(mi.getName().equals(samName)) {
+                    mv.dup();
+                    mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
+                    mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR);
+                } else {
+                    mv.visitInsn(ACONST_NULL);
+                }
+                mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
+            }
+            initGlobal = new Label();
+            mv.goTo(initGlobal);
+            mv.visitLabel(notAFunction);
+        } else {
+            initGlobal = null;
+        }
+        // Assign MethodHandle fields through invoking getHandle() for a ScriptObject
         for (final MethodInfo mi : methodInfos) {
             mv.dup();
             mv.aconst(mi.getName());
@@ -319,6 +346,9 @@
             mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
         }
 
+        if(initGlobal != null) {
+            mv.visitLabel(initGlobal);
+        }
         // Assign "staticGlobal = Context.getGlobal()"
         invokeGetGlobalWithNullCheck(mv);
         mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Wed Jul 05 18:57:52 2017 +0200
@@ -43,6 +43,7 @@
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.security.SecureClassLoader;
+
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
@@ -58,6 +59,7 @@
  * "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this
  * class are normally created by {@link JavaAdapterBytecodeGenerator}.
  */
+@SuppressWarnings("javadoc")
 class JavaAdapterClassLoader extends JavaAdapterGeneratorBase {
     private static final Type PRIVILEGED_ACTION_TYPE = Type.getType(PrivilegedAction.class);
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Wed Jul 05 18:57:52 2017 +0200
@@ -39,6 +39,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.LinkRequestImpl;
 import jdk.nashorn.internal.objects.NativeJava;
@@ -66,6 +67,7 @@
  * </p>
  */
 
+@SuppressWarnings("javadoc")
 public final class JavaAdapterFactory {
     /**
      * A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java	Wed Jul 05 18:57:52 2017 +0200
@@ -33,6 +33,7 @@
  * Base class for both {@link JavaAdapterBytecodeGenerator} and {@link JavaAdapterClassLoader}, containing those
  * bytecode types, type names and method descriptor that are used by both.
  */
+@SuppressWarnings("javadoc")
 abstract class JavaAdapterGeneratorBase {
     static final Type CONTEXT_TYPE       = Type.getType(Context.class);
     static final Type OBJECT_TYPE        = Type.getType(Object.class);
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java	Wed Jul 05 18:57:52 2017 +0200
@@ -42,10 +42,6 @@
        this.value = value;
     }
 
-    void setValue(final T value) {
-        this.value = value;
-    }
-
     /**
      * Return the value of an option
      * @return the option value
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.options;
 
+import java.util.Locale;
 import java.util.TimeZone;
 import jdk.nashorn.internal.runtime.QuotedStringTokenizer;
 
@@ -151,6 +152,9 @@
         case "timezone":
             this.defaultValue = TimeZone.getDefault().getID();
             break;
+        case "locale":
+            this.defaultValue = Locale.getDefault().toLanguageTag();
+            break;
         default:
             break;
         }
@@ -263,7 +267,7 @@
                     this.params = arg;
                     break;
                 case "type":
-                    this.type = arg.toLowerCase();
+                    this.type = arg.toLowerCase(Locale.ENGLISH);
                     break;
                 case "default":
                     this.defaultValue = arg;
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java	Wed Jul 05 18:57:52 2017 +0200
@@ -499,10 +499,10 @@
         case "timezone":
             // default value "TimeZone.getDefault()"
             return new Option<>(TimeZone.getTimeZone(value));
+        case "locale":
+            return new Option<>(Locale.forLanguageTag(value));
         case "keyvalues":
             return new KeyValueOption(value);
-        case "values":
-            return new ValueOption(value);
         case "log":
             final KeyValueOption kv = new KeyValueOption(value);
             Logging.initialize(kv.getValues());
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.options;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.StringTokenizer;
-
-/**
- * This option represents a collection of comma separated values
- */
-public class ValueOption extends Option<String> {
-
-    private Collection<String> values;
-
-    ValueOption(final String value) {
-        super(value);
-        if (value != null) {
-            values = new LinkedHashSet<>();
-            final StringTokenizer st = new StringTokenizer(getValue(), ",");
-            while (st.hasMoreElements()) {
-                values.add(st.nextToken());
-            }
-        }
-    }
-
-    /**
-     * Get the values in the option
-     * @return collection of strings
-     */
-    public Collection<String> getValues() {
-        return Collections.unmodifiableCollection(values);
-    }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.regexp;
-
-import jdk.nashorn.internal.runtime.ParserException;
-
-import static java.util.regex.Pattern.CASE_INSENSITIVE;
-import static java.util.regex.Pattern.MULTILINE;
-import static java.util.regex.Pattern.UNICODE_CASE;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-/**
- * Default regular expression implementation based on java.util.regex package.
- *
- * Note that this class is not thread-safe as it stores the current match result
- * and the string being matched in instance fields.
- */
-public class DefaultRegExp extends RegExp {
-
-    /** Java regexp pattern to use for match. We compile to one of these */
-    private Pattern pattern;
-
-    /** The matcher */
-    private RegExpMatcher matcher;
-
-    /**
-     * Construct a Regular expression from the given {@code source} and {@code flags} strings.
-     *
-     * @param source RegExp source string
-     * @param flags RegExp flag string
-     * @throws ParserException if flags is invalid or source string has syntax error.
-     */
-    public DefaultRegExp(final String source, final String flags) throws ParserException {
-        super(source, flags);
-
-        int intFlags = 0;
-
-        if (isIgnoreCase()) {
-            intFlags |= CASE_INSENSITIVE | UNICODE_CASE;
-        }
-        if (isMultiline()) {
-            intFlags |= MULTILINE;
-        }
-
-        try {
-            RegExpScanner parsed;
-
-            try {
-                parsed = RegExpScanner.scan(source);
-            } catch (final PatternSyntaxException e) {
-                // refine the exception with a better syntax error, if this
-                // passes, just rethrow what we have
-                Pattern.compile(source, intFlags);
-                throw e;
-            }
-
-            if (parsed != null) {
-                this.pattern = Pattern.compile(parsed.getJavaPattern(), intFlags);
-                this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
-            }
-        } catch (final PatternSyntaxException e2) {
-            throwParserException("syntax", e2.getMessage());
-        }
-    }
-
-    @Override
-    public RegExpMatcher match(final String str) {
-        if (pattern == null) {
-            return null; // never matches or similar, e.g. a[]
-        }
-
-        RegExpMatcher currentMatcher = this.matcher;
-
-        if (currentMatcher == null || matcher.getInput() != str) {
-            currentMatcher = new DefaultMatcher(str);
-            this.matcher  = currentMatcher;
-        }
-
-        return currentMatcher;
-    }
-
-    class DefaultMatcher implements RegExpMatcher {
-        final String input;
-        final Matcher defaultMatcher;
-
-        DefaultMatcher(final String input) {
-            this.input = input;
-            this.defaultMatcher = pattern.matcher(input);
-        }
-
-        @Override
-        public boolean search(final int start) {
-            return defaultMatcher.find(start);
-        }
-
-        @Override
-        public String getInput() {
-            return input;
-        }
-
-        @Override
-        public int start() {
-            return defaultMatcher.start();
-        }
-
-        @Override
-        public int start(final int group) {
-            return defaultMatcher.start(group);
-        }
-
-        @Override
-        public int end() {
-            return defaultMatcher.end();
-        }
-
-        @Override
-        public int end(final int group) {
-            return defaultMatcher.end(group);
-        }
-
-        @Override
-        public String group() {
-            return defaultMatcher.group();
-        }
-
-        @Override
-        public String group(final int group) {
-            return defaultMatcher.group(group);
-        }
-
-        @Override
-        public int groupCount() {
-            return defaultMatcher.groupCount();
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,163 @@
+/*
+ * 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.runtime.regexp;
+
+import jdk.nashorn.internal.runtime.ParserException;
+
+import static java.util.regex.Pattern.CASE_INSENSITIVE;
+import static java.util.regex.Pattern.MULTILINE;
+import static java.util.regex.Pattern.UNICODE_CASE;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Default regular expression implementation based on java.util.regex package.
+ *
+ * Note that this class is not thread-safe as it stores the current match result
+ * and the string being matched in instance fields.
+ */
+public class JdkRegExp extends RegExp {
+
+    /** Java regexp pattern to use for match. We compile to one of these */
+    private Pattern pattern;
+
+    /** The matcher */
+    private RegExpMatcher matcher;
+
+    /**
+     * Construct a Regular expression from the given {@code source} and {@code flags} strings.
+     *
+     * @param source RegExp source string
+     * @param flags RegExp flag string
+     * @throws ParserException if flags is invalid or source string has syntax error.
+     */
+    public JdkRegExp(final String source, final String flags) throws ParserException {
+        super(source, flags);
+
+        int intFlags = 0;
+
+        if (isIgnoreCase()) {
+            intFlags |= CASE_INSENSITIVE | UNICODE_CASE;
+        }
+        if (isMultiline()) {
+            intFlags |= MULTILINE;
+        }
+
+        try {
+            RegExpScanner parsed;
+
+            try {
+                parsed = RegExpScanner.scan(source);
+            } catch (final PatternSyntaxException e) {
+                // refine the exception with a better syntax error, if this
+                // passes, just rethrow what we have
+                Pattern.compile(source, intFlags);
+                throw e;
+            }
+
+            if (parsed != null) {
+                this.pattern = Pattern.compile(parsed.getJavaPattern(), intFlags);
+                this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
+            }
+        } catch (final PatternSyntaxException e2) {
+            throwParserException("syntax", e2.getMessage());
+        }
+    }
+
+    @Override
+    public RegExpMatcher match(final String str) {
+        if (pattern == null) {
+            return null; // never matches or similar, e.g. a[]
+        }
+
+        RegExpMatcher currentMatcher = this.matcher;
+
+        if (currentMatcher == null || matcher.getInput() != str) {
+            currentMatcher = new DefaultMatcher(str);
+            this.matcher  = currentMatcher;
+        }
+
+        return currentMatcher;
+    }
+
+    class DefaultMatcher implements RegExpMatcher {
+        final String input;
+        final Matcher defaultMatcher;
+
+        DefaultMatcher(final String input) {
+            this.input = input;
+            this.defaultMatcher = pattern.matcher(input);
+        }
+
+        @Override
+        public boolean search(final int start) {
+            return defaultMatcher.find(start);
+        }
+
+        @Override
+        public String getInput() {
+            return input;
+        }
+
+        @Override
+        public int start() {
+            return defaultMatcher.start();
+        }
+
+        @Override
+        public int start(final int group) {
+            return defaultMatcher.start(group);
+        }
+
+        @Override
+        public int end() {
+            return defaultMatcher.end();
+        }
+
+        @Override
+        public int end(final int group) {
+            return defaultMatcher.end(group);
+        }
+
+        @Override
+        public String group() {
+            return defaultMatcher.group();
+        }
+
+        @Override
+        public String group(final int group) {
+            return defaultMatcher.group(group);
+        }
+
+        @Override
+        public int groupCount() {
+            return defaultMatcher.groupCount();
+        }
+    }
+
+}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java	Wed Jul 05 18:57:52 2017 +0200
@@ -113,7 +113,7 @@
     public static class Factory extends RegExpFactory {
 
         @Override
-        protected RegExp compile(final String pattern, final String flags) throws ParserException {
+        public RegExp compile(final String pattern, final String flags) throws ParserException {
             return new JoniRegExp(pattern, flags);
         }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Wed Jul 05 18:57:52 2017 +0200
@@ -29,7 +29,7 @@
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
- * Factory class for regular expressions. This class creates instances of {@link DefaultRegExp}.
+ * Factory class for regular expressions. This class creates instances of {@link JdkRegExp}.
  * An alternative factory can be installed using the {@code nashorn.regexp.impl} system property.
  */
 public class RegExpFactory {
@@ -62,8 +62,8 @@
      * @return new RegExp
      * @throws ParserException if flags is invalid or pattern string has syntax error.
      */
-    protected RegExp compile(final String pattern, final String flags) throws ParserException {
-        return new DefaultRegExp(pattern, flags);
+    public RegExp compile(final String pattern, final String flags) throws ParserException {
+        return new JdkRegExp(pattern, flags);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Wed Jul 05 18:57:52 2017 +0200
@@ -868,6 +868,9 @@
      *      \ ClassEscape
      */
     private boolean classAtomNoDash() {
+        if (atEOF()) {
+            return false;
+        }
         final int startIn  = position;
         final int startOut = sb.length();
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java	Wed Jul 05 18:57:52 2017 +0200
@@ -21,10 +21,7 @@
 
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAll;
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsClear;
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAt;
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
-import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
@@ -36,8 +33,6 @@
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -49,9 +44,7 @@
 import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.ObjPtr;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
 
 final class Analyser extends Parser {
 
@@ -74,38 +67,9 @@
         //regex.repeatRangeAlloc = 0;
         regex.repeatRangeLo = null;
         regex.repeatRangeHi = null;
-        regex.numCombExpCheck = 0;
-
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) regex.numCombExpCheck = 0;
 
         parse();
 
-        if (Config.USE_NAMED_GROUP) {
-            /* mixed use named group and no-named group */
-            if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
-                if (env.numNamed != env.numMem) {
-                    root = disableNoNameGroupCapture(root);
-                } else {
-                    numberedRefCheck(root);
-                }
-            }
-        } // USE_NAMED_GROUP
-
-        if (Config.USE_NAMED_GROUP) {
-            if (env.numCall > 0) {
-                env.unsetAddrList = new UnsetAddrList(env.numCall);
-                setupSubExpCall(root);
-                // r != 0 ???
-                subexpRecursiveCheckTrav(root);
-                // r < 0 -< err, FOUND_CALLED_NODE = 1
-                subexpInfRecursiveCheckTrav(root);
-                // r != 0  recursion infinite ???
-                regex.numCall = env.numCall;
-            } else {
-                regex.numCall = 0;
-            }
-        } // USE_NAMED_GROUP
-
         if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) {
             Config.log.println("<RAW TREE>");
             Config.log.println(root + "\n");
@@ -129,27 +93,6 @@
             regex.btMemEnd |= regex.captureHistory;
         }
 
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-            if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
-                setupCombExpCheck(root, 0);
-
-                if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
-                    env.numCombExpCheck = 0;
-                } else { // USE_SUBEXP_CALL
-                    if (env.combExpMaxRegNum > 0) {
-                        for (int i=1; i<env.combExpMaxRegNum; i++) {
-                            if (bsAt(env.backrefedMem, i)) {
-                                env.numCombExpCheck = 0;
-                                break;
-                            }
-                        }
-                    }
-                }
-
-            } // USE_SUBEXP_CALL
-            regex.numCombExpCheck = env.numCombExpCheck;
-        } // USE_COMBINATION_EXPLOSION_CHECK
-
         regex.clearOptimizeInfo();
 
         if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);
@@ -167,7 +110,6 @@
         }
 
         if (Config.DEBUG_COMPILE) {
-            if (Config.USE_NAMED_GROUP) Config.log.print(regex.nameTableToString());
             Config.log.println("stack used: " + regex.stackNeeded);
             if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
             Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
@@ -177,157 +119,6 @@
         regex.state = RegexState.NORMAL;
     }
 
-    private void noNameDisableMapFor_cosAlt(Node node, int[]map, Ptr counter) {
-        ConsAltNode can = (ConsAltNode)node;
-        do {
-            can.setCar(noNameDisableMap(can.car, map, counter));
-        } while ((can = can.cdr) != null);
-    }
-
-    private void noNameDisableMapFor_quantifier(Node node, int[]map, Ptr counter) {
-        QuantifierNode qn = (QuantifierNode)node;
-        Node target = qn.target;
-        Node old = target;
-        target = noNameDisableMap(target, map, counter);
-
-        if (target != old) {
-            qn.setTarget(target);
-            if (target.getType() == NodeType.QTFR) qn.reduceNestedQuantifier((QuantifierNode)target);
-        }
-    }
-
-    private Node noNameDisableMapFor_enclose(Node node, int[]map, Ptr counter) {
-        EncloseNode en = (EncloseNode)node;
-        if (en.type == EncloseType.MEMORY) {
-            if (en.isNamedGroup()) {
-                counter.p++;
-                map[en.regNum] = counter.p;
-                en.regNum = counter.p;
-                //en.target = noNameDisableMap(en.target, map, counter);
-                en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
-            } else {
-                node = en.target;
-                en.target = null; // remove first enclose: /(a)(?<b>c)/
-                node = noNameDisableMap(node, map, counter);
-            }
-        } else {
-            //en.target = noNameDisableMap(en.target, map, counter);
-            en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
-        }
-        return node;
-    }
-
-    private void noNameDisableMapFor_anchor(Node node, int[]map, Ptr counter) {
-        AnchorNode an = (AnchorNode)node;
-        switch (an.type) {
-            case AnchorNode.PREC_READ:
-            case AnchorNode.PREC_READ_NOT:
-            case AnchorNode.LOOK_BEHIND:
-            case AnchorNode.LOOK_BEHIND_NOT:
-                an.setTarget(noNameDisableMap(an.target, map, counter));
-        }
-    }
-
-    private Node noNameDisableMap(Node node, int[]map, Ptr counter) {
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            noNameDisableMapFor_cosAlt(node, map, counter);
-            break;
-        case NodeType.QTFR:
-            noNameDisableMapFor_quantifier(node, map, counter);
-            break;
-        case NodeType.ENCLOSE:
-            node = noNameDisableMapFor_enclose(node, map, counter);
-            break;
-        case NodeType.ANCHOR:
-            noNameDisableMapFor_anchor(node, map, counter);
-            break;
-        } // switch
-        return node;
-    }
-
-    private void renumberByMap(Node node, int[]map) {
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                renumberByMap(can.car, map);
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            renumberByMap(((QuantifierNode)node).target, map);
-            break;
-
-        case NodeType.ENCLOSE:
-            renumberByMap(((EncloseNode)node).target, map);
-            break;
-
-        case NodeType.BREF:
-            ((BackRefNode)node).renumber(map);
-            break;
-        } // switch
-    }
-
-    protected final void numberedRefCheck(Node node) {
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                numberedRefCheck(can.car);
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            numberedRefCheck(((QuantifierNode)node).target);
-            break;
-
-        case NodeType.ENCLOSE:
-            numberedRefCheck(((EncloseNode)node).target);
-            break;
-
-        case NodeType.BREF:
-            BackRefNode br = (BackRefNode)node;
-            if (!br.isNameRef()) newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
-            break;
-        } // switch
-    }
-
-    protected final Node disableNoNameGroupCapture(Node root) {
-        int[]map = new int[env.numMem + 1];
-
-        for (int i=1; i<=env.numMem; i++) map[i] = 0;
-
-        root = noNameDisableMap(root, map, new Ptr(0));
-        renumberByMap(root, map);
-
-        for (int i=1, pos=1; i<=env.numMem; i++) {
-            if (map[i] > 0) {
-                env.memNodes[pos] = env.memNodes[i];
-                pos++;
-            }
-        }
-
-        int loc = env.captureHistory;
-        env.captureHistory = bsClear();
-
-        for (int i=1; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
-            if (bsAt(loc, i)) {
-                env.captureHistory = bsOnAtSimple(env.captureHistory, map[i]);
-            }
-        }
-
-        env.numMem = env.numNamed;
-        regex.numMem = env.numNamed;
-
-        regex.renumberNameTable(map);
-
-        return root;
-    }
-
     private void swap(Node a, Node b) {
         a.swap(b);
 
@@ -352,17 +143,6 @@
             } while ((can = can.cdr) != null);
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (cn.isRecursion()) {
-                    return TargetInfo.IS_EMPTY_REC; /* tiny version */
-                } else {
-                    info = quantifiersMemoryInfo(cn.target);
-                }
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.QTFR:
             QuantifierNode qn = (QuantifierNode)node;
             if (qn.upper != 0) {
@@ -417,18 +197,6 @@
             }
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (cn.isRecursion()) {
-                    EncloseNode en = (EncloseNode)cn.target;
-                    if (en.isMinFixed()) min = en.minLength;
-                } else {
-                    min = getMinMatchLength(cn.target);
-                }
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.LIST:
             ConsAltNode can = (ConsAltNode)node;
             do {
@@ -474,15 +242,13 @@
             EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.MEMORY:
-                if (Config.USE_SUBEXP_CALL) {
-                    if (en.isMinFixed()) {
-                        min = en.minLength;
-                    } else {
-                        min = getMinMatchLength(en.target);
-                        en.minLength = min;
-                        en.setMinFixed();
-                    }
-                } // USE_SUBEXP_CALL
+                if (en.isMinFixed()) {
+                    min = en.minLength;
+                } else {
+                    min = getMinMatchLength(en.target);
+                    en.minLength = min;
+                    en.setMinFixed();
+                }
                 break;
 
             case EncloseType.OPTION:
@@ -547,17 +313,6 @@
             }
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (!cn.isRecursion()) {
-                    max = getMaxMatchLength(cn.target);
-                } else {
-                    max = MinMaxLen.INFINITE_DISTANCE;
-                }
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.QTFR:
             QuantifierNode qn = (QuantifierNode)node;
             if (qn.upper != 0) {
@@ -576,15 +331,13 @@
             EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.MEMORY:
-                if (Config.USE_SUBEXP_CALL) {
-                    if (en.isMaxFixed()) {
-                        max = en.maxLength;
-                    } else {
-                        max = getMaxMatchLength(en.target);
-                        en.maxLength = max;
-                        en.setMaxFixed();
-                    }
-                } // USE_SUBEXP_CALL
+                if (en.isMaxFixed()) {
+                    max = en.maxLength;
+                } else {
+                    max = getMaxMatchLength(en.target);
+                    en.maxLength = max;
+                    en.setMaxFixed();
+                }
                 break;
 
             case EncloseType.OPTION:
@@ -663,17 +416,6 @@
             }
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (!cn.isRecursion()) {
-                    len = getCharLengthTree(cn.target, level);
-                } else {
-                    returnCode = GET_CHAR_LEN_VARLEN;
-                }
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.CTYPE:
             len = 1;
 
@@ -686,17 +428,15 @@
             EncloseNode en = (EncloseNode)node;
             switch(en.type) {
             case EncloseType.MEMORY:
-                if (Config.USE_SUBEXP_CALL) {
-                    if (en.isCLenFixed()) {
-                        len = en.charLength;
-                    } else {
-                        len = getCharLengthTree(en.target, level);
-                        if (returnCode == 0) {
-                            en.charLength = len;
-                            en.setCLenFixed();
-                        }
+                if (en.isCLenFixed()) {
+                    len = en.charLength;
+                } else {
+                    len = getCharLengthTree(en.target, level);
+                    if (returnCode == 0) {
+                        en.charLength = len;
+                        en.setCLenFixed();
                     }
-                } // USE_SUBEXP_CALL
+                }
                 break;
 
             case EncloseType.OPTION:
@@ -727,10 +467,6 @@
         switch(x.getType()) {
         case NodeType.CTYPE:
             switch(yType) {
-            case NodeType.CTYPE:
-                CTypeNode cny = (CTypeNode)y;
-                CTypeNode cnx = (CTypeNode)x;
-                return cny.ctype == cnx.ctype && cny.not != cnx.not;
 
             case NodeType.CCLASS:
                 // !swap:!
@@ -756,37 +492,6 @@
             CClassNode xc = (CClassNode)x;
 
             switch(yType) {
-            case NodeType.CTYPE:
-                switch(((CTypeNode)y).ctype) {
-                case CharacterType.WORD:
-                    if (!((CTypeNode)y).not) {
-                        if (xc.mbuf == null && !xc.isNot()) {
-                            for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
-                                if (xc.bs.at(i)) {
-                                    if (EncodingHelper.isWord(i)) return false;
-                                }
-                            }
-                            return true;
-                        }
-                        return false;
-                    } else {
-                        for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
-                            if (!EncodingHelper.isWord(i)) {
-                                if (!xc.isNot()) {
-                                    if (xc.bs.at(i)) return false;
-                                } else {
-                                    if (!xc.bs.at(i)) return false;
-                                }
-                            }
-                        }
-                        return true;
-                    }
-                    // break; not reached
-
-                default:
-                    break;
-                } // inner switch
-                break;
 
             case NodeType.CCLASS:
                 CClassNode yc = (CClassNode)y;
@@ -820,17 +525,6 @@
             if (xs.length() == 0) break;
 
             switch (yType) {
-            case NodeType.CTYPE:
-                CTypeNode cy = ((CTypeNode)y);
-                switch (cy.ctype) {
-                case CharacterType.WORD:
-                    return !cy.not;
-
-                default:
-                    break;
-
-                } // inner switch
-                break;
 
             case NodeType.CCLASS:
                 CClassNode cc = (CClassNode)y;
@@ -873,9 +567,6 @@
         case NodeType.CANY:
             break;
 
-        case NodeType.CALL:
-            break; // if (Config.USE_SUBEXP_CALL)
-
         case NodeType.CTYPE:
         case NodeType.CCLASS:
             if (!exact) n = node;
@@ -977,316 +668,6 @@
         return invalid;
     }
 
-    private static final int RECURSION_EXIST       = 1;
-    private static final int RECURSION_INFINITE    = 2;
-    private int subexpInfRecursiveCheck(Node node, boolean head) {
-        int r = 0;
-
-        switch (node.getType()) {
-        case NodeType.LIST:
-            int min;
-            ConsAltNode x = (ConsAltNode)node;
-            do {
-                int ret = subexpInfRecursiveCheck(x.car, head);
-                if (ret == RECURSION_INFINITE) return ret;
-                r |= ret;
-                if (head) {
-                    min = getMinMatchLength(x.car);
-                    if (min != 0) head = false;
-                }
-            } while ((x = x.cdr) != null);
-            break;
-
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            r = RECURSION_EXIST;
-            do {
-                int ret = subexpInfRecursiveCheck(can.car, head);
-                if (ret == RECURSION_INFINITE) return ret;
-                r &= ret;
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
-            r = subexpInfRecursiveCheck(qn.target, head);
-            if (r == RECURSION_EXIST) {
-                if (qn.lower == 0) r = 0;
-            }
-            break;
-
-        case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
-            switch (an.type) {
-            case AnchorType.PREC_READ:
-            case AnchorType.PREC_READ_NOT:
-            case AnchorType.LOOK_BEHIND:
-            case AnchorType.LOOK_BEHIND_NOT:
-                r = subexpInfRecursiveCheck(an.target, head);
-                break;
-            } // inner switch
-            break;
-
-        case NodeType.CALL:
-            r = subexpInfRecursiveCheck(((CallNode)node).target, head);
-            break;
-
-        case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
-            if (en.isMark2()) {
-                return 0;
-            } else if (en.isMark1()) {
-                return !head ? RECURSION_EXIST : RECURSION_INFINITE;
-                // throw exception here ???
-            } else {
-                en.setMark2();
-                r = subexpInfRecursiveCheck(en.target, head);
-                en.clearMark2();
-            }
-            break;
-
-        default:
-            break;
-        } // switch
-        return r;
-    }
-
-    protected final int subexpInfRecursiveCheckTrav(Node node) {
-        int r = 0;
-
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                r = subexpInfRecursiveCheckTrav(can.car);
-            } while (r == 0 && (can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            r = subexpInfRecursiveCheckTrav(((QuantifierNode)node).target);
-            break;
-
-        case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
-            switch (an.type) {
-            case AnchorType.PREC_READ:
-            case AnchorType.PREC_READ_NOT:
-            case AnchorType.LOOK_BEHIND:
-            case AnchorType.LOOK_BEHIND_NOT:
-                r = subexpInfRecursiveCheckTrav(an.target);
-                break;
-            } // inner switch
-            break;
-
-        case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
-            if (en.isRecursion()) {
-                en.setMark1();
-                r = subexpInfRecursiveCheck(en.target, true);
-                if (r > 0) newValueException(ERR_NEVER_ENDING_RECURSION);
-                en.clearMark1();
-            }
-            r = subexpInfRecursiveCheckTrav(en.target);
-            break;
-
-        default:
-            break;
-        } // switch
-
-        return r;
-    }
-
-    private int subexpRecursiveCheck(Node node) {
-        int r = 0;
-
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                r |= subexpRecursiveCheck(can.car);
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            r = subexpRecursiveCheck(((QuantifierNode)node).target);
-            break;
-
-        case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
-            switch (an.type) {
-            case AnchorType.PREC_READ:
-            case AnchorType.PREC_READ_NOT:
-            case AnchorType.LOOK_BEHIND:
-            case AnchorType.LOOK_BEHIND_NOT:
-                r = subexpRecursiveCheck(an.target);
-                break;
-            } // inner switch
-            break;
-
-        case NodeType.CALL:
-            CallNode cn = (CallNode)node;
-            r = subexpRecursiveCheck(cn.target);
-            if (r != 0) cn.setRecursion();
-            break;
-
-        case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
-            if (en.isMark2()) {
-                return 0;
-            } else if (en.isMark1()) {
-                return 1; /* recursion */
-            } else {
-                en.setMark2();
-                r = subexpRecursiveCheck(en.target);
-                en.clearMark2();
-            }
-            break;
-
-        default:
-            break;
-        } // switch
-
-        return r;
-    }
-
-    private static final int FOUND_CALLED_NODE  = 1;
-    protected final int subexpRecursiveCheckTrav(Node node) {
-        int r = 0;
-
-        switch (node.getType()) {
-        case NodeType.LIST:
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                int ret = subexpRecursiveCheckTrav(can.car);
-                if (ret == FOUND_CALLED_NODE) {
-                    r = FOUND_CALLED_NODE;
-                }
-                // else if (ret < 0) return ret; ???
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
-            r = subexpRecursiveCheckTrav(qn.target);
-            if (qn.upper == 0) {
-                if (r == FOUND_CALLED_NODE) qn.isRefered = true;
-            }
-            break;
-
-        case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
-            switch (an.type) {
-            case AnchorType.PREC_READ:
-            case AnchorType.PREC_READ_NOT:
-            case AnchorType.LOOK_BEHIND:
-            case AnchorType.LOOK_BEHIND_NOT:
-                r = subexpRecursiveCheckTrav(an.target);
-                break;
-            } // inner switch
-            break;
-
-        case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
-            if (!en.isRecursion()) {
-                if (en.isCalled()) {
-                    en.setMark1();
-                    r = subexpRecursiveCheck(en.target);
-                    if (r != 0) en.setRecursion();
-                    en.clearMark1();
-                }
-            }
-            r = subexpRecursiveCheckTrav(en.target);
-            if (en.isCalled()) r |= FOUND_CALLED_NODE;
-            break;
-
-        default:
-            break;
-        } // switch
-
-        return r;
-    }
-
-    private void setCallAttr(CallNode cn) {
-        cn.target = env.memNodes[cn.groupNum]; // no setTarget in call nodes!
-        if (cn.target == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
-
-        ((EncloseNode)cn.target).setCalled();
-        env.btMemStart = BitStatus.bsOnAt(env.btMemStart, cn.groupNum);
-        cn.unsetAddrList = env.unsetAddrList;
-    }
-
-    protected final void setupSubExpCall(Node node) {
-
-        switch(node.getType()) {
-        case NodeType.LIST:
-            ConsAltNode ln = (ConsAltNode)node;
-            do {
-                setupSubExpCall(ln.car);
-            } while ((ln = ln.cdr) != null);
-            break;
-
-        case NodeType.ALT:
-            ConsAltNode can = (ConsAltNode)node;
-            do {
-                setupSubExpCall(can.car);
-            } while ((can = can.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            setupSubExpCall(((QuantifierNode)node).target);
-            break;
-
-        case NodeType.ENCLOSE:
-            setupSubExpCall(((EncloseNode)node).target);
-            break;
-
-        case NodeType.CALL:
-            CallNode cn = (CallNode)node;
-
-            if (cn.groupNum != 0) {
-                int gNum = cn.groupNum;
-
-                if (Config.USE_NAMED_GROUP) {
-                    if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(env.option)) {
-                        newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
-                    }
-                } // USE_NAMED_GROUP
-                if (gNum > env.numMem) newValueException(ERR_UNDEFINED_GROUP_REFERENCE, cn.nameP, cn.nameEnd);
-                setCallAttr(cn);
-            } else {
-                if (Config.USE_NAMED_GROUP) {
-                    NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
-
-                    if (ne == null) {
-                        newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
-                    } else if (ne.backNum > 1) {
-                        newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
-                    } else {
-                        cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
-                        setCallAttr(cn);
-                    }
-                }
-            }
-            break;
-
-        case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
-            switch (an.type) {
-            case AnchorType.PREC_READ:
-            case AnchorType.PREC_READ_NOT:
-            case AnchorType.LOOK_BEHIND:
-            case AnchorType.LOOK_BEHIND_NOT:
-                setupSubExpCall(an.target);
-                break;
-            }
-            break;
-
-        } // switch
-    }
-
     /* divide different length alternatives in look-behind.
     (?<=A|B) ==> (?<=A)|(?<=B)
     (?<!A|B) ==> (?<!A)(?<!B)
@@ -1523,125 +904,6 @@
         return xnode;
     }
 
-    private static final int CEC_THRES_NUM_BIG_REPEAT       = 512;
-    private static final int CEC_INFINITE_NUM               = 0x7fffffff;
-
-    private static final int CEC_IN_INFINITE_REPEAT         = (1<<0);
-    private static final int CEC_IN_FINITE_REPEAT           = (1<<1);
-    private static final int CEC_CONT_BIG_REPEAT            = (1<<2);
-
-    protected final int setupCombExpCheck(Node node, int state) {
-        int r = state;
-        int ret;
-
-        switch (node.getType()) {
-        case NodeType.LIST:
-            ConsAltNode ln = (ConsAltNode)node;
-
-            do {
-                r = setupCombExpCheck(ln.car, r);
-                //prev = ((ConsAltNode)node).car;
-            } while (r >= 0 && (ln = ln.cdr) != null);
-            break;
-
-        case NodeType.ALT:
-            ConsAltNode an = (ConsAltNode)node;
-            do {
-                ret = setupCombExpCheck(an.car, state);
-                r |= ret;
-            } while (ret >= 0 && (an = an.cdr) != null);
-            break;
-
-        case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
-            int childState = state;
-            int addState = 0;
-            int varNum;
-
-            if (!isRepeatInfinite(qn.upper)) {
-                if (qn.upper > 1) {
-                    /* {0,1}, {1,1} are allowed */
-                    childState |= CEC_IN_FINITE_REPEAT;
-
-                    /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
-                    if (env.backrefedMem == 0) {
-                        if (qn.target.getType() == NodeType.ENCLOSE) {
-                            EncloseNode en = (EncloseNode)qn.target;
-                            if (en.type == EncloseType.MEMORY) {
-                                if (en.target.getType() == NodeType.QTFR) {
-                                    QuantifierNode q = (QuantifierNode)en.target;
-                                    if (isRepeatInfinite(q.upper) && q.greedy == qn.greedy) {
-                                        qn.upper = qn.lower == 0 ? 1 : qn.lower;
-                                        if (qn.upper == 1) childState = state;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            if ((state & CEC_IN_FINITE_REPEAT) != 0) {
-                qn.combExpCheckNum = -1;
-            } else {
-                if (isRepeatInfinite(qn.upper)) {
-                    varNum = CEC_INFINITE_NUM;
-                    childState |= CEC_IN_INFINITE_REPEAT;
-                } else {
-                    varNum = qn.upper - qn.lower;
-                }
-
-                if (varNum >= CEC_THRES_NUM_BIG_REPEAT) addState |= CEC_CONT_BIG_REPEAT;
-
-                if (((state & CEC_IN_INFINITE_REPEAT) != 0 && varNum != 0) ||
-                   ((state & CEC_CONT_BIG_REPEAT) != 0 && varNum >= CEC_THRES_NUM_BIG_REPEAT)) {
-                    if (qn.combExpCheckNum == 0) {
-                        env.numCombExpCheck++;
-                        qn.combExpCheckNum = env.numCombExpCheck;
-                        if (env.currMaxRegNum > env.combExpMaxRegNum) {
-                            env.combExpMaxRegNum = env.currMaxRegNum;
-                        }
-                    }
-                }
-            }
-            r = setupCombExpCheck(qn.target, childState);
-            r |= addState;
-            break;
-
-        case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
-            switch( en.type) {
-            case EncloseNode.MEMORY:
-                if (env.currMaxRegNum < en.regNum) {
-                    env.currMaxRegNum = en.regNum;
-                }
-                r = setupCombExpCheck(en.target, state);
-                break;
-
-            default:
-                r = setupCombExpCheck(en.target, state);
-            } // inner switch
-            break;
-
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (cn.isRecursion()) {
-                    env.hasRecursion = true;
-                } else {
-                    r = setupCombExpCheck(cn.target, state);
-                }
-            } // USE_SUBEXP_CALL
-            break;
-
-        default:
-            break;
-
-        } // switch
-
-        return r;
-    }
-
     private static final int IN_ALT                     = (1<<0);
     private static final int IN_NOT                     = (1<<1);
     private static final int IN_REPEAT                  = (1<<2);
@@ -1691,20 +953,12 @@
         case NodeType.CANY:
             break;
 
-        case NodeType.CALL: // if (Config.USE_SUBEXP_CALL) ?
-            break;
-
         case NodeType.BREF:
             BackRefNode br = (BackRefNode)node;
             for (int i=0; i<br.backNum; i++) {
                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
                 env.backrefedMem = bsOnAt(env.backrefedMem, br.back[i]);
                 env.btMemStart = bsOnAt(env.btMemStart, br.back[i]);
-                if (Config.USE_BACKREF_WITH_LEVEL) {
-                    if (br.isNestLevel()) {
-                        env.btMemEnd = bsOnAt(env.btMemEnd, br.back[i]);
-                    }
-                } // USE_BACKREF_AT_LEVEL
                 ((EncloseNode)env.memNodes[br.back[i]]).setMemBackrefed();
             }
             break;
@@ -1916,37 +1170,6 @@
             break;
         }
 
-        case NodeType.CTYPE: {
-            int min;
-            int max = 1;
-            if (max == 1) {
-                min = 1;
-                CTypeNode cn = (CTypeNode)node;
-
-                switch (cn.ctype) {
-                case CharacterType.WORD:
-                    if (cn.not) {
-                        for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
-                            if (!EncodingHelper.isWord(i)) {
-                                opt.map.addChar(i);
-                            }
-                        }
-                    } else {
-                        for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
-                            if (EncodingHelper.isWord(i)) {
-                                opt.map.addChar(i);
-                            }
-                        }
-                    }
-                    break;
-                } // inner switch
-            } else {
-                min = 1;
-            }
-            opt.length.set(min, max);
-            break;
-        }
-
         case NodeType.CANY: {
             opt.length.set(1, 1);
             break;
@@ -2008,20 +1231,6 @@
             break;
         }
 
-        case NodeType.CALL: {
-            if (Config.USE_SUBEXP_CALL) {
-                CallNode cn = (CallNode)node;
-                if (cn.isRecursion()) {
-                    opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
-                } else {
-                    int safe = oenv.options;
-                    oenv.options = ((EncloseNode)cn.target).option;
-                    optimizeNodeLeft(cn.target, opt, oenv);
-                    oenv.options = safe;
-                }
-            } // USE_SUBEXP_CALL
-            break;
-        }
 
         case NodeType.QTFR: {
             NodeOptInfo nopt = new NodeOptInfo();
@@ -2081,7 +1290,7 @@
                 break;
 
             case EncloseType.MEMORY:
-                if (Config.USE_SUBEXP_CALL && ++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
+                if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
                     int min = 0;
                     int max = MinMaxLen.INFINITE_DISTANCE;
                     if (en.isMinFixed()) min = en.minLength;
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java	Wed Jul 05 18:57:52 2017 +0200
@@ -28,8 +28,6 @@
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -71,11 +69,6 @@
         regex.templates = templates;
         regex.templateNum = templateNum;
         regex.factory = MatcherFactory.DEFAULT;
-
-        if (Config.USE_SUBEXP_CALL && analyser.env.unsetAddrList != null) {
-            analyser.env.unsetAddrList.fix(regex);
-            analyser.env.unsetAddrList = null;
-        }
     }
 
     @Override
@@ -119,7 +112,7 @@
         return isNeedStrLenOpExact(op);
     }
 
-    private int selectStrOpcode(int mbLength, int strLength, boolean ignoreCase) {
+    private int selectStrOpcode(int strLength, boolean ignoreCase) {
         int op;
 
         if (ignoreCase) {
@@ -128,31 +121,14 @@
             default:op = OPCode.EXACTN_IC; break;
             } // switch
         } else {
-            switch (mbLength) {
-            case 1:
-                switch (strLength) {
-                case 1: op = OPCode.EXACT1; break;
-                case 2: op = OPCode.EXACT2; break;
-                case 3: op = OPCode.EXACT3; break;
-                case 4: op = OPCode.EXACT4; break;
-                case 5: op = OPCode.EXACT5; break;
-                default:op = OPCode.EXACTN; break;
-                } // inner switch
-                break;
-            case 2:
-                switch (strLength) {
-                case 1: op = OPCode.EXACTMB2N1; break;
-                case 2: op = OPCode.EXACTMB2N2; break;
-                case 3: op = OPCode.EXACTMB2N3; break;
-                default:op = OPCode.EXACTMB2N;  break;
-                } // inner switch
-                break;
-            case 3:
-                op = OPCode.EXACTMB3N;
-                break;
-            default:
-                op = OPCode.EXACTMBN;
-            } // switch
+            switch (strLength) {
+            case 1: op = OPCode.EXACT1; break;
+            case 2: op = OPCode.EXACT2; break;
+            case 3: op = OPCode.EXACT3; break;
+            case 4: op = OPCode.EXACT4; break;
+            case 5: op = OPCode.EXACT5; break;
+            default:op = OPCode.EXACTN; break;
+            } // inner switch
         }
         return op;
     }
@@ -185,8 +161,8 @@
         }
     }
 
-    private int addCompileStringlength(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
-        int op = selectStrOpcode(mbLength, strLength, ignoreCase);
+    private int addCompileStringlength(char[] chars, int p, int strLength, boolean ignoreCase) {
+        int op = selectStrOpcode(strLength, ignoreCase);
         int len = OPSize.OPCODE;
 
         if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
@@ -194,25 +170,21 @@
             len += OPSize.LENGTH + OPSize.INDEX + OPSize.INDEX;
         } else {
             if (isNeedStrLenOpExact(op)) len += OPSize.LENGTH;
-            len += mbLength * strLength;
+            len += strLength;
         }
         if (op == OPCode.EXACTMBN) len += OPSize.LENGTH;
         return len;
     }
 
     @Override
-    protected final void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
-        int op = selectStrOpcode(mbLength, strLength, ignoreCase);
+    protected final void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase) {
+        int op = selectStrOpcode(strLength, ignoreCase);
         addOpcode(op);
 
-        if (op == OPCode.EXACTMBN) addLength(mbLength);
+        if (op == OPCode.EXACTMBN) addLength(1);
 
         if (isNeedStrLenOpExact(op)) {
-            if (op == OPCode.EXACTN_IC || op == OPCode.EXACTN_IC_SB) {
-                addLength(mbLength * strLength);
-            } else {
-                addLength(strLength);
-            }
+            addLength(strLength);
         }
 
         if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
@@ -220,7 +192,7 @@
             addInt(p);
             addTemplate(chars);
         } else {
-            addChars(chars, p, mbLength * strLength);
+            addChars(chars, p, strLength);
         }
     }
 
@@ -242,14 +214,14 @@
             slen++;
             p++;
         }
-        int r = addCompileStringlength(chars, prev, 1, slen, ambig);
+        int r = addCompileStringlength(chars, prev, slen, ambig);
         rlen += r;
         return rlen;
     }
 
     private int compileLengthStringRawNode(StringNode sn) {
         if (sn.length() <= 0) return 0;
-        return addCompileStringlength(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
+        return addCompileStringlength(sn.chars, sn.p, sn.length(), false);
     }
 
     private void addMultiByteCClass(CodeRangeBuffer mbuf) {
@@ -312,26 +284,6 @@
     }
 
     @Override
-    protected void compileCTypeNode(CTypeNode node) {
-        CTypeNode cn = node;
-        int op;
-        switch (cn.ctype) {
-        case CharacterType.WORD:
-            if (cn.not) {
-                op = OPCode.NOT_WORD;
-            } else {
-                op = OPCode.WORD;
-            }
-            break;
-
-        default:
-            newInternalException(ERR_PARSER_BUG);
-            return; // not reached
-        } // inner switch
-        addOpcode(op);
-    }
-
-    @Override
     protected void compileAnyCharNode() {
         if (isMultiline(regex.options)) {
             addOpcode(OPCode.ANYCHAR_ML);
@@ -341,30 +293,15 @@
     }
 
     @Override
-    protected void compileCallNode(CallNode node) {
-        addOpcode(OPCode.CALL);
-        node.unsetAddrList.add(codeLength, node.target);
-        addAbsAddr(0); /*dummy addr.*/
-    }
-
-    @Override
     protected void compileBackrefNode(BackRefNode node) {
         BackRefNode br = node;
-        if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
-            addOpcode(OPCode.BACKREF_WITH_LEVEL);
-            addOption(regex.options & Option.IGNORECASE);
-            addLength(br.nestLevel);
-            // !goto add_bacref_mems;!
-            addLength(br.backNum);
-            for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
-            return;
-        } else { // USE_BACKREF_AT_LEVEL
-            if (br.backNum == 1) {
-                if (isIgnoreCase(regex.options)) {
-                    addOpcode(OPCode.BACKREFN_IC);
-                    addMemNum(br.back[0]);
-                } else {
-                    switch (br.back[0]) {
+        // USE_BACKREF_AT_LEVEL
+        if (br.backNum == 1) {
+            if (isIgnoreCase(regex.options)) {
+                addOpcode(OPCode.BACKREFN_IC);
+                addMemNum(br.back[0]);
+            } else {
+                switch (br.back[0]) {
                     case 1:
                         addOpcode(OPCode.BACKREF1);
                         break;
@@ -375,18 +312,17 @@
                         addOpcode(OPCode.BACKREFN);
                         addOpcode(br.back[0]);
                         break;
-                    } // switch
-                }
+                } // switch
+            }
+        } else {
+            if (isIgnoreCase(regex.options)) {
+                addOpcode(OPCode.BACKREF_MULTI_IC);
             } else {
-                if (isIgnoreCase(regex.options)) {
-                    addOpcode(OPCode.BACKREF_MULTI_IC);
-                } else {
-                    addOpcode(OPCode.BACKREF_MULTI);
-                }
-                // !add_bacref_mems:!
-                addLength(br.backNum);
-                for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
+                addOpcode(OPCode.BACKREF_MULTI);
             }
+            // !add_bacref_mems:!
+            addLength(br.backNum);
+            for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
         }
     }
 
@@ -419,7 +355,7 @@
 
         compileTreeEmptyCheck(qn.target, emptyInfo);
 
-        if ((Config.USE_SUBEXP_CALL && regex.numCall > 0) || qn.isInRepeat()) {
+        if (qn.isInRepeat()) {
             addOpcode(qn.greedy ? OPCode.REPEAT_INC_SG : OPCode.REPEAT_INC_NG_SG);
         } else {
             addOpcode(qn.greedy ? OPCode.REPEAT_INC : OPCode.REPEAT_INC_NG);
@@ -434,193 +370,6 @@
         return ckn > 0;
     }
 
-    private int compileCECLengthQuantifierNode(QuantifierNode qn) {
-        boolean infinite = isRepeatInfinite(qn.upper);
-        int emptyInfo = qn.targetEmptyInfo;
-
-        int tlen = compileLengthTree(qn.target);
-        int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
-        int cklen = cknOn(ckn) ? OPSize.STATE_CHECK_NUM : 0;
-
-        /* anychar repeat */
-        if (qn.target.getType() == NodeType.CANY) {
-            if (qn.greedy && infinite) {
-                if (qn.nextHeadExact != null && !cknOn(ckn)) {
-                    return OPSize.ANYCHAR_STAR_PEEK_NEXT + tlen * qn.lower + cklen;
-                } else {
-                    return OPSize.ANYCHAR_STAR + tlen * qn.lower + cklen;
-                }
-            }
-        }
-
-        int modTLen;
-        if (emptyInfo != 0) {
-            modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
-        } else {
-            modTLen = tlen;
-        }
-
-        int len;
-        if (infinite && qn.lower <= 1) {
-            if (qn.greedy) {
-                if (qn.lower == 1) {
-                    len = OPSize.JUMP;
-                } else {
-                    len = 0;
-                }
-                len += OPSize.PUSH + cklen + modTLen + OPSize.JUMP;
-            } else {
-                if (qn.lower == 0) {
-                    len = OPSize.JUMP;
-                } else {
-                    len = 0;
-                }
-                len += modTLen + OPSize.PUSH + cklen;
-            }
-        } else if (qn.upper == 0) {
-            if (qn.isRefered) { /* /(?<n>..){0}/ */
-                len = OPSize.JUMP + tlen;
-            } else {
-                len = 0;
-            }
-        } else if (qn.upper == 1 && qn.greedy) {
-            if (qn.lower == 0) {
-                if (cknOn(ckn)) {
-                    len = OPSize.STATE_CHECK_PUSH + tlen;
-                } else {
-                    len = OPSize.PUSH + tlen;
-                }
-            } else {
-                len = tlen;
-            }
-        } else if (!qn.greedy && qn.upper == 1 && qn.lower == 0) { /* '??' */
-            len = OPSize.PUSH + cklen + OPSize.JUMP + tlen;
-        } else {
-            len = OPSize.REPEAT_INC + modTLen + OPSize.OPCODE + OPSize.RELADDR + OPSize.MEMNUM;
-
-            if (cknOn(ckn)) {
-                len += OPSize.STATE_CHECK;
-            }
-        }
-        return len;
-    }
-
-    @Override
-    protected void compileCECQuantifierNode(QuantifierNode qn) {
-        boolean infinite = isRepeatInfinite(qn.upper);
-        int emptyInfo = qn.targetEmptyInfo;
-
-        int tlen = compileLengthTree(qn.target);
-
-        int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
-
-        if (qn.isAnyCharStar()) {
-            compileTreeNTimes(qn.target, qn.lower);
-            if (qn.nextHeadExact != null && !cknOn(ckn)) {
-                if (isMultiline(regex.options)) {
-                    addOpcode(OPCode.ANYCHAR_ML_STAR_PEEK_NEXT);
-                } else {
-                    addOpcode(OPCode.ANYCHAR_STAR_PEEK_NEXT);
-                }
-                if (cknOn(ckn)) {
-                    addStateCheckNum(ckn);
-                }
-                StringNode sn = (StringNode)qn.nextHeadExact;
-                addChars(sn.chars, sn.p, 1);
-                return;
-            } else {
-                if (isMultiline(regex.options)) {
-                    if (cknOn(ckn)) {
-                        addOpcode(OPCode.STATE_CHECK_ANYCHAR_ML_STAR);
-                    } else {
-                        addOpcode(OPCode.ANYCHAR_ML_STAR);
-                    }
-                } else {
-                    if (cknOn(ckn)) {
-                        addOpcode(OPCode.STATE_CHECK_ANYCHAR_STAR);
-                    } else {
-                        addOpcode(OPCode.ANYCHAR_STAR);
-                    }
-                }
-                if (cknOn(ckn)) {
-                    addStateCheckNum(ckn);
-                }
-                return;
-            }
-        }
-
-        int modTLen;
-        if (emptyInfo != 0) {
-            modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
-        } else {
-            modTLen = tlen;
-        }
-        if (infinite && qn.lower <= 1) {
-            if (qn.greedy) {
-                if (qn.lower == 1) {
-                    addOpcodeRelAddr(OPCode.JUMP, cknOn(ckn) ? OPSize.STATE_CHECK_PUSH :
-                                                                     OPSize.PUSH);
-                }
-                if (cknOn(ckn)) {
-                    addOpcode(OPCode.STATE_CHECK_PUSH);
-                    addStateCheckNum(ckn);
-                    addRelAddr(modTLen + OPSize.JUMP);
-                } else {
-                    addOpcodeRelAddr(OPCode.PUSH, modTLen + OPSize.JUMP);
-                }
-                compileTreeEmptyCheck(qn.target, emptyInfo);
-                addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + (cknOn(ckn) ?
-                                                                               OPSize.STATE_CHECK_PUSH :
-                                                                               OPSize.PUSH)));
-            } else {
-                if (qn.lower == 0) {
-                    addOpcodeRelAddr(OPCode.JUMP, modTLen);
-                }
-                compileTreeEmptyCheck(qn.target, emptyInfo);
-                if (cknOn(ckn)) {
-                    addOpcode(OPCode.STATE_CHECK_PUSH_OR_JUMP);
-                    addStateCheckNum(ckn);
-                    addRelAddr(-(modTLen + OPSize.STATE_CHECK_PUSH_OR_JUMP));
-                } else {
-                    addOpcodeRelAddr(OPCode.PUSH, -(modTLen + OPSize.PUSH));
-                }
-            }
-        } else if (qn.upper == 0) {
-            if (qn.isRefered) { /* /(?<n>..){0}/ */
-                addOpcodeRelAddr(OPCode.JUMP, tlen);
-                compileTree(qn.target);
-            } // else r=0 ???
-        } else if (qn.upper == 1 && qn.greedy) {
-            if (qn.lower == 0) {
-                if (cknOn(ckn)) {
-                    addOpcode(OPCode.STATE_CHECK_PUSH);
-                    addStateCheckNum(ckn);
-                    addRelAddr(tlen);
-                } else {
-                    addOpcodeRelAddr(OPCode.PUSH, tlen);
-                }
-            }
-            compileTree(qn.target);
-        } else if (!qn.greedy && qn.upper == 1 && qn.lower == 0){ /* '??' */
-            if (cknOn(ckn)) {
-                addOpcode(OPCode.STATE_CHECK_PUSH);
-                addStateCheckNum(ckn);
-                addRelAddr(OPSize.JUMP);
-            } else {
-                addOpcodeRelAddr(OPCode.PUSH, OPSize.JUMP);
-            }
-
-            addOpcodeRelAddr(OPCode.JUMP, tlen);
-            compileTree(qn.target);
-        } else {
-            compileRangeRepeatNode(qn, modTLen, emptyInfo);
-            if (cknOn(ckn)) {
-                addOpcode(OPCode.STATE_CHECK);
-                addStateCheckNum(ckn);
-            }
-        }
-    }
-
     private int compileNonCECLengthQuantifierNode(QuantifierNode qn) {
         boolean infinite = isRepeatInfinite(qn.upper);
         int emptyInfo = qn.targetEmptyInfo;
@@ -821,21 +570,12 @@
         int len;
         switch (node.type) {
         case EncloseType.MEMORY:
-            if (Config.USE_SUBEXP_CALL && node.isCalled()) {
-                len = OPSize.MEMORY_START_PUSH + tlen + OPSize.CALL + OPSize.JUMP + OPSize.RETURN;
-                if (bsAt(regex.btMemEnd, node.regNum)) {
-                    len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
-                } else {
-                    len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
-                }
-            } else { // USE_SUBEXP_CALL
-                if (bsAt(regex.btMemStart, node.regNum)) {
-                    len = OPSize.MEMORY_START_PUSH;
-                } else {
-                    len = OPSize.MEMORY_START;
-                }
-                len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
+            if (bsAt(regex.btMemStart, node.regNum)) {
+                len = OPSize.MEMORY_START_PUSH;
+            } else {
+                len = OPSize.MEMORY_START;
             }
+            len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
             break;
 
         case EncloseType.STOP_BACKTRACK:
@@ -860,23 +600,6 @@
         int len;
         switch (node.type) {
         case EncloseType.MEMORY:
-            if (Config.USE_SUBEXP_CALL) {
-                if (node.isCalled()) {
-                    addOpcode(OPCode.CALL);
-                    node.callAddr = codeLength + OPSize.ABSADDR + OPSize.JUMP;
-                    node.setAddrFixed();
-                    addAbsAddr(node.callAddr);
-                    len = compileLengthTree(node.target);
-                    len += OPSize.MEMORY_START_PUSH + OPSize.RETURN;
-                    if (bsAt(regex.btMemEnd, node.regNum)) {
-                        len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
-                    } else {
-                        len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
-                    }
-                    addOpcodeRelAddr(OPCode.JUMP, len);
-                }
-            } // USE_SUBEXP_CALL
-
             if (bsAt(regex.btMemStart, node.regNum)) {
                 addOpcode(OPCode.MEMORY_START_PUSH);
             } else {
@@ -886,22 +609,12 @@
             addMemNum(node.regNum);
             compileTree(node.target);
 
-            if (Config.USE_SUBEXP_CALL && node.isCalled()) {
-                if (bsAt(regex.btMemEnd, node.regNum)) {
-                    addOpcode(node.isRecursion() ? OPCode.MEMORY_END_PUSH_REC : OPCode.MEMORY_END_PUSH);
-                } else {
-                    addOpcode(node.isRecursion() ? OPCode.MEMORY_END_REC : OPCode.MEMORY_END);
-                }
-                addMemNum(node.regNum);
-                addOpcode(OPCode.RETURN);
-            } else { // USE_SUBEXP_CALL
-                if (bsAt(regex.btMemEnd, node.regNum)) {
-                    addOpcode(OPCode.MEMORY_END_PUSH);
-                } else {
-                    addOpcode(OPCode.MEMORY_END);
-                }
-                addMemNum(node.regNum);
+            if (bsAt(regex.btMemEnd, node.regNum)) {
+                addOpcode(OPCode.MEMORY_END_PUSH);
+            } else {
+                addOpcode(OPCode.MEMORY_END);
             }
+            addMemNum(node.regNum);
             break;
 
         case EncloseType.STOP_BACKTRACK:
@@ -1078,32 +791,17 @@
         case NodeType.BREF:
             BackRefNode br = (BackRefNode)node;
 
-            if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
-                len = OPSize.OPCODE + OPSize.OPTION + OPSize.LENGTH +
-                      OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
-            } else { // USE_BACKREF_AT_LEVEL
-                if (br.backNum == 1) {
-                    len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
-                            ? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
-                } else {
-                    len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
-                }
+            // USE_BACKREF_AT_LEVEL
+            if (br.backNum == 1) {
+                len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
+                        ? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
+            } else {
+                len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
             }
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                len = OPSize.CALL;
-                break;
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.QTFR:
-            if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                len = compileCECLengthQuantifierNode((QuantifierNode)node);
-            } else {
-                len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
-            }
+            len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
             break;
 
         case NodeType.ENCLOSE:
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
-
-final class AsmCompiler extends AsmCompilerSupport {
-
-    public AsmCompiler(Analyser analyser) {
-        super(analyser);
-    }
-
-    @Override
-    protected void prepare() {
-        REG_NUM++;
-        prepareMachine();
-        prepareMachineInit();
-        prepareMachineMatch();
-
-        prepareFactory();
-        prepareFactoryInit();
-    }
-
-    @Override
-    protected void finish() {
-        setupFactoryInit();
-
-        setupMachineInit();
-        setupMachineMatch();
-
-        setupClasses();
-    }
-
-    @Override
-    protected void compileAltNode(ConsAltNode node) {
-    }
-
-    @Override
-    protected void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
-        String template = installTemplate(chars, p, strLength);
-    }
-
-    @Override
-    protected void compileCClassNode(CClassNode node) {
-        if (node.bs != null) {
-            String bitsetName = installBitSet(node.bs.bits);
-        }
-    }
-
-    @Override
-    protected void compileCTypeNode(CTypeNode node) {
-    }
-
-    @Override
-    protected void compileAnyCharNode() {
-    }
-
-    @Override
-    protected void compileBackrefNode(BackRefNode node) {
-    }
-
-    @Override
-    protected void compileCallNode(CallNode node) {
-    }
-
-    @Override
-    protected void compileCECQuantifierNode(QuantifierNode node) {
-    }
-
-    @Override
-    protected void compileNonCECQuantifierNode(QuantifierNode node) {
-    }
-
-    @Override
-    protected void compileOptionNode(EncloseNode node) {
-    }
-
-    @Override
-    protected void compileEncloseNode(EncloseNode node) {
-    }
-
-    @Override
-    protected void compileAnchorNode(AnchorNode node) {
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
-abstract class AsmCompilerSupport extends Compiler implements Opcodes, AsmConstants {
-    protected ClassWriter factory;      // matcher allocator, also bit set, code rage and string template container
-    protected MethodVisitor factoryInit;// factory constructor
-    protected String factoryName;
-
-    protected ClassWriter machine;      // matcher
-    protected MethodVisitor machineInit;// matcher constructor
-    protected MethodVisitor match;      // actual matcher implementation (the matchAt method)
-    protected String machineName;
-
-    // we will? try to manage visitMaxs ourselves for efficiency
-    protected int maxStack = 1;
-    protected int maxVars = LAST_INDEX;
-
-    // for field generation
-    protected int bitsets, ranges, templates;
-
-    // simple class name postfix scheme for now
-    static int REG_NUM = 0;
-
-    // dummy class loader for now
-    private static final class DummyClassLoader extends ClassLoader {
-        public Class<?> defineClass(String name, byte[] bytes) {
-            return super.defineClass(name, bytes, 0, bytes.length);
-        }
-    };
-
-    private static final DummyClassLoader loader = new DummyClassLoader();
-
-    AsmCompilerSupport(Analyser analyser) {
-        super(analyser);
-    }
-
-    protected final void prepareFactory() {
-        factory = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-        factoryName = "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory" + REG_NUM;
-
-        factory.visit(V1_4, ACC_PUBLIC + ACC_FINAL, factoryName, null, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", null);
-
-        MethodVisitor create = factory.visitMethod(ACC_SYNTHETIC, "create", "(Lorg/joni/Regex;[BII)Lorg/joni/Matcher;", null, null);
-        create.visitTypeInsn(NEW, machineName);
-        create.visitInsn(DUP);          // instance
-        create.visitVarInsn(ALOAD, 1);  // Regex
-        create.visitVarInsn(ALOAD, 2);  // bytes[]
-        create.visitVarInsn(ILOAD, 3);  // p
-        create.visitVarInsn(ILOAD, 4);  // end
-        create.visitMethodInsn(INVOKESPECIAL, machineName, "<init>", "(Lorg/joni/Regex;[BII)V");
-        create.visitInsn(ARETURN);
-        create.visitMaxs(0, 0);
-        //create.visitMaxs(6, 5);
-        create.visitEnd();
-    }
-
-    protected final void prepareFactoryInit() {
-        factoryInit = factory.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
-        factoryInit.visitVarInsn(ALOAD, 0);
-        factoryInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", "<init>", "()V");
-    }
-
-    protected final void setupFactoryInit() {
-        factoryInit.visitInsn(RETURN);
-        factoryInit.visitMaxs(0, 0);
-        //init.visitMaxs(1, 1);
-        factoryInit.visitEnd();
-    }
-
-    protected final void prepareMachine() {
-        machine = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-        machineName = "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine" + REG_NUM;
-    }
-
-    protected final void prepareMachineInit() {
-        machine.visit(V1_4, ACC_PUBLIC + ACC_FINAL, machineName, null, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", null);
-        machineInit = machine.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/joni/Regex;[BII)V", null, null);
-        machineInit.visitVarInsn(ALOAD, THIS);  // this
-        machineInit.visitVarInsn(ALOAD, 1);     // Regex
-        machineInit.visitVarInsn(ALOAD, 2);     // bytes[]
-        machineInit.visitVarInsn(ILOAD, 3);     // p
-        machineInit.visitVarInsn(ILOAD, 4);     // end
-        machineInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", "<init>", "(Lorg/joni/Regex;[BII)V");
-    }
-
-    protected final void setupMachineInit() {
-        if (bitsets + ranges + templates > 0) { // ok, some of these are in use, we'd like to cache the factory
-            machine.visitField(ACC_PRIVATE + ACC_FINAL, "factory", "L" + factoryName + ";", null, null);
-            machineInit.visitVarInsn(ALOAD, THIS);  // this
-            machineInit.visitVarInsn(ALOAD, 1);     // this, Regex
-            machineInit.visitFieldInsn(GETFIELD, "jdk/nashorn/internal/runtime/regexp/joni/Regex", "factory", "Lorg/joni/MatcherFactory;"); // this, factory
-            machineInit.visitTypeInsn(CHECKCAST, factoryName);
-            machineInit.visitFieldInsn(PUTFIELD, machineName, "factory", "L" + factoryName + ";"); // []
-        }
-
-        machineInit.visitInsn(RETURN);
-        machineInit.visitMaxs(0, 0);
-        //init.visitMaxs(5, 5);
-        machineInit.visitEnd();
-    }
-
-    protected final void prepareMachineMatch() {
-        match = machine.visitMethod(ACC_SYNTHETIC, "matchAt", "(III)I", null, null);
-        move(S, SSTART);        // s = sstart
-        load("bytes", "[B");    //
-        astore(BYTES);          // byte[]bytes = this.bytes
-    }
-
-    protected final void setupMachineMatch() {
-        match.visitInsn(ICONST_M1);
-        match.visitInsn(IRETURN);
-
-        match.visitMaxs(maxStack, maxVars);
-        match.visitEnd();
-    }
-
-    protected final void setupClasses() {
-        byte[]factoryCode = factory.toByteArray();
-        byte[]machineCode = machine.toByteArray();
-
-        if (Config.DEBUG_ASM) {
-            try {
-                FileOutputStream fos;
-                fos = new FileOutputStream(factoryName.substring(factoryName.lastIndexOf('/') + 1) + ".class");
-                fos.write(factoryCode);
-                fos.close();
-                fos = new FileOutputStream(machineName.substring(machineName.lastIndexOf('/') + 1) + ".class");
-                fos.write(machineCode);
-                fos.close();
-            } catch (IOException ioe) {
-                ioe.printStackTrace(Config.err);
-            }
-        }
-
-        loader.defineClass(machineName.replace('/', '.'), machineCode);
-        Class<?> cls = loader.defineClass(factoryName.replace('/', '.'), factoryCode);
-        try {
-            regex.factory = (MatcherFactory)cls.newInstance();
-        } catch(Exception e) {
-            e.printStackTrace(Config.err);
-        }
-    }
-
-    protected final void aload(int var) {
-        match.visitVarInsn(ALOAD, var);
-    }
-
-    protected final void astore(int var) {
-        match.visitVarInsn(ASTORE, var);
-    }
-
-    protected final void loadThis() {
-        match.visitVarInsn(ALOAD, THIS);
-    }
-
-    protected final void load(int var) {
-        match.visitVarInsn(ILOAD, var);
-    }
-
-    protected final void store(int var) {
-        match.visitVarInsn(ISTORE, var);
-    }
-
-    protected final void move(int to, int from) {
-        load(from);
-        store(to);
-    }
-
-    protected final void load(String field, String singature) {
-        loadThis();
-        match.visitFieldInsn(GETFIELD, machineName, field, singature);
-    }
-
-    protected final void load(String field) {
-        load(field, "I");
-    }
-
-    protected final void store(String field, String singature) {
-        loadThis();
-        match.visitFieldInsn(PUTFIELD, machineName, field, singature);
-    }
-
-    protected final void store(String field) {
-        store(field, "I");
-    }
-
-    protected final String installTemplate(char[] arr, int p, int length) {
-        String templateName = TEMPLATE + ++templates;
-        installArray(templateName, arr, p, length);
-        return templateName;
-    }
-
-    protected final String installCodeRange(int[]arr) {
-        String coreRangeName = CODERANGE + ++ranges;
-        installArray(coreRangeName, arr);
-        return coreRangeName;
-    }
-
-    protected final String installBitSet(int[]arr) {
-        String bitsetName = BITSET + ++bitsets;
-        installArray(bitsetName, arr);
-        return bitsetName;
-    }
-
-    private void installArray(String name, int[]arr) {
-        factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[I", null, null);
-        factoryInit.visitVarInsn(ALOAD, THIS);          // this;
-        loadInt(factoryInit, arr.length);               // this, length
-        factoryInit.visitIntInsn(NEWARRAY, T_INT);      // this, arr
-        for (int i=0;i < arr.length; i++) buildArray(i, arr[i], IASTORE);
-        factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[I");
-    }
-
-    private void installArray(String name, char[]arr, int p, int length) {
-        factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[B", null, null);
-        factoryInit.visitVarInsn(ALOAD, THIS);          // this;
-        loadInt(factoryInit, arr.length);               // this, length
-        factoryInit.visitIntInsn(NEWARRAY, T_BYTE);     // this, arr
-        for (int i=p, j=0; i < p + length; i++, j++) buildArray(j, arr[i] & 0xff, BASTORE);
-        factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[B");
-    }
-
-    private void buildArray(int index, int value, int type) {
-        factoryInit.visitInsn(DUP);     // ... arr, arr
-        loadInt(factoryInit, index);    // ... arr, arr, index
-        loadInt(factoryInit, value);    // ... arr, arr, index, value
-        factoryInit.visitInsn(type);    // ... arr
-    }
-
-    private void loadInt(MethodVisitor mv, int value) {
-        if (value >= -1 && value <= 5) {
-            mv.visitInsn(value + ICONST_0); // ICONST_0 == 3
-        } else if (value >= 6 && value <= 127 || value >= -128 && value <= -2) {
-            mv.visitIntInsn(BIPUSH, value);
-        } else if (value >= 128 && value <= 32767 || value >= -32768 && value <= -129) {
-            mv.visitIntInsn(SIPUSH, value);
-        } else {
-            mv.visitLdcInsn(new Integer(value));
-        }
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java	Wed Jul 05 18:57:52 2017 +0200
@@ -51,10 +51,6 @@
         bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
     }
 
-    public void invert(int pos) {
-        bits[pos >>> ROOM_SHIFT] ^= bit(pos);
-    }
-
     public void clear() {
         for (int i=0; i<BITSET_SIZE; i++) bits[i]=0;
     }
@@ -70,10 +66,6 @@
         for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i);
     }
 
-    public void setAll() {
-        for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~0;
-    }
-
     public void invert() {
         for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i];
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,12 +25,15 @@
     public static int bsClear() {
         return 0;
     }
+
     public static int bsAll() {
         return -1;
     }
+
     public static boolean bsAt(int stats, int n) {
         return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0;
     }
+
     public static int bsOnAt(int stats, int n) {
         if (n < BIT_STATUS_BITS_NUM) {
             stats |= (1 << n);
@@ -39,10 +42,6 @@
         }
         return stats;
     }
-    public static int bsOnAtSimple(int stats, int n) {
-        if (n < BIT_STATUS_BITS_NUM) stats |= (1 << n);
-        return stats;
-    }
 
     public static int bsOnOff(int v, int f, boolean negative) {
         if (negative) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java	Wed Jul 05 18:57:52 2017 +0200
@@ -53,56 +53,6 @@
         this.code = regex.code;
     }
 
-    protected int stkp; // a temporary
-    private boolean makeCaptureHistoryTree(CaptureTreeNode node) {
-        //CaptureTreeNode child;
-        int k = stkp;
-        //int k = kp;
-
-        while (k < stk) {
-            StackEntry e = stack[k];
-            if (e.type == MEM_START) {
-                int n = e.getMemNum();
-                if (n <= Config.MAX_CAPTURE_HISTORY_GROUP && bsAt(regex.captureHistory, n)) {
-                    CaptureTreeNode child = new CaptureTreeNode();
-                    child.group = n;
-                    child.beg = e.getMemPStr() - str;
-                    node.addChild(child);
-                    stkp = k + 1;
-                    if (makeCaptureHistoryTree(child)) return true;
-
-                    k = stkp;
-                    child.end = e.getMemPStr() - str;
-                }
-            } else if (e.type == MEM_END) {
-                if (e.getMemNum() == node.group) {
-                    node.end = e.getMemPStr() - str;
-                    stkp = k;
-                    return false;
-                }
-            }
-        }
-        return true; /* 1: root node ending. */
-    }
-
-    private void checkCaptureHistory(Region region) {
-        CaptureTreeNode node;
-        if (region.historyRoot == null) {
-            node = region.historyRoot = new CaptureTreeNode();
-        } else {
-            node = region.historyRoot;
-            node.clear();
-        }
-
-        // was clear ???
-        node.group = 0;
-        node.beg = sstart - str;
-        node.end = s      - str;
-
-        stkp = 0;
-        makeCaptureHistoryTree(region.historyRoot);
-    }
-
     private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) {
 
         int s2 = ps2.value;
@@ -175,13 +125,6 @@
                 case OPCode.EXACT5:                     opExact5();                continue;
                 case OPCode.EXACTN:                     opExactN();                continue;
 
-                case OPCode.EXACTMB2N1:                 opExactMB2N1();            break;
-                case OPCode.EXACTMB2N2:                 opExactMB2N2();            continue;
-                case OPCode.EXACTMB2N3:                 opExactMB2N3();            continue;
-                case OPCode.EXACTMB2N:                  opExactMB2N();             continue;
-                case OPCode.EXACTMB3N:                  opExactMB3N();             continue;
-                case OPCode.EXACTMBN:                   opExactMBN();              continue;
-
                 case OPCode.EXACT1_IC:                  opExact1IC();              break;
                 case OPCode.EXACTN_IC:                  opExactNIC();              continue;
 
@@ -199,8 +142,6 @@
                 case OPCode.ANYCHAR_ML_STAR:            opAnyCharMLStar();         break;
                 case OPCode.ANYCHAR_STAR_PEEK_NEXT:     opAnyCharStarPeekNext();   break;
                 case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT:  opAnyCharMLStarPeekNext(); break;
-                case OPCode.STATE_CHECK_ANYCHAR_STAR:   opStateCheckAnyCharStar(); break;
-                case OPCode.STATE_CHECK_ANYCHAR_ML_STAR:opStateCheckAnyCharMLStar();break;
 
                 case OPCode.WORD:                       opWord();                  break;
                 case OPCode.NOT_WORD:                   opNotWord();               break;
@@ -239,11 +180,6 @@
                 case OPCode.JUMP:                       opJump();                  continue;
                 case OPCode.PUSH:                       opPush();                  continue;
 
-                // CEC
-                case OPCode.STATE_CHECK_PUSH:           opStateCheckPush();        continue;
-                case OPCode.STATE_CHECK_PUSH_OR_JUMP:   opStateCheckPushOrJump();  continue;
-                case OPCode.STATE_CHECK:                opStateCheck();            continue;
-
                 case OPCode.POP:                        opPop();                   continue;
                 case OPCode.PUSH_OR_JUMP_EXACT1:        opPushOrJumpExact1();      continue;
                 case OPCode.PUSH_IF_PEEK_NEXT:          opPushIfPeekNext();        continue;
@@ -266,10 +202,6 @@
                 case OPCode.PUSH_LOOK_BEHIND_NOT:       opPushLookBehindNot();     continue;
                 case OPCode.FAIL_LOOK_BEHIND_NOT:       opFailLookBehindNot();     continue;
 
-                // USE_SUBEXP_CALL
-                case OPCode.CALL:                       opCall();                  continue;
-                case OPCode.RETURN:                     opReturn();                continue;
-
                 case OPCode.FINISH:
                     return finish();
 
@@ -322,9 +254,6 @@
 
                 }
 
-                if (Config.USE_CAPTURE_HISTORY) {
-                    if (regex.captureHistory != 0) checkCaptureHistory(region);
-                }
             } else {
                 msaBegin = sstart - str;
                 msaEnd   = s      - str;
@@ -437,125 +366,6 @@
         sprev = s - 1;
     }
 
-    private void opExactMB2N1() {
-        if (s + 2 > range) {opFail(); return;}
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        sprev = sbegin; // break;
-    }
-
-    private void opExactMB2N2() {
-        if (s + 4 > range) {opFail(); return;}
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        sprev = s;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-   }
-
-    private void opExactMB2N3() {
-        if (s + 6 > range) {opFail(); return;}
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        sprev = s;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-        if (code[ip] != chars[s]) {opFail(); return;}
-        ip++; s++;
-    }
-
-    private void opExactMB2N() {
-        int tlen = code[ip++];
-        if (s + tlen * 2 > range) {opFail(); return;}
-
-        if (Config.USE_STRING_TEMPLATES) {
-            char[] bs = regex.templates[code[ip++]];
-            int ps = code[ip++];
-
-            while(tlen-- > 0) {
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-            }
-        } else {
-            while(tlen-- > 0) {
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-            }
-        }
-        sprev = s - 2;
-    }
-
-    private void opExactMB3N() {
-        int tlen = code[ip++];
-        if (s + tlen * 3 > range) {opFail(); return;}
-
-        if (Config.USE_STRING_TEMPLATES) {
-            char[] bs = regex.templates[code[ip++]];
-            int ps = code[ip++];
-
-            while (tlen-- > 0) {
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-            }
-        } else {
-            while (tlen-- > 0) {
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-            }
-        }
-
-        sprev = s - 3;
-    }
-
-    private void opExactMBN() {
-        int tlen = code[ip++];   /* mb-len */
-        int tlen2= code[ip++];   /* string len */
-
-        tlen2 *= tlen;
-        if (s + tlen2 > range) {opFail(); return;}
-
-        if (Config.USE_STRING_TEMPLATES) {
-            char[] bs = regex.templates[code[ip++]];
-            int ps = code[ip++];
-
-            while (tlen2-- > 0) {
-                if (bs[ps] != chars[s]) {opFail(); return;}
-                ps++; s++;
-            }
-        } else {
-            while (tlen2-- > 0) {
-                if (code[ip] != chars[s]) {opFail(); return;}
-                ip++; s++;
-            }
-        }
-
-        sprev = s - tlen;
-    }
-
     private void opExact1IC() {
         if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;}
         ip++;
@@ -748,34 +558,6 @@
         sprev = sbegin; // break;
     }
 
-    // CEC
-    private void opStateCheckAnyCharStar() {
-        int mem = code[ip++];
-        final char[] chars = this.chars;
-
-        while (s < range) {
-            if (stateCheckVal(s, mem)) {opFail(); return;}
-            pushAltWithStateCheck(ip, s, sprev, mem);
-            if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;}
-            sprev = s;
-            s++;
-        }
-        sprev = sbegin; // break;
-    }
-
-    // CEC
-    private void opStateCheckAnyCharMLStar() {
-        int mem = code[ip++];
-
-        while (s < range) {
-            if (stateCheckVal(s, mem)) {opFail(); return;}
-            pushAltWithStateCheck(ip, s, sprev, mem);
-            sprev = s;
-            s++;
-        }
-        sprev = sbegin; // break;
-    }
-
     private void opWord() {
         if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;}
         s++;
@@ -1223,33 +1005,6 @@
         pushAlt(ip + addr, s, sprev);
     }
 
-    // CEC
-    private void opStateCheckPush() {
-        int mem = code[ip++];
-        if (stateCheckVal(s, mem)) {opFail(); return;}
-        int addr = code[ip++];
-        pushAltWithStateCheck(ip + addr, s, sprev, mem);
-    }
-
-    // CEC
-    private void opStateCheckPushOrJump() {
-        int mem = code[ip++];
-        int addr= code[ip++];
-
-        if (stateCheckVal(s, mem)) {
-            ip += addr;
-        } else {
-            pushAltWithStateCheck(ip + addr, s, sprev, mem);
-        }
-    }
-
-    // CEC
-    private void opStateCheck() {
-        int mem = code[ip++];
-        if (stateCheckVal(s, mem)) {opFail(); return;}
-        pushStateCheck(s, mem);
-    }
-
     private void opPop() {
         popOne();
     }
@@ -1425,17 +1180,6 @@
         opFail();
     }
 
-    private void opCall() {
-        int addr = code[ip++];
-        pushCallFrame(ip);
-        ip = addr; // absolute address
-    }
-
-    private void opReturn() {
-        ip = sreturn();
-        pushReturn();
-    }
-
     private void opFail() {
         if (stack == null) {
             ip = regex.codeLength - 1;
@@ -1447,13 +1191,6 @@
         ip    = e.getStatePCode();
         s     = e.getStatePStr();
         sprev = e.getStatePStrPrev();
-
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-            if (e.getStateCheck() != 0) {
-                e.type = STATE_CHECK_MARK;
-                stk++;
-            }
-        }
     }
 
     private int finish() {
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java	Wed Jul 05 18:57:52 2017 +0200
@@ -34,6 +34,239 @@
     int operantCount;
     WarnCallback warnings;
 
+    private final static String OpCodeNames[] = new String[] {
+            "finish", /*OP_FINISH*/
+            "end", /*OP_END*/
+            "exact1", /*OP_EXACT1*/
+            "exact2", /*OP_EXACT2*/
+            "exact3", /*OP_EXACT3*/
+            "exact4", /*OP_EXACT4*/
+            "exact5", /*OP_EXACT5*/
+            "exactn", /*OP_EXACTN*/
+            "exactmb2-n1", /*OP_EXACTMB2N1*/
+            "exactmb2-n2", /*OP_EXACTMB2N2*/
+            "exactmb2-n3", /*OP_EXACTMB2N3*/
+            "exactmb2-n", /*OP_EXACTMB2N*/
+            "exactmb3n", /*OP_EXACTMB3N*/
+            "exactmbn", /*OP_EXACTMBN*/
+            "exact1-ic", /*OP_EXACT1_IC*/
+            "exactn-ic", /*OP_EXACTN_IC*/
+            "cclass", /*OP_CCLASS*/
+            "cclass-mb", /*OP_CCLASS_MB*/
+            "cclass-mix", /*OP_CCLASS_MIX*/
+            "cclass-not", /*OP_CCLASS_NOT*/
+            "cclass-mb-not", /*OP_CCLASS_MB_NOT*/
+            "cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
+            "cclass-node", /*OP_CCLASS_NODE*/
+            "anychar", /*OP_ANYCHAR*/
+            "anychar-ml", /*OP_ANYCHAR_ML*/
+            "anychar*", /*OP_ANYCHAR_STAR*/
+            "anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
+            "anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+            "anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+            "word", /*OP_WORD*/
+            "not-word", /*OP_NOT_WORD*/
+            "word-bound", /*OP_WORD_BOUND*/
+            "not-word-bound", /*OP_NOT_WORD_BOUND*/
+            "word-begin", /*OP_WORD_BEGIN*/
+            "word-end", /*OP_WORD_END*/
+            "begin-buf", /*OP_BEGIN_BUF*/
+            "end-buf", /*OP_END_BUF*/
+            "begin-line", /*OP_BEGIN_LINE*/
+            "end-line", /*OP_END_LINE*/
+            "semi-end-buf", /*OP_SEMI_END_BUF*/
+            "begin-position", /*OP_BEGIN_POSITION*/
+            "backref1", /*OP_BACKREF1*/
+            "backref2", /*OP_BACKREF2*/
+            "backrefn", /*OP_BACKREFN*/
+            "backrefn-ic", /*OP_BACKREFN_IC*/
+            "backref_multi", /*OP_BACKREF_MULTI*/
+            "backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
+            "backref_at_level", /*OP_BACKREF_AT_LEVEL*/
+            "mem-start", /*OP_MEMORY_START*/
+            "mem-start-push", /*OP_MEMORY_START_PUSH*/
+            "mem-end-push", /*OP_MEMORY_END_PUSH*/
+            "mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
+            "mem-end", /*OP_MEMORY_END*/
+            "mem-end-rec", /*OP_MEMORY_END_REC*/
+            "fail", /*OP_FAIL*/
+            "jump", /*OP_JUMP*/
+            "push", /*OP_PUSH*/
+            "pop", /*OP_POP*/
+            "push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
+            "push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
+            "repeat", /*OP_REPEAT*/
+            "repeat-ng", /*OP_REPEAT_NG*/
+            "repeat-inc", /*OP_REPEAT_INC*/
+            "repeat-inc-ng", /*OP_REPEAT_INC_NG*/
+            "repeat-inc-sg", /*OP_REPEAT_INC_SG*/
+            "repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
+            "null-check-start", /*OP_NULL_CHECK_START*/
+            "null-check-end", /*OP_NULL_CHECK_END*/
+            "null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
+            "null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
+            "push-pos", /*OP_PUSH_POS*/
+            "pop-pos", /*OP_POP_POS*/
+            "push-pos-not", /*OP_PUSH_POS_NOT*/
+            "fail-pos", /*OP_FAIL_POS*/
+            "push-stop-bt", /*OP_PUSH_STOP_BT*/
+            "pop-stop-bt", /*OP_POP_STOP_BT*/
+            "look-behind", /*OP_LOOK_BEHIND*/
+            "push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
+            "fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
+            "call", /*OP_CALL*/
+            "return", /*OP_RETURN*/
+            "state-check-push", /*OP_STATE_CHECK_PUSH*/
+            "state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
+            "state-check", /*OP_STATE_CHECK*/
+            "state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
+            "state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+            "set-option-push", /*OP_SET_OPTION_PUSH*/
+            "set-option", /*OP_SET_OPTION*/
+
+            // single byte versions
+            "anychar-sb", /*OP_ANYCHAR*/
+            "anychar-ml-sb", /*OP_ANYCHAR_ML*/
+            "anychar*-sb", /*OP_ANYCHAR_STAR*/
+            "anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
+            "anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+            "anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+            "state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
+            "state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+
+            "cclass-sb", /*OP_CCLASS*/
+            "cclass-not-sb", /*OP_CCLASS_NOT*/
+
+            "word-sb", /*OP_WORD*/
+            "not-word-sb", /*OP_NOT_WORD*/
+            "word-bound-sb", /*OP_WORD_BOUND*/
+            "not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
+            "word-begin-sb", /*OP_WORD_BEGIN*/
+            "word-end-sb", /*OP_WORD_END*/
+
+            "look-behind-sb", /*OP_LOOK_BEHIND*/
+
+            "exact1-ic-sb", /*OP_EXACT1_IC*/
+            "exactn-ic-sb", /*OP_EXACTN_IC*/
+
+    };
+
+    private final static int OpCodeArgTypes[] = new int[] {
+            Arguments.NON, /*OP_FINISH*/
+            Arguments.NON, /*OP_END*/
+            Arguments.SPECIAL, /*OP_EXACT1*/
+            Arguments.SPECIAL, /*OP_EXACT2*/
+            Arguments.SPECIAL, /*OP_EXACT3*/
+            Arguments.SPECIAL, /*OP_EXACT4*/
+            Arguments.SPECIAL, /*OP_EXACT5*/
+            Arguments.SPECIAL, /*OP_EXACTN*/
+            Arguments.SPECIAL, /*OP_EXACTMB2N1*/
+            Arguments.SPECIAL, /*OP_EXACTMB2N2*/
+            Arguments.SPECIAL, /*OP_EXACTMB2N3*/
+            Arguments.SPECIAL, /*OP_EXACTMB2N*/
+            Arguments.SPECIAL, /*OP_EXACTMB3N*/
+            Arguments.SPECIAL, /*OP_EXACTMBN*/
+            Arguments.SPECIAL, /*OP_EXACT1_IC*/
+            Arguments.SPECIAL, /*OP_EXACTN_IC*/
+            Arguments.SPECIAL, /*OP_CCLASS*/
+            Arguments.SPECIAL, /*OP_CCLASS_MB*/
+            Arguments.SPECIAL, /*OP_CCLASS_MIX*/
+            Arguments.SPECIAL, /*OP_CCLASS_NOT*/
+            Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
+            Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
+            Arguments.SPECIAL, /*OP_CCLASS_NODE*/
+            Arguments.NON, /*OP_ANYCHAR*/
+            Arguments.NON, /*OP_ANYCHAR_ML*/
+            Arguments.NON, /*OP_ANYCHAR_STAR*/
+            Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
+            Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+            Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+            Arguments.NON, /*OP_WORD*/
+            Arguments.NON, /*OP_NOT_WORD*/
+            Arguments.NON, /*OP_WORD_BOUND*/
+            Arguments.NON, /*OP_NOT_WORD_BOUND*/
+            Arguments.NON, /*OP_WORD_BEGIN*/
+            Arguments.NON, /*OP_WORD_END*/
+            Arguments.NON, /*OP_BEGIN_BUF*/
+            Arguments.NON, /*OP_END_BUF*/
+            Arguments.NON, /*OP_BEGIN_LINE*/
+            Arguments.NON, /*OP_END_LINE*/
+            Arguments.NON, /*OP_SEMI_END_BUF*/
+            Arguments.NON, /*OP_BEGIN_POSITION*/
+            Arguments.NON, /*OP_BACKREF1*/
+            Arguments.NON, /*OP_BACKREF2*/
+            Arguments.MEMNUM, /*OP_BACKREFN*/
+            Arguments.SPECIAL, /*OP_BACKREFN_IC*/
+            Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
+            Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
+            Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
+            Arguments.MEMNUM, /*OP_MEMORY_START*/
+            Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
+            Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
+            Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
+            Arguments.MEMNUM, /*OP_MEMORY_END*/
+            Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
+            Arguments.NON, /*OP_FAIL*/
+            Arguments.RELADDR, /*OP_JUMP*/
+            Arguments.RELADDR, /*OP_PUSH*/
+            Arguments.NON, /*OP_POP*/
+            Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
+            Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
+            Arguments.SPECIAL, /*OP_REPEAT*/
+            Arguments.SPECIAL, /*OP_REPEAT_NG*/
+            Arguments.MEMNUM, /*OP_REPEAT_INC*/
+            Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
+            Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
+            Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
+            Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
+            Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
+            Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
+            Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
+            Arguments.NON, /*OP_PUSH_POS*/
+            Arguments.NON, /*OP_POP_POS*/
+            Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
+            Arguments.NON, /*OP_FAIL_POS*/
+            Arguments.NON, /*OP_PUSH_STOP_BT*/
+            Arguments.NON, /*OP_POP_STOP_BT*/
+            Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
+            Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
+            Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
+            Arguments.ABSADDR, /*OP_CALL*/
+            Arguments.NON, /*OP_RETURN*/
+            Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
+            Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
+            Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
+            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
+            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+            Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
+            Arguments.OPTION, /*OP_SET_OPTION*/
+
+            // single byte versions
+            Arguments.NON, /*OP_ANYCHAR*/
+            Arguments.NON, /*OP_ANYCHAR_ML*/
+            Arguments.NON, /*OP_ANYCHAR_STAR*/
+            Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
+            Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+            Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
+            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+
+            Arguments.SPECIAL, /*OP_CCLASS*/
+            Arguments.SPECIAL, /*OP_CCLASS_NOT*/
+
+            Arguments.NON, /*OP_WORD*/
+            Arguments.NON, /*OP_NOT_WORD*/
+            Arguments.NON, /*OP_WORD_BOUND*/
+            Arguments.NON, /*OP_NOT_WORD_BOUND*/
+            Arguments.NON, /*OP_WORD_BEGIN*/
+            Arguments.NON, /*OP_WORD_END*/
+
+            Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
+
+            Arguments.SPECIAL, /*OP_EXACT1_IC*/
+            Arguments.SPECIAL, /*OP_EXACTN_IC*/
+    };
+
     public ByteCodePrinter(Regex regex) {
         code = regex.code;
         codeLength = regex.codeLength;
@@ -76,8 +309,8 @@
         CClassNode cc;
         int tm, idx;
 
-        sb.append("[" + OPCode.OpCodeNames[code[bp]]);
-        int argType = OPCode.OpCodeArgTypes[code[bp]];
+        sb.append("[" + OpCodeNames[code[bp]]);
+        int argType = OpCodeArgTypes[code[bp]];
         int ip = bp;
         if (argType != Arguments.SPECIAL) {
             bp++;
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public class CaptureTreeNode {
-
-
-    int group;
-    int beg;
-    int end;
-    // int allocated;
-    int numChildren;
-    CaptureTreeNode[]children;
-
-    CaptureTreeNode() {
-        beg = Region.REGION_NOTPOS;
-        end = Region.REGION_NOTPOS;
-        group = -1;
-    }
-
-    static final int HISTORY_TREE_INIT_ALLOC_SIZE = 8;
-    void addChild(CaptureTreeNode child) {
-        if (children == null) {
-            children = new CaptureTreeNode[HISTORY_TREE_INIT_ALLOC_SIZE];
-        } else if (numChildren >= children.length) {
-            CaptureTreeNode[]tmp = new CaptureTreeNode[children.length << 1];
-            System.arraycopy(children, 0, tmp, 0, children.length);
-            children = tmp;
-        }
-
-        children[numChildren] = child;
-        numChildren++;
-    }
-
-    void clear() {
-        for (int i=0; i<numChildren; i++) {
-            children[i] = null; // ???
-        }
-        numChildren = 0;
-        beg = end = Region.REGION_NOTPOS;
-        group = -1;
-    }
-
-    CaptureTreeNode cloneTree() {
-        CaptureTreeNode clone = new CaptureTreeNode();
-        clone.beg = beg;
-        clone.end = end;
-
-        for (int i=0; i<numChildren; i++) {
-            CaptureTreeNode child = children[i].cloneTree();
-            clone.addChild(child);
-        }
-        return clone;
-    }
-
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,8 +22,6 @@
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -56,7 +54,7 @@
 
     private void compileStringRawNode(StringNode sn) {
         if (sn.length() <= 0) return;
-        addCompileString(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
+        addCompileString(sn.chars, sn.p, sn.length(), false);
     }
 
     private void compileStringNode(StringNode node) {
@@ -76,17 +74,14 @@
             slen++;
             p++;
         }
-        addCompileString(chars, prev, 1, slen, ambig);
+        addCompileString(chars, prev, slen, ambig);
     }
 
-    protected abstract void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase);
+    protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
 
     protected abstract void compileCClassNode(CClassNode node);
-    protected abstract void compileCTypeNode(CTypeNode node);
     protected abstract void compileAnyCharNode();
-    protected abstract void compileCallNode(CallNode node);
     protected abstract void compileBackrefNode(BackRefNode node);
-    protected abstract void compileCECQuantifierNode(QuantifierNode node);
     protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
     protected abstract void compileOptionNode(EncloseNode node);
     protected abstract void compileEncloseNode(EncloseNode node);
@@ -118,10 +113,6 @@
             compileCClassNode((CClassNode)node);
             break;
 
-        case NodeType.CTYPE:
-            compileCTypeNode((CTypeNode)node);
-            break;
-
         case NodeType.CANY:
             compileAnyCharNode();
             break;
@@ -130,19 +121,8 @@
             compileBackrefNode((BackRefNode)node);
             break;
 
-        case NodeType.CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                compileCallNode((CallNode)node);
-                break;
-            } // USE_SUBEXP_CALL
-            break;
-
         case NodeType.QTFR:
-            if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                compileCECQuantifierNode((QuantifierNode)node);
-            } else {
-                compileNonCECQuantifierNode((QuantifierNode)node);
-            }
+            compileNonCECQuantifierNode((QuantifierNode)node);
             break;
 
         case NodeType.ENCLOSE:
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java	Wed Jul 05 18:57:52 2017 +0200
@@ -31,10 +31,6 @@
     final int ENC_CASE_FOLD_DEFAULT = ENC_CASE_FOLD_MIN;
     final boolean USE_CRNL_AS_LINE_TERMINATOR = false;
 
-    final boolean USE_NAMED_GROUP = true;
-    final boolean USE_SUBEXP_CALL = true;
-    final boolean USE_BACKREF_WITH_LEVEL = true;                            /* \k<name+n>, \k<name-n> */
-
     final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */
     final boolean USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE = true;     /* /\n$/ =~ "\n" */
     final boolean USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR = false;
@@ -42,12 +38,10 @@
     final boolean CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS = true;
 
     final boolean USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE = false;
-    final boolean USE_CAPTURE_HISTORY = false;
     final boolean USE_VARIABLE_META_CHARS = true;
     final boolean USE_WORD_BEGIN_END = true;                                /* "\<": word-begin, "\>": word-end */
-    final boolean USE_POSIX_API_REGION_OPTION = true;                           /* needed for POSIX API support */
+    final boolean USE_POSIX_API_REGION_OPTION = false;                           /* needed for POSIX API support */
     final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true;
-    final boolean USE_COMBINATION_EXPLOSION_CHECK = false;
 
     final int NREGION                   = 10;
     final int MAX_BACKREF_NUM           = 1000;
@@ -73,13 +67,6 @@
 
     final boolean USE_STRING_TEMPLATES              = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
 
-
-    final int MAX_CAPTURE_HISTORY_GROUP             = 31;
-
-
-    final int CHECK_STRING_THRESHOLD_LEN            = 7;
-    final int CHECK_BUFF_MAX_SIZE                   = 0x4000;
-
     final boolean NON_UNICODE_SDW                   = true;
 
 
@@ -95,6 +82,4 @@
     final boolean DEBUG_COMPILE_BYTE_CODE_INFO      = DEBUG_ALL;
     final boolean DEBUG_SEARCH                      = DEBUG_ALL;
     final boolean DEBUG_MATCH                       = DEBUG_ALL;
-    final boolean DEBUG_ASM                         = true;
-    final boolean DEBUG_ASM_EXEC                    = true;
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java	Wed Jul 05 18:57:52 2017 +0200
@@ -95,20 +95,6 @@
        return s;
     }
 
-    /* onigenc_with_ascii_strncmp */
-    public static int strNCmp(char[] chars1, int p1, int end, char[] chars2, int p2, int n) {
-        while (n-- > 0) {
-            if (p1 >= end) return chars2[p2];
-            int c = chars1[p1];
-            int x = chars2[p2] - c;
-            if (x != 0) return x;
-
-            p2++;
-            p1++;
-        }
-        return 0;
-    }
-
     public static int mbcToCode(byte[] bytes, int p, int end) {
         int code = 0;
         for (int i = p; i < end; i++) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java	Wed Jul 05 18:57:52 2017 +0200
@@ -27,10 +27,7 @@
 import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.TokenType;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
 
 class Lexer extends ScannerSupport {
     protected final ScanEnvironment env;
@@ -215,198 +212,6 @@
         \k<-num+n>, \k<-num-n>
      */
 
-    // value implicit (rnameEnd)
-    private boolean fetchNameWithLevel(int startCode, Ptr rbackNum, Ptr rlevel) {
-        int src = p;
-        boolean existLevel = false;
-        int isNum = 0;
-        int sign = 1;
-
-        int endCode = nameEndCodePoint(startCode);
-        int pnumHead = p;
-        int nameEnd = stop;
-
-        String err = null;
-        if (!left()) {
-            newValueException(ERR_EMPTY_GROUP_NAME);
-        } else {
-            fetch();
-            if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
-            if (Character.isDigit(c)) {
-                isNum = 1;
-            } else if (c == '-') {
-                isNum = 2;
-                sign = -1;
-                pnumHead = p;
-            } else if (!EncodingHelper.isWord(c)) {
-                err = ERR_INVALID_GROUP_NAME;
-            }
-        }
-
-        while (left()) {
-            nameEnd = p;
-            fetch();
-            if (c == endCode || c == ')' || c == '+' || c == '-') {
-                if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
-                break;
-            }
-
-            if (isNum != 0) {
-                if (EncodingHelper.isDigit(c)) {
-                    isNum = 1;
-                } else {
-                    err = ERR_INVALID_GROUP_NAME;
-                    // isNum = 0;
-                }
-            } else if (!EncodingHelper.isWord(c)) {
-                err = ERR_INVALID_CHAR_IN_GROUP_NAME;
-            }
-        }
-
-        boolean isEndCode = false;
-        if (err == null && c != endCode) {
-            if (c == '+' || c == '-') {
-                int flag = c == '-' ? -1 : 1;
-
-                fetch();
-                if (!EncodingHelper.isDigit(c)) newValueException(ERR_INVALID_GROUP_NAME, src, stop);
-                unfetch();
-                int level = scanUnsignedNumber();
-                if (level < 0) newValueException(ERR_TOO_BIG_NUMBER);
-                rlevel.p = level * flag;
-                existLevel = true;
-
-                fetch();
-                isEndCode = c == endCode;
-            }
-
-            if (!isEndCode) {
-                err = ERR_INVALID_GROUP_NAME;
-                nameEnd = stop;
-            }
-        }
-
-        if (err == null) {
-            if (isNum != 0) {
-                mark();
-                p = pnumHead;
-                int backNum = scanUnsignedNumber();
-                restore();
-                if (backNum < 0) {
-                    newValueException(ERR_TOO_BIG_NUMBER);
-                } else if (backNum == 0) {
-                    newValueException(ERR_INVALID_GROUP_NAME, src, stop);
-                }
-                rbackNum.p = backNum * sign;
-            }
-            value = nameEnd;
-            return existLevel;
-        } else {
-            newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
-            return false; // not reached
-        }
-    }
-
-    // USE_NAMED_GROUP
-    // ref: 0 -> define name    (don't allow number name)
-    //      1 -> reference name (allow number name)
-    private int fetchNameForNamedGroup(int startCode, boolean ref) {
-        int src = p;
-        value = 0;
-
-        int isNum = 0;
-        int sign = 1;
-
-        int endCode = nameEndCodePoint(startCode);
-        int pnumHead = p;
-        int nameEnd = stop;
-
-        String err = null;
-        if (!left()) {
-            newValueException(ERR_EMPTY_GROUP_NAME);
-        } else {
-            fetch();
-            if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
-            if (EncodingHelper.isDigit(c)) {
-                if (ref) {
-                    isNum = 1;
-                } else {
-                    err = ERR_INVALID_GROUP_NAME;
-                    // isNum = 0;
-                }
-            } else if (c == '-') {
-                if (ref) {
-                    isNum = 2;
-                    sign = -1;
-                    pnumHead = p;
-                } else {
-                    err = ERR_INVALID_GROUP_NAME;
-                    // isNum = 0;
-                }
-            } else if (!EncodingHelper.isWord(c)) {
-                err = ERR_INVALID_CHAR_IN_GROUP_NAME;
-            }
-        }
-
-        if (err == null) {
-            while (left()) {
-                nameEnd = p;
-                fetch();
-                if (c == endCode || c == ')') {
-                    if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
-                    break;
-                }
-
-                if (isNum != 0) {
-                    if (EncodingHelper.isDigit(c)) {
-                        isNum = 1;
-                    } else {
-                        if (!EncodingHelper.isWord(c)) {
-                            err = ERR_INVALID_CHAR_IN_GROUP_NAME;
-                        } else {
-                            err = ERR_INVALID_GROUP_NAME;
-                        }
-                        // isNum = 0;
-                    }
-                } else {
-                    if (!EncodingHelper.isWord(c)) {
-                        err = ERR_INVALID_CHAR_IN_GROUP_NAME;
-                    }
-                }
-            }
-
-            if (c != endCode) {
-                err = ERR_INVALID_GROUP_NAME;
-                nameEnd = stop;
-            }
-
-            int backNum = 0;
-            if (isNum != 0) {
-                mark();
-                p = pnumHead;
-                backNum = scanUnsignedNumber();
-                restore();
-                if (backNum < 0) {
-                    newValueException(ERR_TOO_BIG_NUMBER);
-                } else if (backNum == 0) {
-                    newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
-                }
-                backNum *= sign;
-            }
-            value = nameEnd;
-            return backNum;
-        } else {
-            while (left()) {
-                nameEnd = p;
-                fetch();
-                if (c == endCode || c == ')') break;
-            }
-            if (!left()) nameEnd = stop;
-            newValueException(err, src, nameEnd);
-            return 0; // not reached
-        }
-    }
-
     // #else USE_NAMED_GROUP
     // make it return nameEnd!
     private final int fetchNameForNoNamedGroup(int startCode, boolean ref) {
@@ -472,11 +277,7 @@
     }
 
     protected final int fetchName(int startCode, boolean ref) {
-        if (Config.USE_NAMED_GROUP) {
-            return fetchNameForNamedGroup(startCode, ref);
-        } else {
-            return fetchNameForNoNamedGroup(startCode, ref);
-        }
+        return fetchNameForNoNamedGroup(startCode, ref);
     }
 
     private boolean strExistCheckWithEsc(int[]s, int n, int bad) {
@@ -519,26 +320,6 @@
         token.setPropNot(flag);
     }
 
-    private void fetchTokenInCCFor_p() {
-        int c2 = peek(); // !!! migrate to peekIs
-        if (c2 == '{' && syntax.op2EscPBraceCharProperty()) {
-            inc();
-            token.type = TokenType.CHAR_PROPERTY;
-            token.setPropNot(c == 'P');
-
-            if (syntax.op2EscPBraceCircumflexNot()) {
-                c2 = fetchTo();
-                if (c2 == '^') {
-                    token.setPropNot(!token.getPropNot());
-                } else {
-                    unfetch();
-                }
-            }
-        } else {
-            syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
-        }
-    }
-
     private void fetchTokenInCCFor_x() {
         if (!left()) return;
         int last = p;
@@ -604,30 +385,6 @@
         }
     }
 
-    private void fetchTokenInCCFor_posixBracket() {
-        if (syntax.opPosixBracket() && peekIs(':')) {
-            token.backP = p; /* point at '[' is readed */
-            inc();
-            if (strExistCheckWithEsc(send, send.length, ']')) {
-                token.type = TokenType.POSIX_BRACKET_OPEN;
-            } else {
-                unfetch();
-                // remove duplication, goto cc_in_cc;
-                if (syntax.op2CClassSetOp()) {
-                    token.type = TokenType.CC_CC_OPEN;
-                } else {
-                    env.ccEscWarn("[");
-                }
-            }
-        } else { // cc_in_cc:
-            if (syntax.op2CClassSetOp()) {
-                token.type = TokenType.CC_CC_OPEN;
-            } else {
-                env.ccEscWarn("[");
-            }
-        }
-    }
-
     private void fetchTokenInCCFor_and() {
         if (syntax.op2CClassSetOp() && left() && peekIs('&')) {
             inc();
@@ -683,10 +440,6 @@
             case 'H':
                 if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
                 break;
-            case 'p':
-            case 'P':
-                fetchTokenInCCFor_p();
-                break;
             case 'x':
                 fetchTokenInCCFor_x();
                 break;
@@ -714,18 +467,12 @@
                 break;
             } // switch
 
-        } else if (c == '[') {
-            fetchTokenInCCFor_posixBracket();
         } else if (c == '&') {
             fetchTokenInCCFor_and();
         }
         return token.type;
     }
 
-    protected final int backrefRelToAbs(int relNo) {
-        return env.numMem + 1 + relNo;
-    }
-
     private void fetchTokenFor_repeat(int lower, int upper) {
         token.type = TokenType.OP_REPEAT;
         token.setRepeatLower(lower);
@@ -815,7 +562,6 @@
             token.setBackrefNum(1);
             token.setBackrefRef1(num);
             token.setBackrefByName(false);
-            if (Config.USE_BACKREF_WITH_LEVEL) token.setBackrefExistLevel(false);
             return;
         }
 
@@ -845,76 +591,6 @@
         }
     }
 
-    private void fetchTokenFor_namedBackref() {
-        if (syntax.op2EscKNamedBackref()) {
-            if (left()) {
-                fetch();
-                if (c =='<' || c == '\'') {
-                    int last = p;
-                    int backNum;
-                    if (Config.USE_BACKREF_WITH_LEVEL) {
-                        Ptr rbackNum = new Ptr();
-                        Ptr rlevel = new Ptr();
-                        token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
-                        token.setBackrefLevel(rlevel.p);
-                        backNum = rbackNum.p;
-                    } else {
-                        backNum = fetchName(c, true);
-                    } // USE_BACKREF_AT_LEVEL
-                    int nameEnd = value; // set by fetchNameWithLevel/fetchName
-
-                    if (backNum != 0) {
-                        if (backNum < 0) {
-                            backNum = backrefRelToAbs(backNum);
-                            if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
-                        }
-
-                        if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
-                            newValueException(ERR_INVALID_BACKREF);
-                        }
-                        token.type = TokenType.BACKREF;
-                        token.setBackrefByName(false);
-                        token.setBackrefNum(1);
-                        token.setBackrefRef1(backNum);
-                    } else {
-                        NameEntry e = env.reg.nameToGroupNumbers(chars, last, nameEnd);
-                        if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
-
-                        if (syntax.strictCheckBackref()) {
-                            if (e.backNum == 1) {
-                                if (e.backRef1 > env.numMem ||
-                                    env.memNodes == null ||
-                                    env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
-                            } else {
-                                for (int i=0; i<e.backNum; i++) {
-                                    if (e.backRefs[i] > env.numMem ||
-                                        env.memNodes == null ||
-                                        env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
-                                }
-                            }
-                        }
-
-                        token.type = TokenType.BACKREF;
-                        token.setBackrefByName(true);
-
-                        if (e.backNum == 1) {
-                            token.setBackrefNum(1);
-                            token.setBackrefRef1(e.backRef1);
-                        } else {
-                            token.setBackrefNum(e.backNum);
-                            token.setBackrefRefs(e.backRefs);
-                        }
-                    }
-                } else {
-                    unfetch();
-                    syntaxWarn(Warnings.INVALID_BACKREFERENCE);
-                }
-            } else {
-                syntaxWarn(Warnings.INVALID_BACKREFERENCE);
-            }
-        }
-    }
-
     private void fetchTokenFor_subexpCall() {
         if (syntax.op2EscGSubexpCall()) {
             if (left()) {
@@ -937,25 +613,6 @@
         }
     }
 
-    private void fetchTokenFor_charProperty() {
-        if (peekIs('{') && syntax.op2EscPBraceCharProperty()) {
-            inc();
-            token.type = TokenType.CHAR_PROPERTY;
-            token.setPropNot(c == 'P');
-
-            if (syntax.op2EscPBraceCircumflexNot()) {
-                fetch();
-                if (c == '^') {
-                    token.setPropNot(!token.getPropNot());
-                } else {
-                    unfetch();
-                }
-            }
-        } else {
-            syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
-        }
-    }
-
     private void fetchTokenFor_metaChars() {
         if (c == syntax.metaCharTable.anyChar) {
             token.type = TokenType.ANYCHAR;
@@ -1091,19 +748,6 @@
                 case '0':
                     fetchTokenFor_zero();
                     break;
-                case 'k':
-                    if (Config.USE_NAMED_GROUP) fetchTokenFor_namedBackref();
-                    break;
-                case 'g':
-                    if (Config.USE_SUBEXP_CALL) fetchTokenFor_subexpCall();
-                    break;
-                case 'Q':
-                    if (syntax.op2EscCapitalQQuote()) token.type = TokenType.QUOTE_OPEN;
-                    break;
-                case 'p':
-                case 'P':
-                    fetchTokenFor_charProperty();
-                    break;
 
                 default:
                     unfetch();
@@ -1244,24 +888,6 @@
         }
     }
 
-    protected final int fetchCharPropertyToCType() {
-        mark();
-
-        while (left()) {
-            int last = p;
-            fetch();
-            if (c == '}') {
-                String name = new String(chars, _p, last - _p);
-                return PosixBracket.propertyNameToCType(name);
-            } else if (c == '(' || c == ')' || c == '{' || c == '|') {
-                String name = new String(chars, _p, last - _p);
-                throw new JOniException(ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
-            }
-        }
-        newInternalException(ERR_PARSER_BUG);
-        return 0; // not reached
-    }
-
     protected final void syntaxWarn(String message, char c) {
         syntaxWarn(message.replace("<%n>", Character.toString(c)));
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java	Wed Jul 05 18:57:52 2017 +0200
@@ -58,17 +58,10 @@
     // main matching method
     protected abstract int matchAt(int range, int sstart, int sprev);
 
-    protected abstract void stateCheckBuffInit(int strLength, int offset, int stateNum);
-    protected abstract void stateCheckBuffClear();
-
     public final Region getRegion() {
         return msaRegion;
     }
 
-    public final Region getEagerRegion() {
-        return msaRegion != null ? msaRegion : new Region(msaBegin, msaEnd);
-    }
-
     public final int getBegin() {
         return msaBegin;
     }
@@ -86,11 +79,6 @@
     public final int match(int at, int range, int option) {
         msaInit(option, at);
 
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-            int offset = at = str;
-            stateCheckBuffInit(end - str, offset, regex.numCombExpCheck); // move it to construction?
-        } // USE_COMBINATION_EXPLOSION_CHECK
-
         int prev = EncodingHelper.prevCharHead(str, at);
 
         if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
@@ -377,8 +365,6 @@
                 prev = -1;
                 msaInit(option, start);
 
-                if (Config.USE_COMBINATION_EXPLOSION_CHECK) stateCheckBuffClear();
-
                 if (matchCheck(end, s, prev)) return match(s);
                 return mismatch();
             }
@@ -393,10 +379,6 @@
         }
 
         msaInit(option, origStart);
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-            int offset = Math.min(start, range) - str;
-            stateCheckBuffInit(end - str, offset, regex.numCombExpCheck);
-        }
 
         s = start;
         if (range > start) {    /* forward search */
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public final class NameEntry {
-    static final int INIT_NAME_BACKREFS_ALLOC_NUM = 8;
-
-    public final char[] name;
-    public final int nameP;
-    public final int nameEnd;
-
-    int backNum;
-    int backRef1;
-    int backRefs[];
-
-    public NameEntry(char[] chars, int p, int end) {
-        name = chars;
-        nameP = p;
-        nameEnd = end;
-    }
-
-    public int[] getBackRefs() {
-        switch (backNum) {
-        case 0:
-            return new int[]{};
-        case 1:
-            return new int[]{backRef1};
-        default:
-            int[]result = new int[backNum];
-            System.arraycopy(backRefs, 0, result, 0, backNum);
-            return result;
-        }
-    }
-
-    private void alloc() {
-        backRefs = new int[INIT_NAME_BACKREFS_ALLOC_NUM];
-    }
-
-    private void ensureSize() {
-        if (backNum > backRefs.length) {
-            int[]tmp = new int[backRefs.length << 1];
-            System.arraycopy(backRefs, 0, tmp, 0, backRefs.length);
-            backRefs = tmp;
-        }
-    }
-
-    public void addBackref(int backRef) {
-        backNum++;
-
-        switch (backNum) {
-            case 1:
-                backRef1 = backRef;
-                break;
-            case 2:
-                alloc();
-                backRefs[0] = backRef1;
-                backRefs[1] = backRef;
-                break;
-            default:
-                ensureSize();
-                backRefs[backNum - 1] = backRef;
-        }
-    }
-
-    public String toString() {
-        StringBuilder buff = new StringBuilder(new String(name, nameP, nameEnd - nameP) + " ");
-        if (backNum == 0) {
-            buff.append("-");
-        } else if (backNum == 1){
-            buff.append(backRef1);
-        } else {
-            for (int i=0; i<backNum; i++){
-                if (i > 0) buff.append(", ");
-                buff.append(backRefs[i]);
-            }
-        }
-        return buff.toString();
-    }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public abstract class NativeMachine extends Matcher {
-
-    protected NativeMachine(Regex regex, char[] chars, int p, int end) {
-        super(regex, chars, p, end);
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java	Wed Jul 05 18:57:52 2017 +0200
@@ -19,20 +19,15 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni;
 
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
 
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -66,65 +61,6 @@
         return root;
     }
 
-    private static final int POSIX_BRACKET_NAME_MIN_LEN            = 4;
-    private static final int POSIX_BRACKET_CHECK_LIMIT_LENGTH      = 20;
-    private static final char BRACKET_END[]                        = ":]".toCharArray();
-    private boolean parsePosixBracket(CClassNode cc) {
-        mark();
-
-        boolean not;
-        if (peekIs('^')) {
-            inc();
-            not = true;
-        } else {
-            not = false;
-        }
-        if (stop - p >= POSIX_BRACKET_NAME_MIN_LEN + 3) { // else goto not_posix_bracket
-            char[][] pbs = PosixBracket.PBSNamesLower;
-            for (int i=0; i<pbs.length; i++) {
-                char[] name = pbs[i];
-                // hash lookup here ?
-                if (EncodingHelper.strNCmp(chars, p, stop, name, 0, name.length) == 0) {
-                    p += name.length;
-                    if (EncodingHelper.strNCmp(chars, p, stop, BRACKET_END, 0, BRACKET_END.length) != 0) {
-                        newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
-                    }
-                    cc.addCType(PosixBracket.PBSValues[i], not, env, this);
-                    inc();
-                    inc();
-                    return false;
-                }
-            }
-
-        }
-
-        // not_posix_bracket:
-        c = 0;
-        int i= 0;
-        while (left() && ((c=peek()) != ':') && c != ']') {
-            inc();
-            if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
-        }
-
-        if (c == ':' && left()) {
-            inc();
-            if (left()) {
-                fetch();
-                if (c == ']') newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
-            }
-        }
-        restore();
-        return true; /* 1: is not POSIX bracket, but no error. */
-    }
-
-    private CClassNode parseCharProperty() {
-        int ctype = fetchCharPropertyToCType();
-        CClassNode n = new CClassNode();
-        n.addCType(ctype, false, env, this);
-        if (token.getPropNot()) n.setNot();
-        return n;
-    }
-
     private boolean codeExistCheck(int code, boolean ignoreEscaped) {
         mark();
 
@@ -225,29 +161,11 @@
                 parseCharClassValEntry(cc, arg); // val_entry:, val_entry2
                 break;
 
-            case POSIX_BRACKET_OPEN:
-                if (parsePosixBracket(cc)) { /* true: is not POSIX bracket */
-                    env.ccEscWarn("[");
-                    p = token.backP;
-                    arg.v = token.getC();
-                    arg.vIsRaw = false;
-                    parseCharClassValEntry(cc, arg); // goto val_entry
-                    break;
-                }
-                cc.nextStateClass(arg, env); // goto next_class
-                break;
-
             case CHAR_TYPE:
                 cc.addCType(token.getPropCType(), token.getPropNot(), env, this);
                 cc.nextStateClass(arg, env); // next_class:
                 break;
 
-            case CHAR_PROPERTY:
-                int ctype = fetchCharPropertyToCType();
-                cc.addCType(ctype, token.getPropNot(), env, this);
-                cc.nextStateClass(arg, env); // goto next_class
-                break;
-
             case CC_RANGE:
                 if (arg.state == CCSTATE.VALUE) {
                     fetchTokenInCC();
@@ -413,15 +331,6 @@
                 node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
                 break;
             case '\'':
-                if (Config.USE_NAMED_GROUP) {
-                    if (syntax.op2QMarkLtNamedGroup()) {
-                        listCapture = false; // goto named_group1
-                        node = parseEncloseNamedGroup2(listCapture);
-                        break;
-                    } else {
-                        newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
-                    }
-                } // USE_NAMED_GROUP
                 break;
             case '<':  /* look behind (?<=...), (?<!...) */
                 fetch();
@@ -430,36 +339,12 @@
                 } else if (c == '!') {
                     node = new AnchorNode(AnchorType.LOOK_BEHIND_NOT);
                 } else {
-                    if (Config.USE_NAMED_GROUP) {
-                        if (syntax.op2QMarkLtNamedGroup()) {
-                            unfetch();
-                            c = '<';
-
-                            listCapture = false; // named_group1:
-                            node = parseEncloseNamedGroup2(listCapture); // named_group2:
-                            break;
-                        } else {
-                            newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
-                        }
-
-                    } else { // USE_NAMED_GROUP
-                        newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
-                    } // USE_NAMED_GROUP
+                    newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
                 }
                 break;
             case '@':
                 if (syntax.op2AtMarkCaptureHistory()) {
-                    if (Config.USE_NAMED_GROUP) {
-                        if (syntax.op2QMarkLtNamedGroup()) {
-                            fetch();
-                            if (c == '<' || c == '\'') {
-                                listCapture = true;
-                                node = parseEncloseNamedGroup2(listCapture); // goto named_group2 /* (?@<name>...) */
-                            }
-                            unfetch();
-                        }
-                    } // USE_NAMED_GROUP
-                    EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
+                    EncloseNode en = new EncloseNode(); // node_new_enclose_memory
                     int num = env.addMemEntry();
                     if (num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
                     en.regNum = num;
@@ -546,7 +431,7 @@
                 returnCode = 1; /* group */
                 return node;
             }
-            EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
+            EncloseNode en = new EncloseNode(); // node_new_enclose_memory
             int num = env.addMemEntry();
             en.regNum = num;
             node = en;
@@ -570,48 +455,6 @@
         return node; // ??
     }
 
-    private Node parseEncloseNamedGroup2(boolean listCapture) {
-        int nm = p;
-        int num = fetchName(c, false);
-        int nameEnd = value;
-        num = env.addMemEntry();
-        if (listCapture && num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
-
-        regex.nameAdd(chars, nm, nameEnd, num, syntax);
-        EncloseNode en = new EncloseNode(env.option, true); // node_new_enclose_memory
-        en.regNum = num;
-
-        Node node = en;
-
-        if (listCapture) env.captureHistory = bsOnAtSimple(env.captureHistory, num);
-        env.numNamed++;
-        return node;
-    }
-
-    private int findStrPosition(int[]s, int n, int from, int to, Ptr nextChar) {
-        int x;
-        int q;
-        int p = from;
-        int i = 0;
-        while (p < to) {
-            x = chars[p];
-            q = p + 1;
-            if (x == s[0]) {
-                for (i=1; i<n && q<to; i++) {
-                    x = chars[q];
-                    if (x != s[i]) break;
-                    q++;
-                }
-                if (i >= n) {
-                    if (chars[nextChar.p] != 0) nextChar.p = q; // we may need zero term semantics...
-                    return p;
-                }
-            }
-            p = q;
-        }
-        return -1;
-    }
-
     private Node parseExp(TokenType term) {
         if (token.type == term) return StringNode.EMPTY; // goto end_of_token
 
@@ -656,16 +499,6 @@
             node = new StringNode(buf, 0, 1);
             break;
 
-        case QUOTE_OPEN:
-            int[] endOp = new int[] {syntax.metaCharTable.esc, 'E'};
-            int qstart = p;
-            Ptr nextChar = new Ptr();
-            int qend = findStrPosition(endOp, endOp.length, qstart, stop, nextChar);
-            if (qend == -1) nextChar.p = qend = stop;
-            node = new StringNode(chars, qstart, qend);
-            p = nextChar.p;
-            break;
-
         case CHAR_TYPE:
             switch(token.getPropCType()) {
             case CharacterType.D:
@@ -679,10 +512,6 @@
                 }
                 break;
 
-            case CharacterType.WORD:
-                node = new CTypeNode(token.getPropCType(), token.getPropNot());
-                break;
-
             case CharacterType.SPACE:
             case CharacterType.DIGIT:
             case CharacterType.XDIGIT:
@@ -699,10 +528,6 @@
             } // inner switch
             break;
 
-        case CHAR_PROPERTY:
-            node = parseCharProperty();
-            break;
-
         case CC_CC_OPEN:
             CClassNode cc = parseCharClass();
             node = cc;
@@ -735,20 +560,6 @@
                             token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
                             token.getBackrefLevel(),      // ...
                             env);
-
-            break;
-
-        case CALL:
-            if (Config.USE_SUBEXP_CALL) {
-                int gNum = token.getCallGNum();
-
-                if (gNum < 0) {
-                    gNum = backrefRelToAbs(gNum);
-                    if (gNum <= 0) newValueException(ERR_INVALID_BACKREF);
-                }
-                node = new CallNode(chars, token.getCallNameP(), token.getCallNameEnd(), gNum);
-                env.numCall++;
-            } // USE_SUBEXP_CALL
             break;
 
         case ANCHOR:
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java	Wed Jul 05 18:57:52 2017 +0200
@@ -23,9 +23,11 @@
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
 
+import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Iterator;
 
+import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
@@ -44,7 +46,6 @@
     int numMem;             /* used memory(...) num counted from 1 */
     int numRepeat;          /* OP_REPEAT/OP_REPEAT_NG id-counter */
     int numNullCheck;       /* OP_NULL_CHECK_START/END id counter */
-    int numCombExpCheck;    /* combination explosion check */
     int numCall;            /* number of subexp call */
     int captureHistory;     /* (?@...) flag (1-31) */
     int btMemStart;         /* need backtrack flag */
@@ -57,7 +58,7 @@
 
     WarnCallback warnings;
     MatcherFactory factory;
-    private Analyser analyser;
+    protected Analyser analyser;
 
     int options;
     int userOptions;
@@ -65,8 +66,6 @@
     //final Syntax syntax;
     final int caseFoldFlag;
 
-    HashMap<String,NameEntry> nameTable;        // named entries
-
     /* optimization info (string search, char-map and anchors) */
     SearchAlgorithm searchAlgorithm;        /* optimize flag */
     int thresholdLength;                    /* search str-length for apply optimize */
@@ -172,112 +171,6 @@
         return numMem;
     }
 
-    public int numberOfCaptureHistories() {
-        if (Config.USE_CAPTURE_HISTORY) {
-            int n = 0;
-            for (int i=0; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
-                if (bsAt(captureHistory, i)) n++;
-            }
-            return n;
-        } else {
-            return 0;
-        }
-    }
-
-    String nameTableToString() {
-        StringBuilder sb = new StringBuilder();
-
-        if (nameTable != null) {
-            sb.append("name table\n");
-            for (NameEntry ne : nameTable.values()) {
-                sb.append("  " + ne + "\n");
-            }
-            sb.append("\n");
-        }
-        return sb.toString();
-    }
-
-    NameEntry nameFind(char[] name, int nameP, int nameEnd) {
-        if (nameTable != null) return nameTable.get(new String(name, nameP, nameEnd - nameP));
-        return null;
-    }
-
-    void renumberNameTable(int[]map) {
-        if (nameTable != null) {
-            for (NameEntry e : nameTable.values()) {
-                if (e.backNum > 1) {
-                    for (int i=0; i<e.backNum; i++) {
-                        e.backRefs[i] = map[e.backRefs[i]];
-                    }
-                } else if (e.backNum == 1) {
-                    e.backRef1 = map[e.backRef1];
-                }
-            }
-        }
-    }
-
-    public int numberOfNames() {
-        return nameTable == null ? 0 : nameTable.size();
-    }
-
-    void nameAdd(char[] name, int nameP, int nameEnd, int backRef, Syntax syntax) {
-        if (nameEnd - nameP <= 0) throw new ValueException(ErrorMessages.ERR_EMPTY_GROUP_NAME);
-
-        NameEntry e = null;
-        if (nameTable == null) {
-            nameTable = new HashMap<String,NameEntry>(); // 13, oni defaults to 5
-        } else {
-            e = nameFind(name, nameP, nameEnd);
-        }
-
-        if (e == null) {
-            // dup the name here as oni does ?, what for ? (it has to manage it, we don't)
-            e = new NameEntry(name, nameP, nameEnd);
-            nameTable.put(new String(name, nameP, nameEnd - nameP), e);
-        } else if (e.backNum >= 1 && !syntax.allowMultiplexDefinitionName()) {
-            throw new ValueException(ErrorMessages.ERR_MULTIPLEX_DEFINED_NAME, new String(name, nameP, nameEnd - nameP));
-        }
-
-        e.addBackref(backRef);
-    }
-
-    NameEntry nameToGroupNumbers(char[] name, int nameP, int nameEnd) {
-        return nameFind(name, nameP, nameEnd);
-    }
-
-    public int nameToBackrefNumber(char[] name, int nameP, int nameEnd, Region region) {
-        NameEntry e = nameToGroupNumbers(name, nameP, nameEnd);
-        if (e == null) throw new ValueException(ErrorMessages.ERR_UNDEFINED_NAME_REFERENCE,
-                                                new String(name, nameP, nameEnd - nameP));
-
-        switch(e.backNum) {
-        case 0:
-            throw new InternalException(ErrorMessages.ERR_PARSER_BUG);
-        case 1:
-            return e.backRef1;
-        default:
-            if (region != null) {
-                for (int i = e.backNum - 1; i >= 0; i--) {
-                    if (region.beg[e.backRefs[i]] != Region.REGION_NOTPOS) return e.backRefs[i];
-                }
-            }
-            return e.backRefs[e.backNum - 1];
-        }
-    }
-
-    public Iterator<NameEntry> namedBackrefIterator() {
-        return nameTable.values().iterator();
-    }
-
-    public boolean noNameGroupIsActive(Syntax syntax) {
-        if (isDontCaptureGroup(options)) return false;
-
-        if (Config.USE_NAMED_GROUP) {
-            if (numberOfNames() > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(options)) return false;
-        }
-        return true;
-    }
-
     /* set skip map for Boyer-Moor search */
     void setupBMSkipMap() {
         char[] chars = exact;
@@ -353,16 +246,6 @@
         exactP = exactEnd = 0;
     }
 
-    public String encStringToString(byte[]bytes, int p, int end) {
-        StringBuilder sb = new StringBuilder("\nPATTERN: /");
-
-        while (p < end) {
-            sb.append(new String(new byte[]{bytes[p]}));
-            p++;
-        }
-        return sb.append("/").toString();
-    }
-
     public String optimizeInfoToString() {
         String s = "";
         s += "optimize: " + searchAlgorithm.getName() + "\n";
@@ -410,19 +293,13 @@
         return options;
     }
 
-    public void setUserOptions(int options) {
-        this.userOptions = options;
-    }
-
-    public int getUserOptions() {
-        return userOptions;
+    public String dumpTree() {
+        return analyser == null ? null : analyser.root.toString();
     }
 
-    public void setUserObject(Object object) {
-        this.userObject = object;
+    public String dumpByteCode() {
+        compile();
+        return new ByteCodePrinter(this).byteCodeListToString();
     }
 
-    public Object getUserObject() {
-        return userObject;
-    }
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,7 +25,6 @@
     public final int numRegs;
     public final int[]beg;
     public final int[]end;
-    public CaptureTreeNode historyRoot;
 
     public Region(int num) {
         this.numRegs = num;
@@ -33,20 +32,6 @@
         this.end = new int[num];
     }
 
-    public Region(int begin, int end) {
-        this.numRegs = 1;
-        this.beg = new int[]{begin};
-        this.end = new int[]{end};
-    }
-
-    public Region clone() {
-        Region region = new Region(numRegs);
-        System.arraycopy(beg, 0, region.beg, 0, beg.length);
-        System.arraycopy(end, 0, region.end, 0, end.length);
-        if (historyRoot != null) region.historyRoot = historyRoot.cloneTree();
-        return region;
-    }
-
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("Region: \n");
@@ -54,10 +39,6 @@
         return sb.toString();
     }
 
-    CaptureTreeNode getCaptureTree() {
-        return historyRoot;
-    }
-
     void clear() {
         for (int i=0; i<beg.length; i++) {
             beg[i] = end[i] = REGION_NOTPOS;
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,16 +40,10 @@
     final public Regex reg;
 
     int numCall;
-    UnsetAddrList unsetAddrList; // USE_SUBEXP_CALL
     public int numMem;
 
-    int numNamed; // USE_NAMED_GROUP
-
     public Node memNodes[];
 
-    // USE_COMBINATION_EXPLOSION_CHECK
-    int numCombExpCheck;
-    int combExpMaxRegNum;
     int currMaxRegNum;
     boolean hasRecursion;
 
@@ -69,12 +63,8 @@
         numCall = 0;
         numMem = 0;
 
-        numNamed = 0;
-
         memNodes = null;
 
-        numCombExpCheck = 0;
-        combExpMaxRegNum = 0;
         currMaxRegNum = 0;
         hasRecursion = false;
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java	Wed Jul 05 18:57:52 2017 +0200
@@ -37,6 +37,8 @@
     private final int end;              // pattern end position for reset() support
     protected int _p;                   // used by mark()/restore() to mark positions
 
+    private final static int INT_SIGN_BIT = 1 << 31;
+
     protected ScannerSupport(char[] chars, int p, int end) {
         this.chars = chars;
         this.begin = p;
@@ -53,8 +55,6 @@
         return end;
     }
 
-    private final int INT_SIGN_BIT = 1 << 31;
-
     protected final int scanUnsignedNumber() {
         int last = c;
         int num = 0; // long ???
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,7 +22,6 @@
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
 
 import java.lang.ref.WeakReference;
-import java.util.Arrays;
 
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
@@ -36,10 +35,6 @@
     protected final int[]repeatStk;
     protected final int memStartStk, memEndStk;
 
-    // CEC
-    protected byte[] stateCheckBuff; // move to int[] ?
-    int stateCheckBuffSize;
-
     protected StackMachine(Regex regex, char[] chars, int p , int end) {
         super(regex, chars, p, end);
 
@@ -104,67 +99,12 @@
         stk++;
     }
 
-    // CEC
-
-    // STATE_CHECK_POS
-    private int stateCheckPos(int s, int snum) {
-        return (s - str) * regex.numCombExpCheck + (snum - 1);
-    }
-
-    // STATE_CHECK_VAL
-    protected final boolean stateCheckVal(int s, int snum) {
-        if (stateCheckBuff != null) {
-            int x = stateCheckPos(s, snum);
-            return (stateCheckBuff[x / 8] & (1 << (x % 8))) != 0;
-        }
-        return false;
-    }
-
-    // ELSE_IF_STATE_CHECK_MARK
-    private void stateCheckMark() {
-        StackEntry e = stack[stk];
-        int x = stateCheckPos(e.getStatePStr(), e.getStateCheck());
-        stateCheckBuff[x / 8] |= (1 << (x % 8));
-    }
-
-    // STATE_CHECK_BUFF_INIT
-    private static final int STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE = 16;
-    protected final void stateCheckBuffInit(int strLength, int offset, int stateNum) {
-        if (stateNum > 0 && strLength >= Config.CHECK_STRING_THRESHOLD_LEN) {
-            int size = ((strLength + 1) * stateNum + 7) >>> 3;
-            offset = (offset * stateNum) >>> 3;
-
-            if (size > 0 && offset < size && size < Config.CHECK_BUFF_MAX_SIZE) {
-                if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {
-                    stateCheckBuff = new byte[size];
-                } else {
-                    // same impl, reduce...
-                    stateCheckBuff = new byte[size];
-                }
-                Arrays.fill(stateCheckBuff, offset, (size - offset), (byte)0);
-                stateCheckBuffSize = size;
-            } else {
-                stateCheckBuff = null; // reduce
-                stateCheckBuffSize = 0;
-            }
-        } else {
-            stateCheckBuff = null; // reduce
-            stateCheckBuffSize = 0;
-        }
-    }
-
-    protected final void stateCheckBuffClear() {
-        stateCheckBuff = null;
-        stateCheckBuffSize = 0;
-    }
-
     private void push(int type, int pat, int s, int prev) {
         StackEntry e = ensure1();
         e.type = type;
         e.setStatePCode(pat);
         e.setStatePStr(s);
         e.setStatePStrPrev(prev);
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
         stk++;
     }
 
@@ -172,30 +112,9 @@
         StackEntry e = stack[stk];
         e.type = type;
         e.setStatePCode(pat);
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
         stk++;
     }
 
-    protected final void pushAltWithStateCheck(int pat, int s, int sprev, int snum) {
-        StackEntry e = ensure1();
-        e.type = ALT;
-        e.setStatePCode(pat);
-        e.setStatePStr(s);
-        e.setStatePStrPrev(sprev);
-        if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(stateCheckBuff != null ? snum : 0);
-        stk++;
-    }
-
-    protected final void pushStateCheck(int s, int snum) {
-        if (stateCheckBuff != null) {
-            StackEntry e = ensure1();
-            e.type = STATE_CHECK_MARK;
-            e.setStatePStr(s);
-            e.setStateCheck(snum);
-            stk++;
-        }
-    }
-
     protected final void pushAlt(int pat, int s, int prev) {
         push(ALT, pat, s, prev);
     }
@@ -294,19 +213,6 @@
         stk++;
     }
 
-    protected final void pushCallFrame(int pat) {
-        StackEntry e = ensure1();
-        e.type = CALL_FRAME;
-        e.setCallFrameRetAddr(pat);
-        stk++;
-    }
-
-    protected final void pushReturn() {
-        StackEntry e = ensure1();
-        e.type = RETURN;
-        stk++;
-    }
-
     // stack debug routines here
     // ...
 
@@ -331,8 +237,6 @@
 
             if ((e.type & MASK_POP_USED) != 0) {
                 return e;
-            } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                if (e.type == STATE_CHECK_MARK) stateCheckMark();
             }
         }
     }
@@ -346,8 +250,6 @@
             } else if (e.type == MEM_START) {
                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
-            } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                if (e.type == STATE_CHECK_MARK) stateCheckMark();
             }
         }
     }
@@ -368,8 +270,6 @@
             } else if (e.type == MEM_END) {
                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
-            } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                if (e.type == STATE_CHECK_MARK) stateCheckMark();
             }
         }
     }
@@ -391,8 +291,6 @@
             } else if (e.type == MEM_END){
                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
                 repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
-            } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                if (e.type == STATE_CHECK_MARK) stateCheckMark();
             }
         }
     }
@@ -414,8 +312,6 @@
             } else if (e.type == MEM_END) {
                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
-            } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
-                if (e.type == STATE_CHECK_MARK) stateCheckMark();
             }
         }
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java	Wed Jul 05 18:57:52 2017 +0200
@@ -609,7 +609,7 @@
         OP_ESC_CONTROL_CHARS | OP_ESC_C_CONTROL | OP_ESC_X_HEX2)
         & ~OP_ESC_LTGT_WORD_BEGIN_END ),
 
-        ( OP2_QMARK_GROUP_EFFECT | OP2_CCLASS_SET_OP |
+        ( OP2_QMARK_GROUP_EFFECT |
         OP2_ESC_V_VTAB | OP2_ESC_U_HEX4 ),
 
         ( GNU_REGEX_BV | DIFFERENT_LEN_ALT_LOOK_BEHIND ),
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
-
-public final class UnsetAddrList {
-    int num;
-    Node[]targets;
-    int[]offsets;
-
-    public UnsetAddrList(int size) {
-        targets = new Node[size];
-        offsets = new int[size];
-    }
-
-    public void add(int offset, Node node) {
-        if (num >= offsets.length) {
-            Node []ttmp = new Node[targets.length << 1];
-            System.arraycopy(targets, 0, ttmp, 0, num);
-            targets = ttmp;
-            int[]otmp = new int[offsets.length << 1];
-            System.arraycopy(offsets, 0, otmp, 0, num);
-            offsets = otmp;
-        }
-        targets[num] = node;
-        offsets[num] = offset;
-
-        num++;
-    }
-
-    public void fix(Regex regex) {
-        for (int i=0; i<num; i++) {
-            EncloseNode en = (EncloseNode)targets[i];
-            if (!en.isAddrFixed()) new InternalException(ErrorMessages.ERR_PARSER_BUG);
-            regex.code[offsets[i]] = en.callAddr; // is this safe ?
-        }
-    }
-
-    public String toString() {
-        StringBuilder value = new StringBuilder();
-        if (num > 0) {
-            for (int i=0; i<num; i++) {
-                value.append("offset + " + offsets[i] + " target: " + targets[i].getAddressName());
-            }
-        }
-        return value.toString();
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,7 +22,6 @@
 import jdk.nashorn.internal.runtime.regexp.joni.*;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.AsciiTables;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
@@ -40,6 +39,41 @@
 
     private int ctype;                      // for hashing purposes
 
+    private final static short AsciiCtypeTable[] = {
+            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
+            0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008,
+            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
+            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
+            0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
+            0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
+            0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0,
+            0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
+            0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2,
+            0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
+            0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
+            0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0,
+            0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2,
+            0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
+            0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
+            0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+    };
+
     // node_new_cclass
     public CClassNode() {}
 
@@ -330,13 +364,13 @@
                 if (not) {
                     for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
                         // if (!ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
-                        if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
+                        if ((AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
                     }
                     addAllMultiByteRange();
                 } else {
                     for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
                         // if (ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
-                        if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
+                        if ((AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
                     }
                 }
                 return;
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CTypeNode.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.ast;
-
-public final class CTypeNode extends Node {
-    public int ctype;
-    public boolean not;
-
-    public CTypeNode(int type, boolean not) {
-        this.ctype= type;
-        this.not = not;
-    }
-
-    @Override
-    public int getType() {
-        return CTYPE;
-    }
-
-    @Override
-    public String getName() {
-        return "Character Type";
-    }
-
-    @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder();
-        value.append("\n  ctype: " + ctype);
-        value.append("\n  not: " + not);
-
-        return value.toString();
-    }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CallNode.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.ast;
-
-import java.util.Set;
-
-import jdk.nashorn.internal.runtime.regexp.joni.UnsetAddrList;
-import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
-
-public final class CallNode extends StateNode {
-    public char[] name;
-    public int nameP;
-    public int nameEnd;
-
-    public int groupNum;
-    public Node target;             // is it an EncloseNode always ?
-    public UnsetAddrList unsetAddrList;
-
-    public CallNode(char[] name, int nameP, int nameEnd, int gnum) {
-        this.name = name;
-        this.nameP = nameP;
-        this.nameEnd = nameEnd;
-        this.groupNum = gnum; /* call by number if gnum != 0 */
-    }
-
-    @Override
-    public int getType() {
-        return CALL;
-    }
-
-    @Override
-    protected void setChild(Node newChild) {
-        target = newChild;
-    }
-
-    @Override
-    protected Node getChild() {
-        return target;
-    }
-
-    public void setTarget(Node tgt) {
-        target = tgt;
-        tgt.parent = this;
-    }
-
-    @Override
-    public String getName() {
-        return "Call";
-    }
-
-    @Override
-    public void verifyTree(Set<Node> set, WarnCallback warnings) {
-        if (target == null || target.parent == this)
-            warnings.warn(this.getAddressName() + " doesn't point to a target or the target has been stolen");
-        // do not recurse here
-    }
-
-    @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder(super.toString(level));
-        value.append("\n  name: " + new String(name, nameP, nameEnd - nameP));
-        value.append("\n  groupNum: " + groupNum);
-        value.append("\n  target: " + pad(target.getAddressName(), level + 1));
-        value.append("\n  unsetAddrList: " + pad(unsetAddrList, level + 1));
-
-        return value.toString();
-    }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -25,7 +25,7 @@
 
 public final class EncloseNode extends StateNode implements EncloseType {
 
-    public int type;                // enclose type
+    public final int type;                // enclose type
     public int regNum;
     public int option;
     public Node target;             /* EncloseNode : ENCLOSE_MEMORY */
@@ -42,10 +42,8 @@
     }
 
     // node_new_enclose_memory
-    public EncloseNode(int option, boolean isNamed) {
+    public EncloseNode() {
         this(MEMORY);
-        if (isNamed) setNamedGroup();
-        if (Config.USE_SUBEXP_CALL) this.option = option;
     }
 
     // node_new_option
@@ -104,46 +102,14 @@
         return types.toString();
     }
 
-    public void setEncloseStatus(int flag) {
-        state |= flag;
-    }
-
-    public void clearEncloseStatus(int flag) {
-        state &= ~flag;
-    }
-
-    public void clearMemory() {
-        type &= ~MEMORY;
-    }
-
-    public void setMemory() {
-        type |= MEMORY;
-    }
-
     public boolean isMemory() {
         return (type & MEMORY) != 0;
     }
 
-    public void clearOption() {
-        type &= ~OPTION;
-    }
-
-    public void setOption() {
-        type |= OPTION;
-    }
-
     public boolean isOption() {
         return (type & OPTION) != 0;
     }
 
-    public void clearStopBacktrack() {
-        type &= ~STOP_BACKTRACK;
-    }
-
-    public void setStopBacktrack() {
-        type |= STOP_BACKTRACK;
-    }
-
     public boolean isStopBacktrack() {
         return (type & STOP_BACKTRACK) != 0;
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -21,9 +21,10 @@
 
 import jdk.nashorn.internal.runtime.regexp.joni.Config;
 import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
-import jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
 
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
+
 public final class QuantifierNode extends StateNode {
 
     public Node target;
@@ -37,8 +38,33 @@
     public Node nextHeadExact;
     public boolean isRefered;           /* include called node. don't eliminate even if {0} */
 
-    // USE_COMBINATION_EXPLOSION_CHECK
-    public int  combExpCheckNum;        /* 1,2,3...: check,  0: no check  */
+    enum ReduceType {
+        ASIS,       /* as is */
+        DEL,        /* delete parent */
+        A,          /* to '*'    */
+        AQ,         /* to '*?'   */
+        QQ,         /* to '??'   */
+        P_QQ,       /* to '+)??' */
+        PQ_Q,       /* to '+?)?' */
+    }
+
+    private final static ReduceType[][] REDUCE_TABLE = {
+            {DEL,     A,      A,      QQ,     AQ,     ASIS}, /* '?'  */
+            {DEL,     DEL,    DEL,    P_QQ,   P_QQ,   DEL},  /* '*'  */
+            {A,       A,      DEL,    ASIS,   P_QQ,   DEL},  /* '+'  */
+            {DEL,     AQ,     AQ,     DEL,    AQ,     AQ},   /* '??' */
+            {DEL,     DEL,    DEL,    DEL,    DEL,    DEL},  /* '*?' */
+            {ASIS,    PQ_Q,   DEL,    AQ,     AQ,     DEL}   /* '+?' */
+    };
+
+    private final static String PopularQStr[] = new String[] {
+            "?", "*", "+", "??", "*?", "+?"
+    };
+
+    private final static String ReduceQStr[]= new String[] {
+            "", "", "*", "*?", "??", "+ and ??", "+? and ?"
+    };
+
 
     public QuantifierNode(int lower, int upper, boolean byNumber) {
         this.lower = lower;
@@ -92,7 +118,6 @@
         value.append("\n  headExact: " + pad(headExact, level + 1));
         value.append("\n  nextHeadExact: " + pad(nextHeadExact, level + 1));
         value.append("\n  isRefered: " + isRefered);
-        value.append("\n  combExpCheckNum: " + combExpCheckNum);
 
         return value.toString();
     }
@@ -134,7 +159,6 @@
         headExact = other.headExact;
         nextHeadExact = other.nextHeadExact;
         isRefered = other.isRefered;
-        combExpCheckNum = other.combExpCheckNum;
     }
 
     public void reduceNestedQuantifier(QuantifierNode other) {
@@ -143,7 +167,7 @@
 
         if (pnum < 0 || cnum < 0) return;
 
-        switch(Reduce.REDUCE_TABLE[cnum][pnum]) {
+        switch(REDUCE_TABLE[cnum][pnum]) {
         case DEL:
             // no need to set the parent here...
             // swap ?
@@ -226,7 +250,7 @@
 
             if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
                 if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
-                    switch(Reduce.REDUCE_TABLE[targetQNum][nestQNum]) {
+                    switch(REDUCE_TABLE[targetQNum][nestQNum]) {
                     case ASIS:
                         break;
 
@@ -237,9 +261,9 @@
 
                     default:
                         env.reg.getWarnings().warn(new String(chars, p, end) +
-                                " nested repeat operator " + Reduce.PopularQStr[targetQNum] +
-                                " and " + Reduce.PopularQStr[nestQNum] + " was replaced with '" +
-                                Reduce.ReduceQStr[Reduce.REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
+                                " nested repeat operator " + PopularQStr[targetQNum] +
+                                " and " + PopularQStr[nestQNum] + " was replaced with '" +
+                                ReduceQStr[REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
                     }
                 }
             } // USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -40,7 +40,6 @@
         if (isRecursion()) states.append("RECURSION ");
         if (isCalled()) states.append("CALLED ");
         if (isAddrFixed()) states.append("ADDR_FIXED ");
-        if (isNamedGroup()) states.append("NAMED_GROUP ");
         if (isNameRef()) states.append("NAME_REF ");
         if (isInRepeat()) states.append("IN_REPEAT ");
         if (isNestLevel()) states.append("NEST_LEVEL ");
@@ -57,10 +56,6 @@
         state |= NST_MIN_FIXED;
     }
 
-    public void clearMinFixed() {
-        state &= ~NST_MIN_FIXED;
-    }
-
     public boolean isMaxFixed() {
         return (state & NST_MAX_FIXED) != 0;
     }
@@ -69,10 +64,6 @@
         state |= NST_MAX_FIXED;
     }
 
-    public void clearMaxFixed() {
-        state &= ~NST_MAX_FIXED;
-    }
-
     public boolean isCLenFixed() {
         return (state & NST_CLEN_FIXED) != 0;
     }
@@ -81,10 +72,6 @@
         state |= NST_CLEN_FIXED;
     }
 
-    public void clearCLenFixed() {
-        state &= ~NST_CLEN_FIXED;
-    }
-
     public boolean isMark1() {
         return (state & NST_MARK1) != 0;
     }
@@ -93,10 +80,6 @@
         state |= NST_MARK1;
     }
 
-    public void clearMark1() {
-        state &= ~NST_MARK1;
-    }
-
     public boolean isMark2() {
         return (state & NST_MARK2) != 0;
     }
@@ -117,10 +100,6 @@
         state |= NST_MEM_BACKREFED;
     }
 
-    public void clearMemBackrefed() {
-        state &= ~NST_MEM_BACKREFED;
-    }
-
     public boolean isStopBtSimpleRepeat() {
         return (state & NST_STOP_BT_SIMPLE_REPEAT) != 0;
     }
@@ -129,10 +108,6 @@
         state |= NST_STOP_BT_SIMPLE_REPEAT;
     }
 
-    public void clearStopBtSimpleRepeat() {
-        state &= ~NST_STOP_BT_SIMPLE_REPEAT;
-    }
-
     public boolean isRecursion() {
         return (state & NST_RECURSION) != 0;
     }
@@ -141,10 +116,6 @@
         state |= NST_RECURSION;
     }
 
-    public void clearRecursion() {
-        state &= ~NST_RECURSION;
-    }
-
     public boolean isCalled() {
         return (state & NST_CALLED) != 0;
     }
@@ -153,10 +124,6 @@
         state |= NST_CALLED;
     }
 
-    public void clearCAlled() {
-        state &= ~NST_CALLED;
-    }
-
     public boolean isAddrFixed() {
         return (state & NST_ADDR_FIXED) != 0;
     }
@@ -165,22 +132,6 @@
         state |= NST_ADDR_FIXED;
     }
 
-    public void clearAddrFixed() {
-        state &= ~NST_ADDR_FIXED;
-    }
-
-    public boolean isNamedGroup() {
-        return (state & NST_NAMED_GROUP) != 0;
-    }
-
-    public void setNamedGroup() {
-        state |= NST_NAMED_GROUP;
-    }
-
-    public void clearNamedGroup() {
-        state &= ~NST_NAMED_GROUP;
-    }
-
     public boolean isNameRef() {
         return (state & NST_NAME_REF) != 0;
     }
@@ -189,10 +140,6 @@
         state |= NST_NAME_REF;
     }
 
-    public void clearNameRef() {
-        state &= ~NST_NAME_REF;
-    }
-
     public boolean isInRepeat() {
         return (state & NST_IN_REPEAT) != 0;
     }
@@ -201,10 +148,6 @@
         state |= NST_IN_REPEAT;
     }
 
-    public void clearInRepeat() {
-        state &= ~NST_IN_REPEAT;
-    }
-
     public boolean isNestLevel() {
         return (state & NST_NEST_LEVEL) != 0;
     }
@@ -213,10 +156,6 @@
         state |= NST_NEST_LEVEL;
     }
 
-    public void clearNestLevel() {
-        state &= ~NST_NEST_LEVEL;
-    }
-
     public boolean isByNumber() {
         return (state & NST_BY_NUMBER) != 0;
     }
@@ -225,8 +164,4 @@
         state |= NST_BY_NUMBER;
     }
 
-    public void clearByNumber() {
-        state &= ~NST_BY_NUMBER;
-    }
-
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-package jdk.nashorn.internal.runtime.regexp.joni.bench;
-
-import jdk.nashorn.internal.runtime.regexp.joni.Option;
-import jdk.nashorn.internal.runtime.regexp.joni.Regex;
-import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
-
-public abstract class AbstractBench {
-    protected void bench(String _reg, String _str, int warmup, int times) throws Exception {
-        char[] reg = _reg.toCharArray();
-        char[] str = _str.toCharArray();
-
-        Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
-
-        System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
-
-        for(int j=0;j<warmup;j++) {
-            long before = System.currentTimeMillis();
-            for(int i = 0; i < times; i++) {
-                p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
-            }
-            long time = System.currentTimeMillis() - before;
-            System.err.println(":  " + time + "ms");
-        }
-    }
-
-    protected void benchBestOf(String _reg, String _str, int warmup, int times) throws Exception {
-        char[] reg = _reg.toCharArray();
-        char[] str = _str.toCharArray();
-
-        Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
-
-        System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
-
-        long best = Long.MAX_VALUE;
-
-        for(int j=0;j<warmup;j++) {
-            long before = System.currentTimeMillis();
-            for(int i = 0; i < times; i++) {
-                p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
-            }
-            long time = System.currentTimeMillis() - before;
-            if(time < best) {
-                best = time;
-            }
-            System.err.print(".");
-        }
-        System.err.println(":  " + best + "ms");
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchGreedyBacktrack.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-package jdk.nashorn.internal.runtime.regexp.joni.bench;
-
-public class BenchGreedyBacktrack extends AbstractBench {
-    public static void main(String[] args) throws Exception {
-        new BenchGreedyBacktrack().bench(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,1000000);
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchRailsRegs.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package jdk.nashorn.internal.runtime.regexp.joni.bench;
-
-public class BenchRailsRegs extends AbstractBench {
-    public static void main(String[] args) throws Exception {
-        final String[][] regexps = {{"a.*?[b-z]{2,4}aaaaaa","afdgdsgderaabxxaaaaaaaaaaaaaaaaaaaaaaaa"},
-                                    {"://","/shop/viewCategory.shtml?category=DOGS"},
-                                    {"^\\w+\\://[^/]+(/.*|$)$","/shop/viewCategory.shtml?category=DOGS"},
-                                    {"\\A/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/signonForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/newAccountForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/newAccount\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/viewCart\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/index\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A/shop/viewCategory\\.shtml/?\\Z","/shop/viewCategory.shtml"},
-                                    {"\\A(?:::)?([A-Z]\\w*(?:::[A-Z]\\w*)*)\\z","CategoriesController"},
-                                    {"\\Ainsert","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7')  LIMIT 1"},
-                                    {"\\A\\(?\\s*(select|show)","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7')  LIMIT 1"},
-                                    {".*?\n","1b341ffe23b5298676d535fcabd3d0d7"},
-                                    {"^find_(all_by|by)_([_a-zA-Z]\\w*)$","find_by_string_id"},
-                                    {"\\.rjs$","categories/show.rhtml"},
-                                    {"^[-a-z]+://","petstore.css"},
-                                    {"^get$",""},
-                                    {"^post$",""},
-                                    {"^[^:]+","www.example.com"},
-                                    {"(=|\\?|_before_type_cast)$", "updated_on"},
-                                    {"^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/"}};
-        for(String[] reg : regexps) {
-            new BenchRailsRegs().benchBestOf(reg[0],reg[1],10,1000000);
-        }
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchSeveralRegexps.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-package jdk.nashorn.internal.runtime.regexp.joni.bench;
-
-public class BenchSeveralRegexps extends AbstractBench {
-    public static void main(String[] args) throws Exception {
-        int BASE = 1000000;
-
-        new BenchSeveralRegexps().benchBestOf("a"," a",10,4*BASE);
-
-        new BenchSeveralRegexps().benchBestOf(".*?=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
-
-        new BenchSeveralRegexps().benchBestOf("^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
-
-        new BenchSeveralRegexps().benchBestOf(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
-
-        new BenchSeveralRegexps().benchBestOf(".*=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java	Wed Jul 05 18:57:52 2017 +0200
@@ -19,8 +19,6 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni.constants;
 
-import jdk.nashorn.internal.runtime.regexp.joni.Config;
-
 public interface OPCode {
     final int FINISH                        = 0;            /* matching process terminator (no more alternative) */
     final int END                           = 1;            /* pattern code terminator (success end) */
@@ -151,237 +149,4 @@
     final int EXACT1_IC_SB                  = 105;           /* single byte, N = 1, ignore case */
     final int EXACTN_IC_SB                  = 106;           /* single byte,        ignore case */
 
-
-    public final String OpCodeNames[] = Config.DEBUG_COMPILE ? new String[] {
-        "finish", /*OP_FINISH*/
-        "end", /*OP_END*/
-        "exact1", /*OP_EXACT1*/
-        "exact2", /*OP_EXACT2*/
-        "exact3", /*OP_EXACT3*/
-        "exact4", /*OP_EXACT4*/
-        "exact5", /*OP_EXACT5*/
-        "exactn", /*OP_EXACTN*/
-        "exactmb2-n1", /*OP_EXACTMB2N1*/
-        "exactmb2-n2", /*OP_EXACTMB2N2*/
-        "exactmb2-n3", /*OP_EXACTMB2N3*/
-        "exactmb2-n", /*OP_EXACTMB2N*/
-        "exactmb3n", /*OP_EXACTMB3N*/
-        "exactmbn", /*OP_EXACTMBN*/
-        "exact1-ic", /*OP_EXACT1_IC*/
-        "exactn-ic", /*OP_EXACTN_IC*/
-        "cclass", /*OP_CCLASS*/
-        "cclass-mb", /*OP_CCLASS_MB*/
-        "cclass-mix", /*OP_CCLASS_MIX*/
-        "cclass-not", /*OP_CCLASS_NOT*/
-        "cclass-mb-not", /*OP_CCLASS_MB_NOT*/
-        "cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
-        "cclass-node", /*OP_CCLASS_NODE*/
-        "anychar", /*OP_ANYCHAR*/
-        "anychar-ml", /*OP_ANYCHAR_ML*/
-        "anychar*", /*OP_ANYCHAR_STAR*/
-        "anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
-        "anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
-        "anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
-        "word", /*OP_WORD*/
-        "not-word", /*OP_NOT_WORD*/
-        "word-bound", /*OP_WORD_BOUND*/
-        "not-word-bound", /*OP_NOT_WORD_BOUND*/
-        "word-begin", /*OP_WORD_BEGIN*/
-        "word-end", /*OP_WORD_END*/
-        "begin-buf", /*OP_BEGIN_BUF*/
-        "end-buf", /*OP_END_BUF*/
-        "begin-line", /*OP_BEGIN_LINE*/
-        "end-line", /*OP_END_LINE*/
-        "semi-end-buf", /*OP_SEMI_END_BUF*/
-        "begin-position", /*OP_BEGIN_POSITION*/
-        "backref1", /*OP_BACKREF1*/
-        "backref2", /*OP_BACKREF2*/
-        "backrefn", /*OP_BACKREFN*/
-        "backrefn-ic", /*OP_BACKREFN_IC*/
-        "backref_multi", /*OP_BACKREF_MULTI*/
-        "backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
-        "backref_at_level", /*OP_BACKREF_AT_LEVEL*/
-        "mem-start", /*OP_MEMORY_START*/
-        "mem-start-push", /*OP_MEMORY_START_PUSH*/
-        "mem-end-push", /*OP_MEMORY_END_PUSH*/
-        "mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
-        "mem-end", /*OP_MEMORY_END*/
-        "mem-end-rec", /*OP_MEMORY_END_REC*/
-        "fail", /*OP_FAIL*/
-        "jump", /*OP_JUMP*/
-        "push", /*OP_PUSH*/
-        "pop", /*OP_POP*/
-        "push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
-        "push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
-        "repeat", /*OP_REPEAT*/
-        "repeat-ng", /*OP_REPEAT_NG*/
-        "repeat-inc", /*OP_REPEAT_INC*/
-        "repeat-inc-ng", /*OP_REPEAT_INC_NG*/
-        "repeat-inc-sg", /*OP_REPEAT_INC_SG*/
-        "repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
-        "null-check-start", /*OP_NULL_CHECK_START*/
-        "null-check-end", /*OP_NULL_CHECK_END*/
-        "null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
-        "null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
-        "push-pos", /*OP_PUSH_POS*/
-        "pop-pos", /*OP_POP_POS*/
-        "push-pos-not", /*OP_PUSH_POS_NOT*/
-        "fail-pos", /*OP_FAIL_POS*/
-        "push-stop-bt", /*OP_PUSH_STOP_BT*/
-        "pop-stop-bt", /*OP_POP_STOP_BT*/
-        "look-behind", /*OP_LOOK_BEHIND*/
-        "push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
-        "fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
-        "call", /*OP_CALL*/
-        "return", /*OP_RETURN*/
-        "state-check-push", /*OP_STATE_CHECK_PUSH*/
-        "state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
-        "state-check", /*OP_STATE_CHECK*/
-        "state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
-        "state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
-        "set-option-push", /*OP_SET_OPTION_PUSH*/
-        "set-option", /*OP_SET_OPTION*/
-
-        // single byte versions
-        "anychar-sb", /*OP_ANYCHAR*/
-        "anychar-ml-sb", /*OP_ANYCHAR_ML*/
-        "anychar*-sb", /*OP_ANYCHAR_STAR*/
-        "anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
-        "anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
-        "anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
-        "state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
-        "state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
-
-        "cclass-sb", /*OP_CCLASS*/
-        "cclass-not-sb", /*OP_CCLASS_NOT*/
-
-        "word-sb", /*OP_WORD*/
-        "not-word-sb", /*OP_NOT_WORD*/
-        "word-bound-sb", /*OP_WORD_BOUND*/
-        "not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
-        "word-begin-sb", /*OP_WORD_BEGIN*/
-        "word-end-sb", /*OP_WORD_END*/
-
-        "look-behind-sb", /*OP_LOOK_BEHIND*/
-
-        "exact1-ic-sb", /*OP_EXACT1_IC*/
-        "exactn-ic-sb", /*OP_EXACTN_IC*/
-
-    } : null;
-
-    public final int OpCodeArgTypes[] = Config.DEBUG_COMPILE ? new int[] {
-        Arguments.NON, /*OP_FINISH*/
-        Arguments.NON, /*OP_END*/
-        Arguments.SPECIAL, /*OP_EXACT1*/
-        Arguments.SPECIAL, /*OP_EXACT2*/
-        Arguments.SPECIAL, /*OP_EXACT3*/
-        Arguments.SPECIAL, /*OP_EXACT4*/
-        Arguments.SPECIAL, /*OP_EXACT5*/
-        Arguments.SPECIAL, /*OP_EXACTN*/
-        Arguments.SPECIAL, /*OP_EXACTMB2N1*/
-        Arguments.SPECIAL, /*OP_EXACTMB2N2*/
-        Arguments.SPECIAL, /*OP_EXACTMB2N3*/
-        Arguments.SPECIAL, /*OP_EXACTMB2N*/
-        Arguments.SPECIAL, /*OP_EXACTMB3N*/
-        Arguments.SPECIAL, /*OP_EXACTMBN*/
-        Arguments.SPECIAL, /*OP_EXACT1_IC*/
-        Arguments.SPECIAL, /*OP_EXACTN_IC*/
-        Arguments.SPECIAL, /*OP_CCLASS*/
-        Arguments.SPECIAL, /*OP_CCLASS_MB*/
-        Arguments.SPECIAL, /*OP_CCLASS_MIX*/
-        Arguments.SPECIAL, /*OP_CCLASS_NOT*/
-        Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
-        Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
-        Arguments.SPECIAL, /*OP_CCLASS_NODE*/
-        Arguments.NON, /*OP_ANYCHAR*/
-        Arguments.NON, /*OP_ANYCHAR_ML*/
-        Arguments.NON, /*OP_ANYCHAR_STAR*/
-        Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
-        Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
-        Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
-        Arguments.NON, /*OP_WORD*/
-        Arguments.NON, /*OP_NOT_WORD*/
-        Arguments.NON, /*OP_WORD_BOUND*/
-        Arguments.NON, /*OP_NOT_WORD_BOUND*/
-        Arguments.NON, /*OP_WORD_BEGIN*/
-        Arguments.NON, /*OP_WORD_END*/
-        Arguments.NON, /*OP_BEGIN_BUF*/
-        Arguments.NON, /*OP_END_BUF*/
-        Arguments.NON, /*OP_BEGIN_LINE*/
-        Arguments.NON, /*OP_END_LINE*/
-        Arguments.NON, /*OP_SEMI_END_BUF*/
-        Arguments.NON, /*OP_BEGIN_POSITION*/
-        Arguments.NON, /*OP_BACKREF1*/
-        Arguments.NON, /*OP_BACKREF2*/
-        Arguments.MEMNUM, /*OP_BACKREFN*/
-        Arguments.SPECIAL, /*OP_BACKREFN_IC*/
-        Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
-        Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
-        Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
-        Arguments.MEMNUM, /*OP_MEMORY_START*/
-        Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
-        Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
-        Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
-        Arguments.MEMNUM, /*OP_MEMORY_END*/
-        Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
-        Arguments.NON, /*OP_FAIL*/
-        Arguments.RELADDR, /*OP_JUMP*/
-        Arguments.RELADDR, /*OP_PUSH*/
-        Arguments.NON, /*OP_POP*/
-        Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
-        Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
-        Arguments.SPECIAL, /*OP_REPEAT*/
-        Arguments.SPECIAL, /*OP_REPEAT_NG*/
-        Arguments.MEMNUM, /*OP_REPEAT_INC*/
-        Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
-        Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
-        Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
-        Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
-        Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
-        Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
-        Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
-        Arguments.NON, /*OP_PUSH_POS*/
-        Arguments.NON, /*OP_POP_POS*/
-        Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
-        Arguments.NON, /*OP_FAIL_POS*/
-        Arguments.NON, /*OP_PUSH_STOP_BT*/
-        Arguments.NON, /*OP_POP_STOP_BT*/
-        Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
-        Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
-        Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
-        Arguments.ABSADDR, /*OP_CALL*/
-        Arguments.NON, /*OP_RETURN*/
-        Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
-        Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
-        Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
-        Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
-        Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
-        Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
-        Arguments.OPTION, /*OP_SET_OPTION*/
-
-        // single byte versions
-        Arguments.NON, /*OP_ANYCHAR*/
-        Arguments.NON, /*OP_ANYCHAR_ML*/
-        Arguments.NON, /*OP_ANYCHAR_STAR*/
-        Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
-        Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
-        Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
-        Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
-        Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
-
-        Arguments.SPECIAL, /*OP_CCLASS*/
-        Arguments.SPECIAL, /*OP_CCLASS_NOT*/
-
-        Arguments.NON, /*OP_WORD*/
-        Arguments.NON, /*OP_NOT_WORD*/
-        Arguments.NON, /*OP_WORD_BOUND*/
-        Arguments.NON, /*OP_NOT_WORD_BOUND*/
-        Arguments.NON, /*OP_WORD_BEGIN*/
-        Arguments.NON, /*OP_WORD_END*/
-
-        Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
-
-        Arguments.SPECIAL, /*OP_EXACT1_IC*/
-        Arguments.SPECIAL, /*OP_EXACTN_IC*/
-    } : null;
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Reduce.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.constants;
-
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.A;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.AQ;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.ASIS;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.DEL;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.PQ_Q;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.P_QQ;
-import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.QQ;
-
-public interface Reduce {
-
-    enum ReduceType {
-        ASIS,       /* as is */
-        DEL,        /* delete parent */
-        A,          /* to '*'    */
-        AQ,         /* to '*?'   */
-        QQ,         /* to '??'   */
-        P_QQ,       /* to '+)??' */
-        PQ_Q,       /* to '+?)?' */
-    }
-
-    final ReduceType[][]REDUCE_TABLE = {
-      {DEL,     A,      A,      QQ,     AQ,     ASIS}, /* '?'  */
-      {DEL,     DEL,    DEL,    P_QQ,   P_QQ,   DEL},  /* '*'  */
-      {A,       A,      DEL,    ASIS,   P_QQ,   DEL},  /* '+'  */
-      {DEL,     AQ,     AQ,     DEL,    AQ,     AQ},   /* '??' */
-      {DEL,     DEL,    DEL,    DEL,    DEL,    DEL},  /* '*?' */
-      {ASIS,    PQ_Q,   DEL,    AQ,     AQ,     DEL}   /* '+?' */
-    };
-
-
-    final String PopularQStr[] = new String[] {
-        "?", "*", "+", "??", "*?", "+?"
-    };
-
-    String ReduceQStr[]= new String[] {
-        "", "", "*", "*?", "??", "+ and ??", "+? and ?"
-    };
-
-}
-
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/AsciiTables.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.encoding;
-
-public class AsciiTables {
-
-    public static final short AsciiCtypeTable[] = {
-            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
-            0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008,
-            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
-            0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
-            0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
-            0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
-            0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0,
-            0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
-            0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2,
-            0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
-            0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
-            0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0,
-            0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2,
-            0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
-            0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
-            0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-    };
-
-    public static final byte ToLowerCaseTable[] = {
-            (byte)'\000', (byte)'\001', (byte)'\002', (byte)'\003', (byte)'\004', (byte)'\005', (byte)'\006', (byte)'\007',
-            (byte)'\010', (byte)'\011', (byte)'\012', (byte)'\013', (byte)'\014', (byte)'\015', (byte)'\016', (byte)'\017',
-            (byte)'\020', (byte)'\021', (byte)'\022', (byte)'\023', (byte)'\024', (byte)'\025', (byte)'\026', (byte)'\027',
-            (byte)'\030', (byte)'\031', (byte)'\032', (byte)'\033', (byte)'\034', (byte)'\035', (byte)'\036', (byte)'\037',
-            (byte)'\040', (byte)'\041', (byte)'\042', (byte)'\043', (byte)'\044', (byte)'\045', (byte)'\046', (byte)'\047',
-            (byte)'\050', (byte)'\051', (byte)'\052', (byte)'\053', (byte)'\054', (byte)'\055', (byte)'\056', (byte)'\057',
-            (byte)'\060', (byte)'\061', (byte)'\062', (byte)'\063', (byte)'\064', (byte)'\065', (byte)'\066', (byte)'\067',
-            (byte)'\070', (byte)'\071', (byte)'\072', (byte)'\073', (byte)'\074', (byte)'\075', (byte)'\076', (byte)'\077',
-            (byte)'\100', (byte)'\141', (byte)'\142', (byte)'\143', (byte)'\144', (byte)'\145', (byte)'\146', (byte)'\147',
-            (byte)'\150', (byte)'\151', (byte)'\152', (byte)'\153', (byte)'\154', (byte)'\155', (byte)'\156', (byte)'\157',
-            (byte)'\160', (byte)'\161', (byte)'\162', (byte)'\163', (byte)'\164', (byte)'\165', (byte)'\166', (byte)'\167',
-            (byte)'\170', (byte)'\171', (byte)'\172', (byte)'\133', (byte)'\134', (byte)'\135', (byte)'\136', (byte)'\137',
-            (byte)'\140', (byte)'\141', (byte)'\142', (byte)'\143', (byte)'\144', (byte)'\145', (byte)'\146', (byte)'\147',
-            (byte)'\150', (byte)'\151', (byte)'\152', (byte)'\153', (byte)'\154', (byte)'\155', (byte)'\156', (byte)'\157',
-            (byte)'\160', (byte)'\161', (byte)'\162', (byte)'\163', (byte)'\164', (byte)'\165', (byte)'\166', (byte)'\167',
-            (byte)'\170', (byte)'\171', (byte)'\172', (byte)'\173', (byte)'\174', (byte)'\175', (byte)'\176', (byte)'\177',
-            (byte)'\200', (byte)'\201', (byte)'\202', (byte)'\203', (byte)'\204', (byte)'\205', (byte)'\206', (byte)'\207',
-            (byte)'\210', (byte)'\211', (byte)'\212', (byte)'\213', (byte)'\214', (byte)'\215', (byte)'\216', (byte)'\217',
-            (byte)'\220', (byte)'\221', (byte)'\222', (byte)'\223', (byte)'\224', (byte)'\225', (byte)'\226', (byte)'\227',
-            (byte)'\230', (byte)'\231', (byte)'\232', (byte)'\233', (byte)'\234', (byte)'\235', (byte)'\236', (byte)'\237',
-            (byte)'\240', (byte)'\241', (byte)'\242', (byte)'\243', (byte)'\244', (byte)'\245', (byte)'\246', (byte)'\247',
-            (byte)'\250', (byte)'\251', (byte)'\252', (byte)'\253', (byte)'\254', (byte)'\255', (byte)'\256', (byte)'\257',
-            (byte)'\260', (byte)'\261', (byte)'\262', (byte)'\263', (byte)'\264', (byte)'\265', (byte)'\266', (byte)'\267',
-            (byte)'\270', (byte)'\271', (byte)'\272', (byte)'\273', (byte)'\274', (byte)'\275', (byte)'\276', (byte)'\277',
-            (byte)'\300', (byte)'\301', (byte)'\302', (byte)'\303', (byte)'\304', (byte)'\305', (byte)'\306', (byte)'\307',
-            (byte)'\310', (byte)'\311', (byte)'\312', (byte)'\313', (byte)'\314', (byte)'\315', (byte)'\316', (byte)'\317',
-            (byte)'\320', (byte)'\321', (byte)'\322', (byte)'\323', (byte)'\324', (byte)'\325', (byte)'\326', (byte)'\327',
-            (byte)'\330', (byte)'\331', (byte)'\332', (byte)'\333', (byte)'\334', (byte)'\335', (byte)'\336', (byte)'\337',
-            (byte)'\340', (byte)'\341', (byte)'\342', (byte)'\343', (byte)'\344', (byte)'\345', (byte)'\346', (byte)'\347',
-            (byte)'\350', (byte)'\351', (byte)'\352', (byte)'\353', (byte)'\354', (byte)'\355', (byte)'\356', (byte)'\357',
-            (byte)'\360', (byte)'\361', (byte)'\362', (byte)'\363', (byte)'\364', (byte)'\365', (byte)'\366', (byte)'\367',
-            (byte)'\370', (byte)'\371', (byte)'\372', (byte)'\373', (byte)'\374', (byte)'\375', (byte)'\376', (byte)'\377',
-    };
-
-    public static final byte ToUpperCaseTable[] = {
-            (byte)'\000', (byte)'\001', (byte)'\002', (byte)'\003', (byte)'\004', (byte)'\005', (byte)'\006', (byte)'\007',
-            (byte)'\010', (byte)'\011', (byte)'\012', (byte)'\013', (byte)'\014', (byte)'\015', (byte)'\016', (byte)'\017',
-            (byte)'\020', (byte)'\021', (byte)'\022', (byte)'\023', (byte)'\024', (byte)'\025', (byte)'\026', (byte)'\027',
-            (byte)'\030', (byte)'\031', (byte)'\032', (byte)'\033', (byte)'\034', (byte)'\035', (byte)'\036', (byte)'\037',
-            (byte)'\040', (byte)'\041', (byte)'\042', (byte)'\043', (byte)'\044', (byte)'\045', (byte)'\046', (byte)'\047',
-            (byte)'\050', (byte)'\051', (byte)'\052', (byte)'\053', (byte)'\054', (byte)'\055', (byte)'\056', (byte)'\057',
-            (byte)'\060', (byte)'\061', (byte)'\062', (byte)'\063', (byte)'\064', (byte)'\065', (byte)'\066', (byte)'\067',
-            (byte)'\070', (byte)'\071', (byte)'\072', (byte)'\073', (byte)'\074', (byte)'\075', (byte)'\076', (byte)'\077',
-            (byte)'\100', (byte)'\101', (byte)'\102', (byte)'\103', (byte)'\104', (byte)'\105', (byte)'\106', (byte)'\107',
-            (byte)'\110', (byte)'\111', (byte)'\112', (byte)'\113', (byte)'\114', (byte)'\115', (byte)'\116', (byte)'\117',
-            (byte)'\120', (byte)'\121', (byte)'\122', (byte)'\123', (byte)'\124', (byte)'\125', (byte)'\126', (byte)'\127',
-            (byte)'\130', (byte)'\131', (byte)'\132', (byte)'\133', (byte)'\134', (byte)'\135', (byte)'\136', (byte)'\137',
-            (byte)'\140', (byte)'\101', (byte)'\102', (byte)'\103', (byte)'\104', (byte)'\105', (byte)'\106', (byte)'\107',
-            (byte)'\110', (byte)'\111', (byte)'\112', (byte)'\113', (byte)'\114', (byte)'\115', (byte)'\116', (byte)'\117',
-            (byte)'\120', (byte)'\121', (byte)'\122', (byte)'\123', (byte)'\124', (byte)'\125', (byte)'\126', (byte)'\127',
-            (byte)'\130', (byte)'\131', (byte)'\132', (byte)'\173', (byte)'\174', (byte)'\175', (byte)'\176', (byte)'\177',
-            (byte)'\200', (byte)'\201', (byte)'\202', (byte)'\203', (byte)'\204', (byte)'\205', (byte)'\206', (byte)'\207',
-            (byte)'\210', (byte)'\211', (byte)'\212', (byte)'\213', (byte)'\214', (byte)'\215', (byte)'\216', (byte)'\217',
-            (byte)'\220', (byte)'\221', (byte)'\222', (byte)'\223', (byte)'\224', (byte)'\225', (byte)'\226', (byte)'\227',
-            (byte)'\230', (byte)'\231', (byte)'\232', (byte)'\233', (byte)'\234', (byte)'\235', (byte)'\236', (byte)'\237',
-            (byte)'\240', (byte)'\241', (byte)'\242', (byte)'\243', (byte)'\244', (byte)'\245', (byte)'\246', (byte)'\247',
-            (byte)'\250', (byte)'\251', (byte)'\252', (byte)'\253', (byte)'\254', (byte)'\255', (byte)'\256', (byte)'\257',
-            (byte)'\260', (byte)'\261', (byte)'\262', (byte)'\263', (byte)'\264', (byte)'\265', (byte)'\266', (byte)'\267',
-            (byte)'\270', (byte)'\271', (byte)'\272', (byte)'\273', (byte)'\274', (byte)'\275', (byte)'\276', (byte)'\277',
-            (byte)'\300', (byte)'\301', (byte)'\302', (byte)'\303', (byte)'\304', (byte)'\305', (byte)'\306', (byte)'\307',
-            (byte)'\310', (byte)'\311', (byte)'\312', (byte)'\313', (byte)'\314', (byte)'\315', (byte)'\316', (byte)'\317',
-            (byte)'\320', (byte)'\321', (byte)'\322', (byte)'\323', (byte)'\324', (byte)'\325', (byte)'\326', (byte)'\327',
-            (byte)'\330', (byte)'\331', (byte)'\332', (byte)'\333', (byte)'\334', (byte)'\335', (byte)'\336', (byte)'\337',
-            (byte)'\340', (byte)'\341', (byte)'\342', (byte)'\343', (byte)'\344', (byte)'\345', (byte)'\346', (byte)'\347',
-            (byte)'\350', (byte)'\351', (byte)'\352', (byte)'\353', (byte)'\354', (byte)'\355', (byte)'\356', (byte)'\357',
-            (byte)'\360', (byte)'\361', (byte)'\362', (byte)'\363', (byte)'\364', (byte)'\365', (byte)'\366', (byte)'\367',
-            (byte)'\370', (byte)'\371', (byte)'\372', (byte)'\373', (byte)'\374', (byte)'\375', (byte)'\376', (byte)'\377',
-    };
-
-    public static final int LowerMap[][] = {
-            {0x41, 0x61},
-            {0x42, 0x62},
-            {0x43, 0x63},
-            {0x44, 0x64},
-            {0x45, 0x65},
-            {0x46, 0x66},
-            {0x47, 0x67},
-            {0x48, 0x68},
-            {0x49, 0x69},
-            {0x4a, 0x6a},
-            {0x4b, 0x6b},
-            {0x4c, 0x6c},
-            {0x4d, 0x6d},
-            {0x4e, 0x6e},
-            {0x4f, 0x6f},
-            {0x50, 0x70},
-            {0x51, 0x71},
-            {0x52, 0x72},
-            {0x53, 0x73},
-            {0x54, 0x74},
-            {0x55, 0x75},
-            {0x56, 0x76},
-            {0x57, 0x77},
-            {0x58, 0x78},
-            {0x59, 0x79},
-            {0x5a, 0x7a}
-    };
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,6 +30,5 @@
 
     public T p;
 
-    static final ObjPtr<Void> NULL = new ObjPtr<Void>();
 }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS".toCharArray(), WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.encoding;
-
-import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
-
-import java.util.HashMap;
-
-public class PosixBracket {
-
-    public static final char[][] PBSNamesLower = {
-            "alnum".toCharArray(),
-            "alpha".toCharArray(),
-            "blank".toCharArray(),
-            "cntrl".toCharArray(),
-            "digit".toCharArray(),
-            "graph".toCharArray(),
-            "lower".toCharArray(),
-            "print".toCharArray(),
-            "punct".toCharArray(),
-            "space".toCharArray(),
-            "upper".toCharArray(),
-            "xdigit".toCharArray(),
-            "ascii".toCharArray(),
-            "word".toCharArray()
-    };
-
-    public static final int PBSValues[] = {
-            CharacterType.ALNUM,
-            CharacterType.ALPHA,
-            CharacterType.BLANK,
-            CharacterType.CNTRL,
-            CharacterType.DIGIT,
-            CharacterType.GRAPH,
-            CharacterType.LOWER,
-            CharacterType.PRINT,
-            CharacterType.PUNCT,
-            CharacterType.SPACE,
-            CharacterType.UPPER,
-            CharacterType.XDIGIT,
-            CharacterType.ASCII,
-            CharacterType.WORD,
-    };
-
-    public static int propertyNameToCType(String name) {
-        name = name.toLowerCase();
-        if (!PBSTableUpper.containsKey(name)) {
-            throw new JOniException(ErrorMessages.ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
-        }
-        return PBSTableUpper.get(name);
-    }
-
-    private static final HashMap<String,Integer> PBSTableUpper = new HashMap<String,Integer>();
-
-    static {
-        for (int i=0; i<PBSValues.length; i++) PBSTableUpper.put(new String(PBSNamesLower[i]), PBSValues[i]);
-    }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/Ptr.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.encoding;
-
-public final class Ptr {
-    public Ptr() {
-        this(0);
-    }
-
-    public Ptr(int p) {
-        this.p = p;
-    }
-
-    public int p;
-
-    public static final Ptr NULL = new Ptr(0);
-}
-
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java	Wed Jul 05 18:57:52 2017 +0200
@@ -22,28 +22,16 @@
 import jdk.nashorn.internal.runtime.regexp.joni.Config;
 
 public interface ErrorMessages {
-    final String MISMATCH = "mismatch";
-    final String NO_SUPPORT_CONFIG = "no support in this configuration";
 
     /* from jcodings */
-    final String ERR_INVALID_CHAR_PROPERTY_NAME = "invalid character property name <%n>";
     final String ERR_INVALID_CODE_POINT_VALUE = "invalid code point value";
     final String ERR_TOO_BIG_WIDE_CHAR_VALUE = "too big wide-char value";
     final String ERR_TOO_LONG_WIDE_CHAR_VALUE = "too long wide-char value";
 
     /* internal error */
-    final String ERR_MEMORY = "fail to memory allocation";
-    final String ERR_MATCH_STACK_LIMIT_OVER = "match-stack limit over";
-    final String ERR_TYPE_BUG = "undefined type (bug)";
     final String ERR_PARSER_BUG = "internal parser error (bug)";
-    final String ERR_STACK_BUG = "stack error (bug)";
     final String ERR_UNDEFINED_BYTECODE = "undefined bytecode (bug)";
     final String ERR_UNEXPECTED_BYTECODE = "unexpected bytecode (bug)";
-    final String ERR_DEFAULT_ENCODING_IS_NOT_SETTED = "default multibyte-encoding is not setted";
-    final String ERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR = "can't convert to wide-char on specified multibyte-encoding";
-
-    /* general error */
-    final String ERR_INVALID_ARGUMENT = "invalid argument";
 
     /* syntax error */
     final String ERR_END_PATTERN_AT_LEFT_BRACE = "end pattern at left brace";
@@ -56,11 +44,9 @@
     final String ERR_META_CODE_SYNTAX = "invalid meta-code syntax";
     final String ERR_CONTROL_CODE_SYNTAX = "invalid control-code syntax";
     final String ERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE = "char-class value at end of range";
-    final String ERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE = "char-class value at start of range";
     final String ERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS = "unmatched range specifier in char-class";
     final String ERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED = "target of repeat operator is not specified";
     final String ERR_TARGET_OF_REPEAT_OPERATOR_INVALID = "target of repeat operator is invalid";
-    final String ERR_NESTED_REPEAT_OPERATOR = "nested repeat operator";
     final String ERR_UNMATCHED_CLOSE_PARENTHESIS = "unmatched close parenthesis";
     final String ERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS = "end pattern with unmatched parenthesis";
     final String ERR_END_PATTERN_IN_GROUP = "end pattern in group";
@@ -74,25 +60,14 @@
     final String ERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE = "too big number for repeat range";
     final String ERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE = "upper is smaller than lower in repeat range";
     final String ERR_EMPTY_RANGE_IN_CHAR_CLASS = "empty range in char class";
-    final String ERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE = "mismatch multibyte code length in char-class range";
     final String ERR_TOO_MANY_MULTI_BYTE_RANGES = "too many multibyte code ranges are specified";
     final String ERR_TOO_SHORT_MULTI_BYTE_STRING = "too short multibyte code string";
-    final String ERR_TOO_BIG_BACKREF_NUMBER = "too big backref number";
-    final String ERR_INVALID_BACKREF = Config.USE_NAMED_GROUP ? "invalid backref number/name" : "invalid backref number";
+    final String ERR_INVALID_BACKREF = "invalid backref number";
     final String ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED = "numbered backref/call is not allowed. (use name)";
-    final String ERR_INVALID_WIDE_CHAR_VALUE = "invalid wide-char value";
     final String ERR_EMPTY_GROUP_NAME = "group name is empty";
     final String ERR_INVALID_GROUP_NAME = "invalid group name <%n>";
-    final String ERR_INVALID_CHAR_IN_GROUP_NAME = Config.USE_NAMED_GROUP ? "invalid char in group name <%n>" : "invalid char in group number <%n>";
-    final String ERR_UNDEFINED_NAME_REFERENCE = "undefined name <%n> reference";
-    final String ERR_UNDEFINED_GROUP_REFERENCE = "undefined group <%n> reference";
-    final String ERR_MULTIPLEX_DEFINED_NAME = "multiplex defined name <%n>";
-    final String ERR_MULTIPLEX_DEFINITION_NAME_CALL = "multiplex definition name <%n> call";
-    final String ERR_NEVER_ENDING_RECURSION = "never ending recursion";
+    final String ERR_INVALID_CHAR_IN_GROUP_NAME = "invalid char in group number <%n>";
     final String ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY = "group number is too big for capture history";
-    final String ERR_NOT_SUPPORTED_ENCODING_COMBINATION = "not supported encoding combination";
     final String ERR_INVALID_COMBINATION_OF_OPTIONS = "invalid combination of options";
-    final String ERR_OVER_THREAD_PASS_LIMIT_COUNT = "over thread pass limit count";
-    final String ERR_TOO_BIG_SB_CHAR_VALUE = "too big singlebyte char value";
 
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java	Wed Jul 05 18:57:52 2017 +0200
@@ -30,8 +30,4 @@
         super(message.replaceAll("%n", str));
     }
 
-    public ValueException(String message, byte[]bytes, int p, int end) {
-        this(message, new String(bytes, p, end - p));
-    }
-
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -125,6 +125,7 @@
 type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
 type.error.method.not.constructor=Java method {0} can't be used as a constructor.
 type.error.env.not.object=$ENV must be an Object.
+type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
 range.error.inappropriate.array.length=inappropriate array length: {0}
 range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
 range.error.invalid.precision=precision argument toPrecision() must be in [1, 21]
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Wed Jul 05 18:57:52 2017 +0200
@@ -277,6 +277,12 @@
     desc="Print the symbol table." \
 }
 
+nashorn.option.range.analysis = { \
+    name="--range-analysis",      \
+    is_undocumented=true,         \
+    desc="Do range analysis using known compile time types, and try to narrow number types" \
+}    
+
 nashorn.option.D = {                                                          \
     name="-D",                                                                \
     desc="-Dname=value. Set a system property. This option can be repeated.", \
@@ -326,6 +332,15 @@
     type=TimeZone                              \
 }
 
+nashorn.option.locale = {                    \
+    name="--locale",                         \
+    short_name="-l",                         \
+    is_undocumented=true,                    \
+    params="<locale>",                       \
+    desc="Set Locale for script execution.", \
+    type=Locale                              \
+}
+
 nashorn.option.trace.callsites = {                                              \
     name="--trace-callsites",                                                   \
     short_name="-tcs",                                                          \
--- a/nashorn/src/netscape/javascript/JSObject.java	Thu May 30 10:58:13 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package netscape.javascript;
-
-import java.applet.Applet;
-
-/**
- * Stub for JSObject to get compilation going.
- */
-public abstract class JSObject {
-
-    /**
-     * Get the window for an {@link Applet}. Not supported
-     * by Nashorn
-     *
-     * @param a applet
-     * @return the window instance
-     */
-    public static JSObject getWindow(final Applet a) {
-        throw new UnsupportedOperationException("getWindow");
-    }
-
-    /**
-     * Call a JavaScript method
-     *
-     * @param methodName name of method
-     * @param args arguments to method
-     * @return result of call
-     */
-    public abstract Object call(String methodName, Object args[]);
-
-    /**
-     * Evaluate a JavaScript expression
-     *
-     * @param s JavaScript expression to evaluate
-     * @return evaluation result
-     */
-    public abstract Object eval(String s);
-
-    /**
-     * Retrieves a named member of a JavaScript object.
-     *
-     * @param name of member
-     * @return member
-     */
-    public abstract Object getMember(String name);
-
-    /**
-     * Retrieves an indexed member of a JavaScript object.
-     *
-     * @param index index of member slot
-     * @return member
-     */
-    public abstract Object getSlot(int index);
-
-    /**
-     * Remove a named member from a JavaScript object
-     *
-     * @param name name of member
-     */
-    public abstract void removeMember(String name);
-
-    /**
-     * Set a named member in a JavaScript object
-     *
-     * @param name  name of member
-     * @param value value of member
-     */
-    public abstract void setMember(String name, Object value);
-
-    /**
-     * Set an indexed member in a JavaScript object
-     *
-     * @param index index of member slot
-     * @param value value of member
-     */
-    public abstract void setSlot(int index, Object value);
-}
--- a/nashorn/test/script/basic/JDK-8008554.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/JDK-8008554.js	Wed Jul 05 18:57:52 2017 +0200
@@ -32,5 +32,5 @@
 var dir = __DIR__;
 var file = __FILE__.replace("JDK-8008554", "NASHORN-99");
 load(file);
-file = "file://" + __DIR__ + "NASHORN-99.js";
+file = "file:///" + __DIR__ + "NASHORN-99.js";
 load(file);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8010804.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8010804: Review long and integer usage conventions
+ *
+ * @test
+ * @run
+ */
+
+var x = [];
+print(x.length);
+x[4294967294] = 1;
+print(x.length);
+x[4294967295] = 1;
+print(x.length);
+print(x.slice(4294967293).length);
+print(x.slice(4294967294).length);
+print(x.slice(4294967295).length);
+print(x.slice(4294967296).length);
+
+print(x.slice(-4294967293).length);
+print(x.slice(-4294967294).length);
+print(x.slice(-4294967295).length);
+print(x.slice(-4294967296).length);
+
+print(x.slice(0, 4294967293).length);
+print(x.slice(0, 4294967294).length);
+print(x.slice(0, 4294967295).length);
+print(x.slice(0, 4294967296).length);
+
+print(x.slice(0, -4294967293).length);
+print(x.slice(0, -4294967294).length);
+print(x.slice(0, -4294967295).length);
+print(x.slice(0, -4294967296).length);
+
+print(x.slice(9223371036854775807).length);
+print(x.slice(9223372036854775807).length);
+print(x.slice(9223373036854775807).length);
+print(x.slice(9223374036854775807).length);
+
+print(x.slice(-9223371036854775807).length);
+print(x.slice(-9223372036854775807).length);
+print(x.slice(-9223373036854775807).length);
+print(x.slice(-9223374036854775807).length);
+
+print(x.slice(-9223371036854775807, 1).length);
+print(x.slice(-9223372036854775807, 1).length);
+print(x.slice(-9223373036854775807, 1).length);
+print(x.slice(-9223374036854775807, 1).length);
+
+print(x.slice(-9223371036854775807, -1).length);
+print(x.slice(-9223372036854775807, -1).length);
+print(x.slice(-9223373036854775807, -1).length);
+print(x.slice(-9223374036854775807, -1).length);
+
+print(x.slice(Infinity).length);
+print(x.slice(Infinity, Infinity).length);
+print(x.slice(Infinity, -Infinity).length);
+print(x.slice(-Infinity).length);
+print(x.slice(-Infinity, Infinity).length);
+print(x.slice(-Infinity, -Infinity).length);
+
+var d = new Date();
+d.setYear(Infinity);
+print(d);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8010804.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,42 @@
+0
+4294967295
+4294967295
+2
+1
+0
+0
+4294967293
+4294967294
+4294967295
+4294967295
+4294967293
+4294967294
+4294967295
+4294967295
+2
+1
+0
+0
+0
+0
+0
+0
+4294967295
+4294967295
+4294967295
+4294967295
+1
+1
+1
+1
+4294967294
+4294967294
+4294967294
+4294967294
+0
+0
+0
+4294967295
+4294967295
+0
+Invalid Date
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011023.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * Round should be ecma compliant
+ *
+ * @test
+ * @run 
+ */
+
+print(1/Math.round(-0.5));
+print(Math.round(9007199254740991));
+print(Math.round(9223372036854775807*2));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011023.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,3 @@
+-Infinity
+9007199254740991
+18446744073709552000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011718.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8011718: binding already bound function with extra arguments fails.
+ *
+ * @test
+ * @run
+ */
+
+var obj = { 
+    hello:"From obj", 
+}; 
+var obj2 = { 
+    hello:"From obj2", 
+}; 
+
+function doit(cb){ 
+    cb(); 
+    var cb2 = cb.bind(obj2, "This one is not acccepted"); 
+    cb2(); 
+} 
+
+doit(function(){ 
+        print(this.hello); 
+    }.bind(obj));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011718.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,2 @@
+From obj
+From obj
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8012083.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8012093 - array literals can only be subject to constant evaluation under very special
+ * circumstances.
+ *
+ * @test
+ * @run
+ */
+
+
+var w00t = 17;
+print(+[w00t]);
+
+var empty = [];
+print(empty == false);
+
+print([] == false);
+print([] === false);
+print(!![]);
+
+print(~[]);
+print(![]);
+print(![17]);
+print(![17,1,2]);
+
+var one = 1;
+var two = 2;
+var a1 = [one];
+var a2 = [two];
+print(+a1 + +a2); //3
+
+var x = 1;
+print(+["apa"]);
+print(+[]);  //0
+print(+[1]); //1
+print(+[x]); //1
+print(+[1,2,3]); //NaN
+var a = [];
+var b = [1];
+print(a/b);
+print(++[[]][+[]]+[+[]]); //10
+print(+[] == 0);
+
+var first = [![]+[]][+[]][+[]]+[![]+[]][+[]][+!+[]]+[!+[]+[]][+![]][+![]]+[![]+[]][+[]][+!+[]]+[![]+[]][+[]][+!+[]+!+[]];
+var second =(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
+
+print(first + " " + second);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8012083.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,19 @@
+17
+true
+true
+false
+true
+-1
+false
+false
+false
+3
+NaN
+0
+1
+1
+NaN
+0
+10
+true
+fatal fail
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8012305.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8012305: Function.bind can't be called on prototype function inside constructor 
+ *
+ * @test
+ * @run
+ */
+
+function MyObject() {
+    // If the call to bind is removed, then the function is properly printed.
+    print("function " + this._process);
+    this._process = this._process.bind(this);
+}
+
+MyObject.prototype._process = function() { print("Message "); }
+
+var s = new MyObject(); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8012305.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,1 @@
+function function() { print("Message "); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8013919.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8013913: finally cloning of function node declarations caused
+ * method collissions
+ *
+ * @test
+ * @run
+ */
+
+try {
+    print("a");
+} finally {
+    var b = function() {
+	print("b");
+    }
+    b();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8013919.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,2 @@
+a
+b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014426.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**
+ * Ensure catchall exceptions from finally inlining are rethrown as is
+ *
+ * @test
+ * @run
+ */
+
+function runScriptEngine() {
+    var fac    = new Packages.jdk.nashorn.api.scripting.NashornScriptEngineFactory();
+    var engine = fac.getScriptEngine();
+    engine.eval(
+"try {\n\
+  doIt();\n\
+} finally { \n\
+  var x = 17;\n\
+}\n\
+function doIt() {\n\
+  throw new TypeError('en stor graa noshoerning!');\n\
+}\n");
+}
+
+try {
+    runScriptEngine();
+} catch(e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014426.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,1 @@
+javax.script.ScriptException: TypeError: en stor graa noshoerning! in <eval> at line number 7 at column number 2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014647.js	Wed Jul 05 18:57:52 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.
+ * 
+ * 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-8014647: Allow class-based overrides to be initialized with a ScriptFunction
+ *
+ * @test
+ * @run
+ */
+
+var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
+var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
+var r1 = new RunnableImpl1()
+var r2 = new RunnableImpl2()
+var r3 = new RunnableImpl2(function() { print("I'm runnable 3!") })
+r1.run()
+r2.run()
+r3.run()
+print("r1.class === r2.class: " + (r1.class === r2.class))
+print("r2.class === r3.class: " + (r2.class === r3.class))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014647.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,5 @@
+I'm runnable 1!
+I'm runnable 2!
+I'm runnable 3!
+r1.class === r2.class: false
+r2.class === r3.class: true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014735.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8014735: Typed Array, BYTES_PER_ELEMENT should be a class property
+ *
+ * @test
+ * @run
+ */
+
+function bytesPerElement(func) {
+    print(func.name + ".BYTES_PER_ELEMENT = " + func.BYTES_PER_ELEMENT);
+}
+
+bytesPerElement(Int8Array);
+bytesPerElement(Int16Array);
+bytesPerElement(Int32Array);
+bytesPerElement(Uint8Array);
+bytesPerElement(Uint8ClampedArray);
+bytesPerElement(Uint16Array);
+bytesPerElement(Uint32Array);
+bytesPerElement(Float32Array);
+bytesPerElement(Float64Array);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014735.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,9 @@
+Int8Array.BYTES_PER_ELEMENT = 1
+Int16Array.BYTES_PER_ELEMENT = 2
+Int32Array.BYTES_PER_ELEMENT = 4
+Uint8Array.BYTES_PER_ELEMENT = 1
+Uint8ClampedArray.BYTES_PER_ELEMENT = 1
+Uint16Array.BYTES_PER_ELEMENT = 2
+Uint32Array.BYTES_PER_ELEMENT = 4
+Float32Array.BYTES_PER_ELEMENT = 4
+Float64Array.BYTES_PER_ELEMENT = 8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014953.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8014953: Have NativeJavaPackage throw a ClassNotFoundException when invoked with "new"
+ *
+ * @test
+ * @run
+ */
+ 
+try {
+    new java.util.ArrrayList(16)
+} catch(e) {
+   print("Invoked as constructor");
+   print("e.class=" + e.class)
+   print("e.message=" + e.message);
+}
+
+try {
+    java.util.ArrrayList(16)
+} catch(e) {
+   print("Invoked as method");
+   print("e.class=" + e.class)
+   print("e.message=" + e.message);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014953.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,6 @@
+Invoked as constructor
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList
+Invoked as method
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015267.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8015267: have a List/Deque adapter for JS array-like objects
+ *
+ * @test
+ * @run
+ */
+ 
+var a = ['a', 'b', 'c', 'd']
+
+var l = Java.to(a, java.util.List)
+print(l instanceof java.util.List)
+print(l instanceof java.util.Deque)
+
+print(l[0])
+print(l[1])
+print(l[2])
+print(l[3])
+
+print(l.size())
+
+l.push('x')
+print(a)
+
+l.addLast('y')
+print(a)
+
+print(l.pop())
+print(l.removeLast())
+print(a)
+
+l.add('e')
+l.add(5, 'f')
+print(a)
+
+l.add(0, 'z')
+print(a)
+
+l.add(2, 'x')
+print(a)
+
+l[7] = 'g'
+print(a)
+
+try { l.add(15, '') } catch(e) { print(e.class) } 
+try { l.remove(15) } catch(e) { print(e.class) } 
+try { l.add(-1, '') } catch(e) { print(e.class) } 
+try { l.remove(-1) } catch(e) { print(e.class) } 
+
+l.remove(7)
+l.remove(2)
+l.remove(0)
+print(a)
+
+print(l.peek())
+print(l.peekFirst())
+print(l.peekLast())
+
+print(l.element())
+print(l.getFirst())
+print(l.getLast())
+
+l.offer('1')
+l.offerFirst('2')
+l.offerLast('3')
+print(a)
+
+a = ['1', '2', 'x', '3', '4', 'x', '5', '6', 'x', '7', '8']
+print(a)
+var l = Java.to(a, java.util.List)
+l.removeFirstOccurrence('x')
+print(a)
+l.removeLastOccurrence('x')
+print(a)
+
+var empty = Java.to([], java.util.List)
+try { empty.pop() } catch(e) { print(e.class) }
+try { empty.removeFirst() } catch(e) { print(e.class) }
+try { empty.removeLast() } catch(e) { print(e.class) }
+
+try { empty.element() } catch(e) { print(e.class) }
+try { empty.getFirst() } catch(e) { print(e.class) }
+try { empty.getLast() } catch(e) { print(e.class) }
+
+print(empty.peek())
+print(empty.peekFirst())
+print(empty.peekLast())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015267.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,40 @@
+true
+true
+a
+b
+c
+d
+4
+x,a,b,c,d
+x,a,b,c,d,y
+x
+y
+a,b,c,d
+a,b,c,d,e,f
+z,a,b,c,d,e,f
+z,a,x,b,c,d,e,f
+z,a,x,b,c,d,e,g
+class java.lang.IndexOutOfBoundsException
+class java.lang.IndexOutOfBoundsException
+class java.lang.IndexOutOfBoundsException
+class java.lang.IndexOutOfBoundsException
+a,b,c,d,e
+a
+a
+e
+a
+a
+e
+2,a,b,c,d,e,1,3
+1,2,x,3,4,x,5,6,x,7,8
+1,2,3,4,x,5,6,x,7,8
+1,2,3,4,x,5,6,7,8
+class java.util.NoSuchElementException
+class java.util.NoSuchElementException
+class java.util.NoSuchElementException
+class java.util.NoSuchElementException
+class java.util.NoSuchElementException
+class java.util.NoSuchElementException
+null
+null
+null
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015348.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8015348: RegExp("[") results in StackOverflowError
+ *
+ * @test
+ * @run
+ */
+
+try {
+    new RegExp('[');
+} catch (error) {
+    print(error.name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015348.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,1 @@
+SyntaxError
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015349.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8015349: "abc".lastIndexOf("a",-1) should evaluate to 0 and not -1
+ *
+ * @test
+ * @run
+ */
+
+function printEval(code) {
+    print(code + " = " + eval(code));
+}
+
+printEval("'abc'.lastIndexOf('a', 4)"); 
+printEval("'abc'.lastIndexOf('b', Infinity)");
+printEval("'abc'.lastIndexOf('a', -1)");
+printEval("'abc'.lastIndexOf('a', -Infinity)");
+printEval("'oracle'.lastIndexOf('u')");
+printEval("'hello'.lastIndexOf('l')");
+printEval("'hello'.lastIndexOf('l', 2)");
+printEval("'hello'.lastIndexOf('l', 3)");
+printEval("'hello'.lastIndexOf('l', 1)");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015349.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,9 @@
+'abc'.lastIndexOf('a', 4) = 0
+'abc'.lastIndexOf('b', Infinity) = 1
+'abc'.lastIndexOf('a', -1) = 0
+'abc'.lastIndexOf('a', -Infinity) = 0
+'oracle'.lastIndexOf('u') = -1
+'hello'.lastIndexOf('l') = 3
+'hello'.lastIndexOf('l', 2) = 2
+'hello'.lastIndexOf('l', 3) = 3
+'hello'.lastIndexOf('l', 1) = -1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015352.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8015352: "i".toUpperCase() => currently returns "Ä°", but should be "I" (with Turkish locale)
+ *
+ * @test
+ * @option --locale=tr-TR
+ * @run
+ */
+
+if ("i".toUpperCase() != "I") {
+    fail("'i'.toUpperCase() is not 'I'");
+}
+
+if ("i".toUpperCase() == "i".toLocaleUpperCase()) {
+    fail("'i'.toUpperCase() == 'i'.toLocaleUpperCase()");
+}
+
+if ("I".toLowerCase() != "i") {
+    fail("'I'.toLowerCase() is not 'i'");
+}
+
+if ("I".toLowerCase() == "I".toLocaleLowerCase()) {
+    fail("'i'.toLowerCase() == 'i'.toLocaleLowerCase()");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015354.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead 
+ *
+ * @test
+ * @run
+ */
+
+Object.defineProperty(Object.prototype,
+    "", {
+    set: function(v) {
+        throw "set called";
+    }
+});
+
+JSON.parse('{}',function(){});
+
+Object.defineProperty(Object.prototype,
+    "foo",{
+    set: function(v) {
+        throw "set called";
+    }
+});
+JSON.parse('{"foo": 1}');
--- a/nashorn/test/script/basic/NASHORN-377.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/NASHORN-377.js	Wed Jul 05 18:57:52 2017 +0200
@@ -43,7 +43,7 @@
 function arrstr(a, n, w) {
   var s = "";
   if (typeof n == "undefined") n = a.length;
-  if (typeof w == "undefined") w = a.BYTES_PER_ELEMENT * 2;
+  if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
   for (var i = 0; i < n; i++) {
     s += tohex(a[i], w);
   }
@@ -96,7 +96,7 @@
   var b = new ArrayBuffer(8);
   for (var i in types) {
     var x = new types[i](b);
-    print(x.byteOffset, x.byteLength, x.length, x.BYTES_PER_ELEMENT);
+    print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
     assertTrue(function(){ return x.constructor === types[i] });
   }
 })();
--- a/nashorn/test/script/basic/NASHORN-556.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/NASHORN-556.js	Wed Jul 05 18:57:52 2017 +0200
@@ -47,7 +47,7 @@
   // (NoTypeArrayData)
   var empty = {};
   empty.length = 10;
-  Java.toJavaArray(empty);
+  Java.to(empty);
   delete empty[0];
   Array.prototype.slice.call(empty, 0, 1);
   Array.prototype.pop.call(empty);
@@ -63,7 +63,7 @@
 function f2() {
   // DeletedArrayFilter
   var deleted = [,1,,2,,3,,4,,];
-  assertEq(2, Java.toJavaArray(deleted)[3]);
+  assertEq(2, Java.to(deleted)[3]);
   assertEq(undefined, deleted.pop());
   assertEq(4, deleted.pop());
   deleted.unshift(5);
@@ -78,7 +78,7 @@
 function f3() {
   // DeletedRangeArrayFilter
   var delrange = [1,2,3,,,,,,,,,,];
-  Java.toJavaArray(delrange);
+  Java.to(delrange);
   delrange.unshift(4);
   p.apply(null, delrange);
   print(delrange.slice(1,3), delrange.slice(2,6));
@@ -88,7 +88,7 @@
 function f4() {
   // NumberArrayData
   var num = [1.1,2.2,3.3,4.4,5.5];
-  Java.toJavaArray(num);
+  Java.to(num);
   assertEq(2, num[3] >>> 1);
   assertEq(5, num[4] | 0);
   assertEq(5.5, num.pop());
@@ -104,7 +104,7 @@
 function f5() {
   // ObjectArrayData
   var obj = [2,"two",3.14,"pi",14,"fourteen"];
-  Java.toJavaArray(obj);
+  Java.to(obj);
   assertEq(-12.86, obj[2] - 16);
   assertEq(7, obj[4] >>> 1);
   obj.unshift("one");
@@ -131,14 +131,14 @@
   sparse.length = 1024*1024;
   sparse.push(sparse.length);
   delete sparse[sparse.length-1];
-  //print(Java.toJavaArray(sparse).length);
+  //print(Java.to(sparse).length);
   (function(){}).apply(null, sparse);
 }
 
 function f7() {
   // UndefinedArrayFilter
   var undef = [1,2,3,4,5,undefined,7,8,9,19];
-  Java.toJavaArray(undef);
+  Java.to(undef);
   assertEq(4, undef[8] >>> 1);
   var tmp = undef[9] >>> 1;
   undef[8] = tmp;
@@ -154,8 +154,8 @@
 
 function f8() {
   // LongArrayData
-  var j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
-  Java.toJavaArray(j);
+  var j = Java.from(Java.to([23,37,42,86,47], "long[]"));
+  Java.to(j);
   p.apply(null, j);
   assertEq(43, j[3] >>> 1);
   assertEq(36, j[4] - 11);
@@ -164,12 +164,12 @@
   assertEq(7, j.shift());
   assertEq(47, j.pop());
   j.push("asdf");
-  j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+  j = Java.from(Java.to([23,37,42,86,47], "long[]"));
   j.length = 3;
   j[0] = 13;
-  j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+  j = Java.from(Java.to([23,37,42,86,47], "long[]"));
   delete j[0];
-  j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+  j = Java.from(Java.to([23,37,42,86,47], "long[]"));
   j.length = 20;
   j[0] = 13.37;
 }
--- a/nashorn/test/script/basic/allgettersetters.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/allgettersetters.js	Wed Jul 05 18:57:52 2017 +0200
@@ -34,6 +34,9 @@
         for (var i in properties) {
             var prop = properties[i];
             try {
+                if (!/\d.*/.test(prop)) {
+                    eval("obj." + prop + " = " + "obj." + prop + ";");
+                }
                 obj[prop] = obj[prop];
             } catch (e) {
                 if (!expectError || !(e instanceof TypeError)) {
--- a/nashorn/test/script/basic/compile-octane.js.EXPECTED	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/compile-octane.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -1,39 +1,13 @@
-Compiling... box2d.js
-Compiled OK: box2d.js
-
-Compiling... code-load.js
-Compiled OK: code-load.js
-
-Compiling... crypto.js
-Compiled OK: crypto.js
-
-Compiling... deltablue.js
-Compiled OK: deltablue.js
-
-Compiling... earley-boyer.js
-Compiled OK: earley-boyer.js
-
-Compiling... gbemu.js
-Compiled OK: gbemu.js
-
-Compiling... mandreel.js
-Compiled OK: mandreel.js
-
-Compiling... navier-stokes.js
-Compiled OK: navier-stokes.js
-
-Compiling... pdfjs.js
-Compiled OK: pdfjs.js
-
-Compiling... raytrace.js
-Compiled OK: raytrace.js
-
-Compiling... regexp.js
-Compiled OK: regexp.js
-
-Compiling... richards.js
-Compiled OK: richards.js
-
-Compiling... splay.js
-Compiled OK: splay.js
-
+Compiled OK: box2d
+Compiled OK: code-load
+Compiled OK: crypto
+Compiled OK: deltablue
+Compiled OK: earley-boyer
+Compiled OK: gbemu
+Compiled OK: mandreel
+Compiled OK: navier-stokes
+Compiled OK: pdfjs
+Compiled OK: raytrace
+Compiled OK: regexp
+Compiled OK: richards
+Compiled OK: splay
--- a/nashorn/test/script/basic/javaarrayconversion.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/javaarrayconversion.js	Wed Jul 05 18:57:52 2017 +0200
@@ -34,7 +34,7 @@
 var testCount = 0;
 
 function testF(inputValue, type, testFn) {
-  var x = Java.toJavaArray([inputValue], type)[0];
+  var x = Java.to([inputValue], type + "[]")[0];
   if(!testFn(x)) {
     throw ("unexpected value: " + x)
   }
@@ -130,7 +130,7 @@
 
 function assertCantConvert(sourceType, targetType) {
   try {
-    Java.toJavaArray([new Java.type(sourceType)()], targetType)
+    Java.to([new Java.type(sourceType)()], targetType + "[]")
     throw "no TypeError encountered"
   } catch(e) {
       if(!(e instanceof TypeError)) {
@@ -164,7 +164,7 @@
 intArray[0] = 1234;
 intArray[1] = 42;
 intArray[2] = 5;
-var jsIntArray = Java.toJavaScriptArray(intArray)
+var jsIntArray = Java.from(intArray)
 assert(jsIntArray instanceof Array);
 assert(jsIntArray[0] === 1234);
 assert(jsIntArray[1] === 42);
@@ -179,7 +179,7 @@
 var byteArray = new (Java.type("byte[]"))(2)
 byteArray[0] = -128;
 byteArray[1] = 127;
-var jsByteArray = Java.toJavaScriptArray(byteArray)
+var jsByteArray = Java.from(byteArray)
 assert(jsByteArray instanceof Array);
 assert(jsByteArray[0] === -128);
 assert(jsByteArray[1] === 127);
@@ -187,7 +187,7 @@
 var shortArray = new (Java.type("short[]"))(2)
 shortArray[0] = -32768;
 shortArray[1] = 32767;
-var jsShortArray = Java.toJavaScriptArray(shortArray)
+var jsShortArray = Java.from(shortArray)
 assert(jsShortArray instanceof Array);
 assert(jsShortArray[0] === -32768);
 assert(jsShortArray[1] === 32767);
@@ -195,7 +195,7 @@
 var floatArray = new (Java.type("float[]"))(2)
 floatArray[0] = java.lang.Float.MIN_VALUE;
 floatArray[1] = java.lang.Float.MAX_VALUE;
-var jsFloatArray = Java.toJavaScriptArray(floatArray)
+var jsFloatArray = Java.from(floatArray)
 assert(jsFloatArray instanceof Array);
 assert(jsFloatArray[0] == java.lang.Float.MIN_VALUE);
 assert(jsFloatArray[1] == java.lang.Float.MAX_VALUE);
@@ -204,7 +204,7 @@
 charArray[0] = "a";
 charArray[1] = "b";
 charArray[2] = "1";
-var jsCharArray = Java.toJavaScriptArray(charArray)
+var jsCharArray = Java.from(charArray)
 assert(jsCharArray instanceof Array);
 assert(jsCharArray[0] === 97);
 assert(jsCharArray[1] === 98);
@@ -213,7 +213,7 @@
 var booleanArray = new (Java.type("boolean[]"))(2)
 booleanArray[0] = true;
 booleanArray[1] = false;
-var jsBooleanArray = Java.toJavaScriptArray(booleanArray)
+var jsBooleanArray = Java.from(booleanArray)
 assert(jsBooleanArray instanceof Array);
 assert(jsBooleanArray[0] === true);
 assert(jsBooleanArray[1] === false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/ranges_disabled.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @test 
+ * @run 
+ */
+
+load(__DIR__ + "ranges_payload.js");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/ranges_disabled.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,4 @@
+289
+11094405
+4294967293
+-4722
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/ranges_enabled.js	Wed Jul 05 18:57:52 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @test
+ * @option --range-analysis
+ * @run 
+ */
+
+load(__DIR__ + "ranges_payload.js");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/ranges_enabled.js.EXPECTED	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,4 @@
+289
+11094405
+4294967293
+-4722
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/ranges_payload.js	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @subtest
+ */
+
+function f(c) {
+    var v = c & 0xffff;
+    var w = v & 0xfff;
+    var x = v * w;
+    return x;
+}
+
+function g() {
+    var sum = 0;
+    for (var x = 0; x < 4711; x++) {
+	sum += x;
+    }
+    return sum;
+}
+
+function g2() {
+    var sum = 0;
+    //make sure we overflow
+    var displacement = 0x7ffffffe;
+    for (var x = displacement; x < (displacement + 2); x++) {
+	sum += x;
+    }
+    return sum;
+}
+
+//mostly provide code coverage for all the range operations    
+function h() {
+    var sum = 0;
+    sum += 4711;
+    sum &= 0xffff;
+    sum /= 2;
+    sum *= 2;
+    sum -= 4;
+    sum |= 2;
+    sum ^= 17;
+    sum = sum % 10000;
+    sum = -sum;
+    return sum
+}
+
+print(f(17));
+print(g());
+print(g2());
+print(h());
--- a/nashorn/test/script/basic/run-octane.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/basic/run-octane.js	Wed Jul 05 18:57:52 2017 +0200
@@ -26,36 +26,20 @@
  */
 
 var tests = [
-    "box2d.js",
-    "code-load.js",
-    "crypto.js", 
-    "deltablue.js", 
-    "earley-boyer.js", 
-    "gbemu.js",
-    "mandreel.js",
-    "navier-stokes.js", 
-    "pdfjs.js",
-    "raytrace.js",
-    "regexp.js", 
-    "richards.js", 
-    "splay.js" 
+    {file:"box2d",suite:"Box2DBenchmark"},
+    {file:"code-load",suite:"CodeLoad"},
+    {file:"crypto",suite:"Crypto"},
+    {file:"deltablue",suite:"DeltaBlue"},
+    {file:"earley-boyer", suite:"EarleyBoyer"},
+    {file:"gbemu", suite:"GameboyBenchmark"},
+    {file:"mandreel", suite:"MandreelBenchmark"},
+    {file:"navier-stokes", suite:"NavierStokes"},
+    {file:"pdfjs", suite:"PdfJS"},
+    {file:"raytrace", suite:"RayTrace"},
+    {file:"regexp", suite:"RegExpSuite"},
+    {file:"richards", suite:"Richards"},
+    {file:"splay", suite:"Splay"}
 ];
-
-// hack, teardown breaks things defined in the global space, making it impossible
-// to do multiple consecutive benchmark runs with the same harness. I think it's a bug
-// that the setup and teardown aren't each others constructor and destructor but rather
-// that the benchmarks rely on partial global state. For shame, Octane! 
-var ignoreTeardown = [
-    { name: "box2d.js" },
-    { name: "gbemu.js" },
-];
-
-
-//TODO mandreel can be compiled as a test, but not run multiple times unless modified to not have global state
-var compileOnly = {
-    "mandreel.js" : true
-};
-
 var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
 
 // TODO: why is this path hard coded when it's defined in project properties?
@@ -71,110 +55,106 @@
 }
 
 function should_compile_only(name) {
-    return (typeof compile_only !== 'undefined') || compileOnly[name] === true;
+    return (typeof compile_only !== 'undefined')
 }
 
 function run_one_benchmark(arg, iters) {
-
     var file_name;
-    var file = arg.split('/');
-    if (file.length == 1) {
-        file = arg.split('\\');
-    }    
-
-    //trim off trailing path separators
-    while (file[file.length - 1].indexOf(".js") == -1) {
-	file.pop();
-    }
-    file_name = file[file.length - 1];
-
+    var file = (arg.file + ".js").split('/');
+    
+    file_name = path + file[file.length - 1];
+    
     var compile_and_return = should_compile_only(file_name);
     if (compile_and_return) {
 	if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
 	    return;
 	}
-	print("Compiling... " + file_name);
     }
-
-    load(path + 'base.js');
-    load(arg);
+    
+    print_verbose("Loading... " + file_name);
+    load(file_name);
     
     if (compile_and_return) {
-	print("Compiled OK: " + file_name);
-	print("");
+	print_always("Compiled OK: " + arg.file);
 	return;
     }
     
     var success = true;
-    var hiscore = 0;
-    var loscore = 10e8;
     var current_name;
     
-    function PrintResult(name, result) {
-	current_name = name;
-    }
-        
-    function PrintError(name, error) {
-	current_name = name;
-	PrintResult(name, error);
-	success = false;
-    }
-        
-    function PrintScore(score) {
-	if (success) {
-	    if (+score >= hiscore) {
-		hiscore = +score;
-	    }
-	    if (+score <= loscore) {
-		loscore = +score;
-	    }
-	}
-
-	if (verbose) {
-	    print("Score: " + score);
-	}
-    }
-    
     if (iters == undefined) {
 	iters = numberOfIterations;
     } else {
 	numberOfIterations = iters;
     }
-
-    print(runtime + ": running " + file_name + "...");
-
-    for (var i = 0; i < numberOfIterations; i++) {
-	var callbacks =
-	    { NotifyResult: PrintResult,
-	      NotifyError: PrintError,
-	      NotifyScore: PrintScore };	
-
-	for (j in ignoreTeardown) {
-	    var ignore = ignoreTeardown[j];
-	    if (endsWith(arg, ignore.name)) {
-		var teardownOverride = ignore.teardown;
-		if (!teardownOverride) {
-		    teardownOverride = function() {};
-		}
+    
+    var benchmarks = eval(arg.suite + ".benchmarks");
+    var min_score  = 1e9;
+    var max_score  = 0;
+    var mean_score = 0;
 
-		for (k in BenchmarkSuite.suites) {
-		    var benchmarks = BenchmarkSuite.suites[k].benchmarks;
-		    for (l in benchmarks) {
-			benchmarks[l].TearDown = teardownOverride;
-		    }
-                }
-		break;
-	    }
+    try {
+	for (var x = 0; x < benchmarks.length ; x++) { 
+	    benchmarks[x].Setup();
+	}
+	print_verbose("Running '" + arg.file + "' for " + iters + " iterations of no less than " + min_time + " seconds (" + runtime + ")");
+	
+	var scores = [];
+	
+	var min_time_ms = min_time * 1000;
+	var len = benchmarks.length;    
+	
+	for (var it = 0; it < iters + 1; it++) {
+	    //every iteration must take a minimum of 10 secs
+	    var ops = 0;
+	    var elapsed = 0;
+	    var start = new Date;
+	    do {
+		for (var i = 0; i < len; i++) {
+		    benchmarks[i].run();
+		}	    
+		ops += len;
+		elapsed = new Date - start;
+	    } while (elapsed < min_time * 1000);
+	    
+	    var score = ops / elapsed * 1000 * 60;
+	    scores.push(score);
+	    var name = it == 0 ? "warmup" : "iteration " + it;   
+	    print_verbose("[" + arg.file + "] " + name + " finished " + score.toFixed(0) + " ops/minute");
 	}
-	
-	BenchmarkSuite.RunSuites(callbacks);
+
+	for (var x = 0; x < benchmarks.length ; x++) { 
+	    benchmarks[x].TearDown();
+	}
+
+	for (var x = 1; x < iters + 1 ; x++) {
+	    mean_score += scores[x];
+	    min_score = Math.min(min_score, scores[x]);
+	    max_score = Math.max(max_score, scores[x]);
+	}
+	mean_score /= iters;    
+
+    } catch (e) {
+	print_always("*** Aborted and setting score to zero. Reason: " + e);
+	mean_score = min_score = max_score = 0;
+	scores = [0];
     }
-    
-    var start = "Score: ";
-    if (runtime != "") {
-	start = runtime + ": ";
-    } 
-    print(start + current_name + ' (version ' + BenchmarkSuite.version + '): ' + loscore + '-' + hiscore);
+
+    var res = "[" + arg.file + "] " + mean_score.toFixed(0);
+    if (verbose) {
+	res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
+    }
+    print_always(res);
+}
+
+function print_always(x) {
+    print(x);
+}
+
+function print_verbose(x) {
+    if (verbose) {
+	print(x);
+    }
 }
 
 function run_suite(tests, iters) {
@@ -186,6 +166,7 @@
 runtime = "command line";
 
 var args = [];
+
 if (typeof $ARGS !== 'undefined') {
     args = $ARGS;
 } else if (typeof arguments !== 'undefined' && arguments.length != 0) {
@@ -211,6 +192,7 @@
 
 var tests_found = [];
 var iters = undefined;
+var min_time = 5;
 
 for (var i = 0; i < args.length; i++) { 
     arg = args[i];
@@ -220,21 +202,41 @@
 	runtime = args[++i];
     } else if (arg == "--verbose") {
 	verbose = true;
+    } else if (arg == "--min-time") {
+	min_time = +args[++i];
     } else if (arg == "") {
 	continue; //skip
     } else {
-	tests_found.push(arg);
+	var found = false;
+	for (j in tests) {
+	    if (tests[j].file === arg) {
+		tests_found.push(tests[j]);
+		found = true;
+		break;
+	    }
+	}
+	if (!found) {
+	    var str = "unknown test name: '" + arg + "' -- valid names are: ";
+	    for (j in tests) {
+		if (j != 0) {
+		    str += ", ";
+		}
+		str += "'" + tests[j].file + "'";
+	    }
+	    throw str;
+	}
     }
 }
 
 if (tests_found.length == 0) {    
     for (i in tests) {
-	tests_found.push(path + tests[i]);
+	tests_found.push(tests[i]);
     }
 } 
 
 tests_found.sort();
 
+load(path + 'base.js');
 run_suite(tests_found, iters);
 
 
--- a/nashorn/test/script/currently-failing/logcoverage.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/currently-failing/logcoverage.js	Wed Jul 05 18:57:52 2017 +0200
@@ -53,8 +53,7 @@
             // set new standard err
             System.setErr(newErr);
             System.setOut(newOut);
-            var strType = Java.type("java.lang.String");
-            var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+            var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
 	    var reader = new java.io.FileReader(name);
             engine.eval(reader);
             newErr.flush();
--- a/nashorn/test/script/trusted/NASHORN-638.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/trusted/NASHORN-638.js	Wed Jul 05 18:57:52 2017 +0200
@@ -47,8 +47,7 @@
         try {
             // set new standard err
             System.setErr(newErr);
-            var strType = Java.type("java.lang.String");
-            var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+            var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
             engine.eval(code);
             newErr.flush();
             return new java.lang.String(baos.toByteArray());
--- a/nashorn/test/script/trusted/NASHORN-653.js	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/script/trusted/NASHORN-653.js	Wed Jul 05 18:57:52 2017 +0200
@@ -85,8 +85,7 @@
         try {
             // set new standard err
             System.setErr(newErr);
-            var strType = Java.type("java.lang.String");
-            var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+            var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
             engine.eval(code);
             newErr.flush();
             return new java.lang.String(baos.toByteArray());
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Thu May 30 10:58:13 2013 -0700
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -47,7 +47,6 @@
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 import javax.script.SimpleScriptContext;
-import netscape.javascript.JSObject;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.runtime.regexp;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import jdk.nashorn.internal.runtime.ParserException;
+import org.testng.annotations.Test;
+
+/**
+ * Basic tests for the JDK based RegExp implementation.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.regexp.JdkRegExpTest
+ */
+public class JdkRegExpTest {
+
+    /**
+     * Compile a regular expression using the JDK implementation
+     */
+    @Test
+    public void testMatcher() {
+        RegExp regexp = new RegExpFactory().compile("f(o)o", "");
+        RegExpMatcher matcher = regexp.match("foo");
+        assertNotNull(matcher);
+        assertTrue(matcher.search(0));
+        assertEquals(matcher.getInput(), "foo");
+        assertEquals(matcher.groupCount(), 1);
+        assertEquals(matcher.group(), "foo");
+        assertEquals(matcher.start(), 0);
+        assertEquals(matcher.end(), 3);
+        assertEquals(matcher.group(1), "o");
+        assertEquals(matcher.start(1), 1);
+        assertEquals(matcher.end(1), 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java	Wed Jul 05 18:57:52 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.runtime.regexp.joni;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+/**
+ * Joni coverage tests
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest
+ */
+public class JoniTest {
+
+    @Test
+    public void testDump() {
+        new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpTree();
+        new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpByteCode();
+        new Regex("(abc){4,}{2,5}").dumpTree();
+        new Regex("(abc){4,}{2,5}").dumpByteCode();
+        new Regex("aaa|aa|bbbb|ccc").dumpTree();
+        new Regex("aaa|aa|bbbb|ccc").dumpByteCode();
+        new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpTree();
+        new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpByteCode();
+    }
+}