--- a/.hgtags-top-repo Mon Jun 03 23:19:23 2013 -0700
+++ b/.hgtags-top-repo Wed Jul 05 18:57:48 2017 +0200
@@ -213,3 +213,4 @@
892a0196d10c67f3a12f0eefb0bb536e423d8868 jdk8-b89
69b773a221b956a3386933ecdbfeccee0edeac47 jdk8-b90
cb51fb4789ac0b8be4056482077ddfb8f3bd3805 jdk8-b91
+3a36c926a7aafa9d4a892a45ef3678e87ad8359b jdk8-b92
--- a/common/autoconf/basics.m4 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/basics.m4 Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/basics_windows.m4 Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/build-performance.m4 Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/generated-configure.sh Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/jdk-options.m4 Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/spec.gmk.in Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/autoconf/toolchain.m4 Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/makefiles/Jprt.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/makefiles/Main.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/makefiles/MakeBase.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/common/makefiles/NativeCompilation.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/corba/.hgtags Wed Jul 05 18:57:48 2017 +0200
@@ -213,3 +213,4 @@
fe4150590ee597f4e125fea950aa3b352622cc2d jdk8-b89
c8286839d0df04aba819ec4bef12b86babccf30e jdk8-b90
8f7ffb296385f85a4a6d53f9f2d4a7b13a8fa1ff jdk8-b91
+717aa26f8e0a1c0e768aebb3a763aca56db0c83e jdk8-b92
--- a/hotspot/.hgtags Mon Jun 03 23:19:23 2013 -0700
+++ b/hotspot/.hgtags Wed Jul 05 18:57:48 2017 +0200
@@ -345,3 +345,4 @@
b19517cecc2e91636d7c16ba2f35e3d3dc628099 hs25-b33
7cbdf0e3725c0c56a2ff7540fc70b6d4b5890d04 jdk8-b91
38da9f4f67096745f851318d792d6468aa1f6cf8 hs25-b34
+092018493d3bbeb1c24278fd8c40ff3d76e1fed7 jdk8-b92
--- a/jdk/.hgtags Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/.hgtags Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/make/common/Defs-windows.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/make/jpda/back/Makefile Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/make/sun/awt/FILES_c_unix.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/make/sun/awt/FILES_export_unix.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/make/sun/awt/mawt.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/makefiles/CompileLaunchers.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/makefiles/CompileNativeLibraries.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/makefiles/Images.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/bin/java_md_macosx.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/macosx/native/sun/font/AWTFont.m Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/io/FileInputStream.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/io/InputStream.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ref/Reference.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/Arrays.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/ComparableTimSort.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/ListResourceBundle.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/PropertyResourceBundle.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/TimSort.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiPredicate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BooleanSupplier.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Consumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoublePredicate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Function.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntPredicate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntSupplier.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongPredicate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongSupplier.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Predicate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Supplier.java Wed Jul 05 18:57:48 2017 +0200
@@ -40,5 +40,5 @@
*
* @return an object
*/
- public T get();
+ T get();
}
--- a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/JToolTip.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/View.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/management/Agent.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/management/jdp/package-info.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/Resources.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/native/java/io/FileInputStream.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/bin/arm/jvm.cfg Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.h Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/bin/cmdtoargs.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/Makefile Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/ProblemList.txt Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/awt/WMSpecificTests/Metacity/FullscreenDialogModality.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java Wed Jul 05 18:57:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/io/File/IsHidden.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/NegativeAvailable.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/io/pathNames/General.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/io/pathNames/GeneralWin32.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/lang/StringBuffer/ToStringCache.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Wed Jul 05 18:57:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/nio/file/Files/PassThroughFileSystem.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/java/util/Arrays/ParallelSorting.java Wed Jul 05 18:57:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/sun/management/jdp/JdpTest.sh Wed Jul 05 18:57:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleData Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/make/deploy-rules.gmk Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/.hgignore Wed Jul 05 18:57:48 2017 +0200
@@ -24,3 +24,4 @@
.idea/*
test/lib/testng.jar
test/script/external/*
+.project
--- a/nashorn/.hgtags Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/.hgtags Wed Jul 05 18:57:48 2017 +0200
@@ -201,3 +201,4 @@
45ce27fbe2720d80070095c0db7344ec41e2833d jdk8-b89
67ca019e3713dd71c884d753de02fd0021981969 jdk8-b90
6b9f4120380091b8b1751a825b9f84bf1be224fe jdk8-b91
+dee23cce5235b594a96d3361b65eacc97bd5a583 jdk8-b92
--- a/nashorn/docs/JavaScriptingProgrammersGuide.html Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/docs/JavaScriptingProgrammersGuide.html Wed Jul 05 18:57:48 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 – passing an implementation JavaScript object
+or function to a constructor, or using <code>Java.extend</code> with <code>new</code> – 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> – aside from being able to take any number of type parameters
+denoting a class to extend and interfaces to implement – 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 – 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 – 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 – 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 – 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. – 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/docs/source/javaarray.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/make/build-benchmark.xml Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/make/build.xml Wed Jul 05 18:57:48 2017 +0200
@@ -212,7 +212,9 @@
target="${javac.target}"
debug="${javac.debug}"
encoding="${javac.encoding}"
- includeantruntime="false"/>
+ includeantruntime="false">
+ <compilerarg line="-extdirs """/>
+ </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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/make/code_coverage.xml Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/make/project.properties Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/DateParser.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java Wed Jul 05 18:57:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Logging.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/JDK-8008554.js Wed Jul 05 18:57:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/NASHORN-377.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/NASHORN-556.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/allgettersetters.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/compile-octane.js.EXPECTED Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/javaarrayconversion.js Wed Jul 05 18:57:48 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:48 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:48 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:48 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:48 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:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/basic/run-octane.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/currently-failing/logcoverage.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/trusted/NASHORN-638.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/script/trusted/NASHORN-653.js Wed Jul 05 18:57:48 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 Mon Jun 03 23:19:23 2013 -0700
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Wed Jul 05 18:57:48 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:48 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:48 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();
+ }
+}