--- a/.hgtags-top-repo Thu Nov 05 13:43:17 2015 -0800
+++ b/.hgtags-top-repo Wed Jul 05 20:59:18 2017 +0200
@@ -333,3 +333,4 @@
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89
cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90
+122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91
--- a/common/autoconf/compare.sh.in Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/compare.sh.in Wed Jul 05 20:59:18 2017 +0200
@@ -86,4 +86,6 @@
$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
+export SCRIPT_DIR="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
+
$BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
--- a/common/autoconf/flags.m4 Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/flags.m4 Wed Jul 05 20:59:18 2017 +0200
@@ -831,8 +831,6 @@
JDKLIB_LIBS="-ljava -ljvm"
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
- elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- JDKLIB_LIBS="$JDKLIB_LIBS -liconv"
fi
fi
@@ -944,7 +942,16 @@
else
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
fi
+
+ if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
+ # Set legacy hotspot variable
+ HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
+ else
+ HOTSPOT_SET_WARNINGS_AS_ERRORS=""
+ fi
+
AC_SUBST(WARNINGS_AS_ERRORS)
+ AC_SUBST(HOTSPOT_SET_WARNINGS_AS_ERRORS)
case "${TOOLCHAIN_TYPE}" in
microsoft)
--- a/common/autoconf/generated-configure.sh Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/generated-configure.sh Wed Jul 05 20:59:18 2017 +0200
@@ -685,6 +685,7 @@
ENABLE_DEBUG_SYMBOLS
CFLAGS_WARNINGS_ARE_ERRORS
DISABLE_WARNING_PREFIX
+HOTSPOT_SET_WARNINGS_AS_ERRORS
WARNINGS_AS_ERRORS
COMPILER_SUPPORTS_TARGET_BITS_FLAG
ZERO_ARCHFLAG
@@ -805,8 +806,6 @@
BUILD_HOTSPOT
HOTSPOT_DIST
BUILD_OUTPUT
-OVERRIDE_SRC_ROOT
-ADD_SRC_ROOT
JDK_TOPDIR
NASHORN_TOPDIR
HOTSPOT_TOPDIR
@@ -1912,26 +1911,29 @@
--with-build-number Set build number value for build [b00]
--with-copyright-year Set copyright year value for build [current year]
--with-boot-jdk path to Boot JDK (used to bootstrap build) [probed]
- --with-add-source-root for each and every source directory, look in this
- additional source root for the same directory; if it
- exists and have files in it, include it in the build
+ --with-add-source-root Deprecated. Option is kept for backwards
+ compatibility and is ignored
--with-override-source-root
- for each and every source directory, look in this
- override source root for the same directory; if it
- exists, use that directory instead and ignore the
- directory in the original source root
+ Deprecated. Option is kept for backwards
+ compatibility and is ignored
--with-adds-and-overrides
- use the subdirs 'adds' and 'overrides' in the
- specified directory as add-source-root and
- override-source-root
+ Deprecated. Option is kept for backwards
+ compatibility and is ignored
--with-override-langtools
- use this langtools dir for the build
- --with-override-corba use this corba dir for the build
- --with-override-jaxp use this jaxp dir for the build
- --with-override-jaxws use this jaxws dir for the build
- --with-override-hotspot use this hotspot dir for the build
- --with-override-nashorn use this nashorn dir for the build
- --with-override-jdk use this jdk dir for the build
+ Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-corba Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-jaxp Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-jaxws Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-hotspot Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-nashorn Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-override-jdk Deprecated. Option is kept for backwards
+ compatibility and is ignored
--with-import-hotspot import hotspot binaries from this jdk image or
hotspot build dist dir instead of building from
source
@@ -4354,7 +4356,7 @@
#
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -4384,7 +4386,6 @@
-
#
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4597,7 +4598,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1446135203
+DATE_WHEN_GENERATED=1446762265
###############################################################################
#
@@ -28868,8 +28869,7 @@
###############################################################################
- # Where are the sources. Any of these can be overridden
- # using --with-override-corba and the likes.
+ # Where are the sources.
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
CORBA_TOPDIR="$SRC_ROOT/corba"
JAXP_TOPDIR="$SRC_ROOT/jaxp"
@@ -28886,263 +28886,98 @@
-
- ###############################################################################
- #
- # Pickup additional source for a component from outside of the source root
- # or override source for a component.
- #
+ # This feature is no longer supported.
+
+
# Check whether --with-add-source-root was given.
if test "${with_add_source_root+set}" = set; then :
- withval=$with_add_source_root;
-fi
+ withval=$with_add_source_root; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-add-source-root is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-add-source-root is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-source-root was given.
if test "${with_override_source_root+set}" = set; then :
- withval=$with_override_source_root;
-fi
+ withval=$with_override_source_root; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-source-root is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-source-root is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-adds-and-overrides was given.
if test "${with_adds_and_overrides+set}" = set; then :
- withval=$with_adds_and_overrides;
-fi
-
-
- if test "x$with_adds_and_overrides" != x; then
- with_add_source_root="$with_adds_and_overrides/adds"
- with_override_source_root="$with_adds_and_overrides/overrides"
- fi
-
- if test "x$with_add_source_root" != x; then
- if ! test -d $with_add_source_root; then
- as_fn_error $? "Trying to use a non-existant add-source-root $with_add_source_root" "$LINENO" 5
- fi
- CURDIR="$PWD"
- cd "$with_add_source_root"
- ADD_SRC_ROOT="`pwd`"
- cd "$CURDIR"
- # Verify that the addon source root does not have any root makefiles.
- # If it does, then it is usually an error, prevent this.
- if test -f $with_add_source_root/langtools/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full langtools repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/corba/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full corba repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/jaxp/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full jaxp repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/jaxws/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full jaxws repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/hotspot/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/nashorn/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- if test -f $with_add_source_root/jdk/make/Makefile; then
- as_fn_error $? "Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources." "$LINENO" 5
- fi
- fi
-
-
- if test "x$with_override_source_root" != x; then
- if ! test -d $with_override_source_root; then
- as_fn_error $? "Trying to use a non-existant override-source-root $with_override_source_root" "$LINENO" 5
- fi
- CURDIR="$PWD"
- cd "$with_override_source_root"
- OVERRIDE_SRC_ROOT="`pwd`"
- cd "$CURDIR"
- if test -f $with_override_source_root/langtools/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full langtools repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/corba/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full corba repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/jaxp/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full jaxp repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/jaxws/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full jaxws repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/hotspot/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/nashorn/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- if test -f $with_override_source_root/jdk/make/Makefile; then
- as_fn_error $? "Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override." "$LINENO" 5
- fi
- fi
-
-
- ###############################################################################
- #
- # Override a repo completely, this is used for example when you have 3 small
- # development sandboxes of the langtools sources and want to avoid having 3 full
- # OpenJDK sources checked out on disk.
- #
- # Assuming that the 3 langtools sandboxes are located here:
- # /home/fredrik/sandbox1/langtools
- # /home/fredrik/sandbox2/langtools
- # /home/fredrik/sandbox3/langtools
- #
- # From the source root you create build subdirs manually:
- # mkdir -p build1 build2 build3
- # in each build directory run:
- # (cd build1 && ../configure --with-override-langtools=/home/fredrik/sandbox1 && make)
- # (cd build2 && ../configure --with-override-langtools=/home/fredrik/sandbox2 && make)
- # (cd build3 && ../configure --with-override-langtools=/home/fredrik/sandbox3 && make)
- #
+ withval=$with_adds_and_overrides; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-adds-and-overrides is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-adds-and-overrides is deprecated and will be ignored." >&2;}
+fi
+
+
# Check whether --with-override-langtools was given.
if test "${with_override_langtools+set}" = set; then :
- withval=$with_override_langtools;
-fi
+ withval=$with_override_langtools; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-langtools is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-langtools is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-corba was given.
if test "${with_override_corba+set}" = set; then :
- withval=$with_override_corba;
-fi
+ withval=$with_override_corba; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-corba is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-corba is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-jaxp was given.
if test "${with_override_jaxp+set}" = set; then :
- withval=$with_override_jaxp;
-fi
+ withval=$with_override_jaxp; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jaxp is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jaxp is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-jaxws was given.
if test "${with_override_jaxws+set}" = set; then :
- withval=$with_override_jaxws;
-fi
+ withval=$with_override_jaxws; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jaxws is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jaxws is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-hotspot was given.
if test "${with_override_hotspot+set}" = set; then :
- withval=$with_override_hotspot;
-fi
+ withval=$with_override_hotspot; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-hotspot is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-hotspot is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-nashorn was given.
if test "${with_override_nashorn+set}" = set; then :
- withval=$with_override_nashorn;
-fi
+ withval=$with_override_nashorn; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-nashorn is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-nashorn is deprecated and will be ignored." >&2;}
+fi
+
# Check whether --with-override-jdk was given.
if test "${with_override_jdk+set}" = set; then :
- withval=$with_override_jdk;
-fi
-
-
- if test "x$with_override_langtools" != x; then
- CURDIR="$PWD"
- cd "$with_override_langtools"
- LANGTOOLS_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $LANGTOOLS_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override langtools with a full langtools repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if langtools should be overridden" >&5
-$as_echo_n "checking if langtools should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $LANGTOOLS_TOPDIR" >&5
-$as_echo "yes with $LANGTOOLS_TOPDIR" >&6; }
- fi
- if test "x$with_override_corba" != x; then
- CURDIR="$PWD"
- cd "$with_override_corba"
- CORBA_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $CORBA_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override corba with a full corba repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if corba should be overridden" >&5
-$as_echo_n "checking if corba should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $CORBA_TOPDIR" >&5
-$as_echo "yes with $CORBA_TOPDIR" >&6; }
- fi
- if test "x$with_override_jaxp" != x; then
- CURDIR="$PWD"
- cd "$with_override_jaxp"
- JAXP_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JAXP_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override jaxp with a full jaxp repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if jaxp should be overridden" >&5
-$as_echo_n "checking if jaxp should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JAXP_TOPDIR" >&5
-$as_echo "yes with $JAXP_TOPDIR" >&6; }
- fi
- if test "x$with_override_jaxws" != x; then
- CURDIR="$PWD"
- cd "$with_override_jaxws"
- JAXWS_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JAXWS_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override jaxws with a full jaxws repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if jaxws should be overridden" >&5
-$as_echo_n "checking if jaxws should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JAXWS_TOPDIR" >&5
-$as_echo "yes with $JAXWS_TOPDIR" >&6; }
- fi
- if test "x$with_override_hotspot" != x; then
- CURDIR="$PWD"
- cd "$with_override_hotspot"
- HOTSPOT_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $HOTSPOT_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override hotspot with a full hotspot repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if hotspot should be overridden" >&5
-$as_echo_n "checking if hotspot should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $HOTSPOT_TOPDIR" >&5
-$as_echo "yes with $HOTSPOT_TOPDIR" >&6; }
- fi
- if test "x$with_override_nashorn" != x; then
- CURDIR="$PWD"
- cd "$with_override_nashorn"
- NASHORN_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $NASHORN_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override nashorn with a full nashorn repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if nashorn should be overridden" >&5
-$as_echo_n "checking if nashorn should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $NASHORN_TOPDIR" >&5
-$as_echo "yes with $NASHORN_TOPDIR" >&6; }
- fi
- if test "x$with_override_jdk" != x; then
- CURDIR="$PWD"
- cd "$with_override_jdk"
- JDK_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JDK_TOPDIR/make/Makefile; then
- as_fn_error $? "You have to override JDK with a full JDK repo!" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if JDK should be overridden" >&5
-$as_echo_n "checking if JDK should be overridden... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JDK_TOPDIR" >&5
-$as_echo "yes with $JDK_TOPDIR" >&6; }
- fi
+ withval=$with_override_jdk; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jdk is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jdk is deprecated and will be ignored." >&2;}
+fi
+
+
BUILD_OUTPUT="$OUTPUT_ROOT"
@@ -45118,8 +44953,6 @@
JDKLIB_LIBS="-ljava -ljvm"
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
- elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- JDKLIB_LIBS="$JDKLIB_LIBS -liconv"
fi
fi
@@ -45305,6 +45138,15 @@
as_fn_error $? "--enable-warnings-as-errors accepts no argument" "$LINENO" 5
fi
+ if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
+ # Set legacy hotspot variable
+ HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
+ else
+ HOTSPOT_SET_WARNINGS_AS_ERRORS=""
+ fi
+
+
+
case "${TOOLCHAIN_TYPE}" in
microsoft)
--- a/common/autoconf/hotspot-spec.gmk.in Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/hotspot-spec.gmk.in Wed Jul 05 20:59:18 2017 +0200
@@ -33,6 +33,7 @@
# Additional legacy variables defined for Hotspot
@SET_OPENJDK@
+@HOTSPOT_SET_WARNINGS_AS_ERRORS@
# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
@BUILD_HEADLESS@
--- a/common/autoconf/source-dirs.m4 Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/source-dirs.m4 Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,7 @@
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
[
- # Where are the sources. Any of these can be overridden
- # using --with-override-corba and the likes.
+ # Where are the sources.
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
CORBA_TOPDIR="$SRC_ROOT/corba"
JAXP_TOPDIR="$SRC_ROOT/jaxp"
@@ -43,216 +42,20 @@
AC_SUBST(JDK_TOPDIR)
])
-
AC_DEFUN_ONCE([SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS],
[
-
- ###############################################################################
- #
- # Pickup additional source for a component from outside of the source root
- # or override source for a component.
- #
- AC_ARG_WITH(add-source-root, [AS_HELP_STRING([--with-add-source-root],
- [for each and every source directory, look in this additional source root for
- the same directory; if it exists and have files in it, include it in the build])])
-
- AC_ARG_WITH(override-source-root, [AS_HELP_STRING([--with-override-source-root],
- [for each and every source directory, look in this override source root for
- the same directory; if it exists, use that directory instead and
- ignore the directory in the original source root])])
-
- AC_ARG_WITH(adds-and-overrides, [AS_HELP_STRING([--with-adds-and-overrides],
- [use the subdirs 'adds' and 'overrides' in the specified directory as
- add-source-root and override-source-root])])
-
- if test "x$with_adds_and_overrides" != x; then
- with_add_source_root="$with_adds_and_overrides/adds"
- with_override_source_root="$with_adds_and_overrides/overrides"
- fi
-
- if test "x$with_add_source_root" != x; then
- if ! test -d $with_add_source_root; then
- AC_MSG_ERROR([Trying to use a non-existant add-source-root $with_add_source_root])
- fi
- CURDIR="$PWD"
- cd "$with_add_source_root"
- ADD_SRC_ROOT="`pwd`"
- cd "$CURDIR"
- # Verify that the addon source root does not have any root makefiles.
- # If it does, then it is usually an error, prevent this.
- if test -f $with_add_source_root/langtools/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full langtools repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/corba/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full corba repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/jaxp/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full jaxp repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/jaxws/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full jaxws repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/hotspot/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/nashorn/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources.])
- fi
- if test -f $with_add_source_root/jdk/make/Makefile; then
- AC_MSG_ERROR([Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources.])
- fi
- fi
- AC_SUBST(ADD_SRC_ROOT)
-
- if test "x$with_override_source_root" != x; then
- if ! test -d $with_override_source_root; then
- AC_MSG_ERROR([Trying to use a non-existant override-source-root $with_override_source_root])
- fi
- CURDIR="$PWD"
- cd "$with_override_source_root"
- OVERRIDE_SRC_ROOT="`pwd`"
- cd "$CURDIR"
- if test -f $with_override_source_root/langtools/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full langtools repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/corba/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full corba repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/jaxp/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full jaxp repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/jaxws/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full jaxws repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/hotspot/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/nashorn/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override.])
- fi
- if test -f $with_override_source_root/jdk/make/Makefile; then
- AC_MSG_ERROR([Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override.])
- fi
- fi
- AC_SUBST(OVERRIDE_SRC_ROOT)
+ # This feature is no longer supported.
- ###############################################################################
- #
- # Override a repo completely, this is used for example when you have 3 small
- # development sandboxes of the langtools sources and want to avoid having 3 full
- # OpenJDK sources checked out on disk.
- #
- # Assuming that the 3 langtools sandboxes are located here:
- # /home/fredrik/sandbox1/langtools
- # /home/fredrik/sandbox2/langtools
- # /home/fredrik/sandbox3/langtools
- #
- # From the source root you create build subdirs manually:
- # mkdir -p build1 build2 build3
- # in each build directory run:
- # (cd build1 && ../configure --with-override-langtools=/home/fredrik/sandbox1 && make)
- # (cd build2 && ../configure --with-override-langtools=/home/fredrik/sandbox2 && make)
- # (cd build3 && ../configure --with-override-langtools=/home/fredrik/sandbox3 && make)
- #
-
- AC_ARG_WITH(override-langtools, [AS_HELP_STRING([--with-override-langtools],
- [use this langtools dir for the build])])
-
- AC_ARG_WITH(override-corba, [AS_HELP_STRING([--with-override-corba],
- [use this corba dir for the build])])
-
- AC_ARG_WITH(override-jaxp, [AS_HELP_STRING([--with-override-jaxp],
- [use this jaxp dir for the build])])
-
- AC_ARG_WITH(override-jaxws, [AS_HELP_STRING([--with-override-jaxws],
- [use this jaxws dir for the build])])
-
- AC_ARG_WITH(override-hotspot, [AS_HELP_STRING([--with-override-hotspot],
- [use this hotspot dir for the build])])
-
- AC_ARG_WITH(override-nashorn, [AS_HELP_STRING([--with-override-nashorn],
- [use this nashorn dir for the build])])
-
- AC_ARG_WITH(override-jdk, [AS_HELP_STRING([--with-override-jdk],
- [use this jdk dir for the build])])
-
- if test "x$with_override_langtools" != x; then
- CURDIR="$PWD"
- cd "$with_override_langtools"
- LANGTOOLS_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $LANGTOOLS_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override langtools with a full langtools repo!])
- fi
- AC_MSG_CHECKING([if langtools should be overridden])
- AC_MSG_RESULT([yes with $LANGTOOLS_TOPDIR])
- fi
- if test "x$with_override_corba" != x; then
- CURDIR="$PWD"
- cd "$with_override_corba"
- CORBA_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $CORBA_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override corba with a full corba repo!])
- fi
- AC_MSG_CHECKING([if corba should be overridden])
- AC_MSG_RESULT([yes with $CORBA_TOPDIR])
- fi
- if test "x$with_override_jaxp" != x; then
- CURDIR="$PWD"
- cd "$with_override_jaxp"
- JAXP_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JAXP_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override jaxp with a full jaxp repo!])
- fi
- AC_MSG_CHECKING([if jaxp should be overridden])
- AC_MSG_RESULT([yes with $JAXP_TOPDIR])
- fi
- if test "x$with_override_jaxws" != x; then
- CURDIR="$PWD"
- cd "$with_override_jaxws"
- JAXWS_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JAXWS_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override jaxws with a full jaxws repo!])
- fi
- AC_MSG_CHECKING([if jaxws should be overridden])
- AC_MSG_RESULT([yes with $JAXWS_TOPDIR])
- fi
- if test "x$with_override_hotspot" != x; then
- CURDIR="$PWD"
- cd "$with_override_hotspot"
- HOTSPOT_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $HOTSPOT_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override hotspot with a full hotspot repo!])
- fi
- AC_MSG_CHECKING([if hotspot should be overridden])
- AC_MSG_RESULT([yes with $HOTSPOT_TOPDIR])
- fi
- if test "x$with_override_nashorn" != x; then
- CURDIR="$PWD"
- cd "$with_override_nashorn"
- NASHORN_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $NASHORN_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override nashorn with a full nashorn repo!])
- fi
- AC_MSG_CHECKING([if nashorn should be overridden])
- AC_MSG_RESULT([yes with $NASHORN_TOPDIR])
- fi
- if test "x$with_override_jdk" != x; then
- CURDIR="$PWD"
- cd "$with_override_jdk"
- JDK_TOPDIR="`pwd`"
- cd "$CURDIR"
- if ! test -f $JDK_TOPDIR/make/Makefile; then
- AC_MSG_ERROR([You have to override JDK with a full JDK repo!])
- fi
- AC_MSG_CHECKING([if JDK should be overridden])
- AC_MSG_RESULT([yes with $JDK_TOPDIR])
- fi
+ BASIC_DEPRECATED_ARG_WITH(add-source-root)
+ BASIC_DEPRECATED_ARG_WITH(override-source-root)
+ BASIC_DEPRECATED_ARG_WITH(adds-and-overrides)
+ BASIC_DEPRECATED_ARG_WITH(override-langtools)
+ BASIC_DEPRECATED_ARG_WITH(override-corba)
+ BASIC_DEPRECATED_ARG_WITH(override-jaxp)
+ BASIC_DEPRECATED_ARG_WITH(override-jaxws)
+ BASIC_DEPRECATED_ARG_WITH(override-hotspot)
+ BASIC_DEPRECATED_ARG_WITH(override-nashorn)
+ BASIC_DEPRECATED_ARG_WITH(override-jdk)
])
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
--- a/common/autoconf/spec.gmk.in Thu Nov 05 13:43:17 2015 -0800
+++ b/common/autoconf/spec.gmk.in Wed Jul 05 20:59:18 2017 +0200
@@ -113,10 +113,6 @@
SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
-# Paths to the source code
-ADD_SRC_ROOT:=@ADD_SRC_ROOT@
-OVERRIDE_SRC_ROOT:=@OVERRIDE_SRC_ROOT@
-
# The top-level directory of the forest (SRC_ROOT is a traditional alias)
TOPDIR:=@TOPDIR@
# These two versions of TOPDIR are used in string comparisons
@@ -548,34 +544,6 @@
MSVCR_DLL:=@MSVCR_DLL@
MSVCP_DLL:=@MSVCP_DLL@
-
-# ADD_SRCS takes a single argument with source roots
-# and appends any corresponding source roots found
-# below --with-add-source-root and below
-# --with-override-source-root. It is the responsibility
-# of the next macro to get rid of superfluous files.
-ADD_SRCS=$1
-ifneq (,$(ADD_SRC_ROOT))
- # Append wildcard rule to pickup any matching source roots found below ADD_SRC_ROOT
- ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(ADD_SRC_ROOT),$1))
-endif
-ifneq (,$(OVERRIDE_SRC_ROOT))
- # Append wildcard rule to pickup any matching source roots found below OVERRIDE_SRC_ROOT
- ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(OVERRIDE_SRC_ROOT),$1))
-endif
-
-# OVR_SRCS creates a filter expression to filter out sources in
-# the original source directory that lie inside directories below
-# --with-override-source-root.
-# Use := here since we want to scan for these files here. To avoid recomputation later.
-# We cannot do the scan in configure, since that would force us to rerun configure when
-# we add overridden sources.
-ifneq (,$(OVERRIDE_SRC_ROOT))
- OVR_SRCS:=$(addsuffix %,$(subst $(OVERRIDE_SRC_ROOT),$(SRC_ROOT),$(sort $(dir $(shell $(FIND) $(OVERRIDE_SRC_ROOT) -type f)))))
-else
- OVR_SRCS:=
-endif
-
####################################################
#
# INSTALLATION
--- a/common/bin/compare.sh Thu Nov 05 13:43:17 2015 -0800
+++ b/common/bin/compare.sh Wed Jul 05 20:59:18 2017 +0200
@@ -989,7 +989,7 @@
fi
fi
-THIS="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
+THIS="$SCRIPT_DIR"
echo "$THIS"
THIS_SCRIPT="$0"
--- a/corba/.hgtags Thu Nov 05 13:43:17 2015 -0800
+++ b/corba/.hgtags Wed Jul 05 20:59:18 2017 +0200
@@ -333,3 +333,4 @@
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89
29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90
+75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91
--- a/hotspot/.hgtags Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/.hgtags Wed Jul 05 20:59:18 2017 +0200
@@ -493,3 +493,4 @@
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89
7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90
+3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91
--- a/hotspot/make/bsd/makefiles/gcc.make Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/make/bsd/makefiles/gcc.make Wed Jul 05 20:59:18 2017 +0200
@@ -97,6 +97,7 @@
# prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+ CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
endif
ifeq ($(USE_CLANG), true)
@@ -326,6 +327,10 @@
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
endif
else
+ # Do not allow GCC 4.1.1
+ ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+ $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+ endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -109,7 +109,11 @@
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
for i in $$($(LS)); do \
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
- $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \
+ $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c.tmp; \
+ done)
+ ($(CD) $(GENSRC_DIR)/META-INF/services && \
+ for i in $$($(LS) *.tmp); do \
+ $(MV) $$i $${i%.tmp}; \
done)
$(TOUCH) $@
--- a/hotspot/make/linux/makefiles/gcc.make Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/make/linux/makefiles/gcc.make Wed Jul 05 20:59:18 2017 +0200
@@ -60,6 +60,7 @@
# prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+ CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
endif
ifeq ($(USE_CLANG), true)
@@ -264,6 +265,10 @@
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
endif
else
+ # Do not allow GCC 4.1.1
+ ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+ $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+ endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/make/solaris/makefiles/gcc.make Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/make/solaris/makefiles/gcc.make Wed Jul 05 20:59:18 2017 +0200
@@ -39,6 +39,7 @@
# prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
# Check for the versions of C++ and C compilers ($CXX and $CC) used.
@@ -160,6 +161,10 @@
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
endif
else
+ # Do not allow GCC 4.1.1
+ ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+ $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+ endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -59,9 +59,9 @@
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
-#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
-#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
-#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+#define MIN_STACK_YELLOW_PAGES 1
+#define MIN_STACK_RED_PAGES 1
+#define MIN_STACK_SHADOW_PAGES 1
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -1777,7 +1777,7 @@
const Register obj_reg = r19; // Will contain the oop
const Register lock_reg = r13; // Address of compiler lock object (BasicLock)
const Register old_hdr = r13; // value of old header at unlock time
- const Register tmp = c_rarg3;
+ const Register tmp = lr;
Label slow_path_lock;
Label lock_done;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -1539,7 +1539,6 @@
emit_arith(0x3B, 0xC0, dst, src);
}
-
void Assembler::cmpl(Register dst, Address src) {
InstructionMark im(this);
prefix(src, dst);
@@ -2125,6 +2124,16 @@
emit_operand(dst, src);
}
+void Assembler::movddup(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
+ NOT_LP64(assert(VM_Version::supports_sse3(), ""));
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false, VEX_OPCODE_0F,
+ /* rex_w */ VM_Version::supports_evex(), AVX_128bit, /* legacy_mode */ false);
+ emit_int8(0x12);
+ emit_int8(0xC0 | encode);
+
+}
+
void Assembler::kmovql(KRegister dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
@@ -3403,6 +3412,20 @@
}
}
+void Assembler::rcpps(XMMRegister dst, XMMRegister src) {
+ NOT_LP64(assert(VM_Version::supports_sse(), ""));
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
+ emit_int8(0x53);
+ emit_int8(0xC0 | encode);
+}
+
+void Assembler::rcpss(XMMRegister dst, XMMRegister src) {
+ NOT_LP64(assert(VM_Version::supports_sse(), ""));
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
+ emit_int8(0x53);
+ emit_int8(0xC0 | encode);
+}
+
void Assembler::rdtsc() {
emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x31);
@@ -6326,6 +6349,26 @@
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) {
+ assert(VM_Version::supports_avx(), "");
+ assert(!VM_Version::supports_evex(), "");
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F, /* no_mask_reg */ false);
+ emit_int8((unsigned char)0xC2);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8((unsigned char)(0xF & cop));
+}
+
+void Assembler::vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len) {
+ assert(VM_Version::supports_avx(), "");
+ assert(!VM_Version::supports_evex(), "");
+ int encode = vex_prefix_and_encode(dst, nds, src1, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* no_mask_reg */ false);
+ emit_int8((unsigned char)0x4B);
+ emit_int8((unsigned char)(0xC0 | encode));
+ int src2_enc = src2->encoding();
+ emit_int8((unsigned char)(0xF0 & src2_enc<<4));
+}
+
+
#ifndef _LP64
void Assembler::incl(Register dst) {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -1504,6 +1504,8 @@
void movb(Address dst, int imm8);
void movb(Register dst, Address src);
+ void movddup(XMMRegister dst, XMMRegister src);
+
void kmovql(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src);
@@ -1768,6 +1770,10 @@
void rcrq(Register dst, int imm8);
+ void rcpps(XMMRegister dst, XMMRegister src);
+
+ void rcpss(XMMRegister dst, XMMRegister src);
+
void rdtsc();
void ret(int imm16);
@@ -2141,6 +2147,11 @@
// runtime code and native libraries.
void vzeroupper();
+ // AVX support for vectorized conditional move (double). The following two instructions used only coupled.
+ void cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len);
+ void vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len);
+
+
protected:
// Next instructions require address alignment 16 bytes SSE mode.
// They should be called only from corresponding MacroAssembler instructions.
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2440,7 +2440,6 @@
} else if (value->is_double_fpu()) {
assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
switch(code) {
- case lir_log : __ flog() ; break;
case lir_log10 : __ flog10() ; break;
case lir_abs : __ fabs() ; break;
case lir_sqrt : __ fsqrt(); break;
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -809,8 +809,8 @@
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
- if (x->id() == vmIntrinsics::_dexp) {
- do_ExpIntrinsic(x);
+ if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog) {
+ do_LibmIntrinsic(x);
return;
}
@@ -822,7 +822,6 @@
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
- case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dpow:
use_fpu = true;
@@ -873,7 +872,6 @@
case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
- case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break;
case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
default: ShouldNotReachHere();
@@ -884,7 +882,7 @@
}
}
-void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
+void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
LIRItem value(x->argument_at(0), this);
value.set_destroys_register();
@@ -900,13 +898,33 @@
#ifndef _LP64
LIR_Opr tmp = FrameMap::fpu0_double_opr;
result_reg = tmp;
- if (VM_Version::supports_sse2()) {
- __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
- } else {
- __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+ switch(x->id()) {
+ case vmIntrinsics::_dexp:
+ if (VM_Version::supports_sse2()) {
+ __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ case vmIntrinsics::_dlog:
+ if (VM_Version::supports_sse2()) {
+ __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
+ }
+ else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ default: ShouldNotReachHere();
}
#else
- __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+ switch (x->id()) {
+ case vmIntrinsics::_dexp:
+ __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+ break;
+ case vmIntrinsics::_dlog:
+ __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
+ break;
+ }
#endif
__ move(result_reg, calc_result);
}
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -786,7 +786,6 @@
break;
}
- case lir_log:
case lir_log10: {
// log and log10 need one temporary fpu stack slot, so
// there is one temporary registers stored in temp of the
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -132,10 +132,15 @@
__ fabs();
break;
case Interpreter::java_lang_math_log:
- __ flog();
- // Store to stack to convert 80bit precision back to 64bits
- __ push_fTOS();
- __ pop_fTOS();
+ __ subptr(rsp, 2 * wordSize);
+ __ fstp_d(Address(rsp, 0));
+ if (VM_Version::supports_sse2()) {
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
+ }
+ else {
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
+ }
+ __ addptr(rsp, 2 * wordSize);
break;
case Interpreter::java_lang_math_log10:
__ flog10();
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -253,6 +253,9 @@
} else if (kind == Interpreter::java_lang_math_exp) {
__ movdbl(xmm0, Address(rsp, wordSize));
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
+ } else if (kind == Interpreter::java_lang_math_log) {
+ __ movdbl(xmm0, Address(rsp, wordSize));
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
} else {
__ fld_d(Address(rsp, wordSize));
switch (kind) {
@@ -268,9 +271,6 @@
case Interpreter::java_lang_math_abs:
__ fabs();
break;
- case Interpreter::java_lang_math_log:
- __ flog();
- break;
case Interpreter::java_lang_math_log10:
__ flog10();
break;
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -56,6 +56,8 @@
#define VIRTUAL virtual
#endif
+#define COMMA ,
+
VIRTUAL void call_VM_leaf_base(
address entry_point, // the entry point
int number_of_arguments // the number of arguments to pop after the call
@@ -910,6 +912,11 @@
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
Register rax, Register rcx, Register rdx, Register tmp);
+
+ void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+ XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+ Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2));
+
void increase_precision();
void restore_precision();
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -24,8 +24,19 @@
*
*/
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "macroAssembler_x86.hpp"
+
+#ifdef _MSC_VER
+#define ALIGNED_(x) __declspec(align(x))
+#else
+#define ALIGNED_(x) __attribute__ ((aligned(x)))
+#endif
+
/******************************************************************************/
-// ALGORITHM DESCRIPTION
+// ALGORITHM DESCRIPTION - EXP()
// ---------------------
//
// Description:
@@ -58,18 +69,6 @@
//
/******************************************************************************/
-
-#include "precompiled.hpp"
-#include "asm/assembler.hpp"
-#include "asm/assembler.inline.hpp"
-#include "macroAssembler_x86.hpp"
-
-#ifdef _MSC_VER
-#define ALIGNED_(x) __declspec(align(x))
-#else
-#define ALIGNED_(x) __attribute__ ((aligned(x)))
-#endif
-
#ifdef _LP64
ALIGNED_(16) juint _cv[] =
@@ -409,6 +408,7 @@
bind(B1_5);
addq(rsp, 24);
}
+
#endif
#ifndef _LP64
@@ -675,3 +675,614 @@
}
#endif
+
+/******************************************************************************/
+// ALGORITHM DESCRIPTION - LOG()
+// ---------------------
+//
+// x=2^k * mx, mx in [1,2)
+//
+// Get B~1/mx based on the output of rcpss instruction (B0)
+// B = int((B0*2^7+0.5))/2^7
+//
+// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
+//
+// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
+// p(r) is a degree 7 polynomial
+// -log(B) read from data table (high, low parts)
+// Result is formed from high and low parts
+//
+// Special cases:
+// log(NaN) = quiet NaN, and raise invalid exception
+// log(+INF) = that INF
+// log(0) = -INF with divide-by-zero exception raised
+// log(1) = +0
+// log(x) = NaN with invalid exception raised if x < -0, including -INF
+//
+/******************************************************************************/
+
+#ifdef _LP64
+
+ALIGNED_(16) juint _L_tbl[] =
+{
+ 0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
+ 0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
+ 0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
+ 0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
+ 0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
+ 0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
+ 0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
+ 0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
+ 0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
+ 0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
+ 0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
+ 0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
+ 0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
+ 0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
+ 0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
+ 0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
+ 0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
+ 0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
+ 0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
+ 0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
+ 0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
+ 0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
+ 0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
+ 0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
+ 0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
+ 0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
+ 0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
+ 0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
+ 0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
+ 0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
+ 0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
+ 0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
+ 0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
+ 0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
+ 0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
+ 0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
+ 0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
+ 0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
+ 0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
+ 0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
+ 0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
+ 0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
+ 0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
+ 0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
+ 0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
+ 0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
+ 0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
+ 0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
+ 0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
+ 0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
+ 0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
+ 0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
+ 0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
+ 0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
+ 0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
+ 0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
+ 0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
+ 0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
+ 0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
+ 0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
+ 0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
+ 0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
+ 0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
+ 0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
+ 0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
+ 0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
+ 0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
+ 0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
+ 0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
+ 0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
+ 0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
+ 0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
+ 0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
+ 0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
+ 0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
+ 0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
+ 0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
+ 0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
+ 0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
+ 0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
+ 0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
+ 0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
+ 0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
+ 0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
+ 0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
+ 0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
+ 0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
+ 0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
+ 0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
+ 0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
+ 0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
+ 0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
+ 0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
+ 0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
+ 0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
+ 0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
+ 0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
+ 0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
+ 0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
+ 0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
+ 0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
+ 0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
+ 0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+ 0x80000000UL
+};
+
+ALIGNED_(16) juint _log2[] =
+{
+ 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
+};
+
+ALIGNED_(16) juint _coeff[] =
+{
+ 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
+ 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
+ 0x00000000UL, 0xbfe00000UL
+};
+
+//registers,
+// input: xmm0
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+// rax, rdx, rcx, r8, r11
+
+void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp1, Register tmp2) {
+ Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+ Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+ Label L_2TAG_PACKET_8_0_2;
+ Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
+
+ assert_different_registers(tmp1, tmp2, eax, ecx, edx);
+ jmp(start);
+ address L_tbl = (address)_L_tbl;
+ address log2 = (address)_log2;
+ address coeff = (address)_coeff;
+
+ bind(start);
+ subq(rsp, 24);
+ movsd(Address(rsp, 0), xmm0);
+ mov64(rax, 0x3ff0000000000000);
+ movdq(xmm2, rax);
+ mov64(rdx, 0x77f0000000000000);
+ movdq(xmm3, rdx);
+ movl(ecx, 32768);
+ movdl(xmm4, rcx);
+ mov64(tmp1, 0xffffe00000000000);
+ movdq(xmm5, tmp1);
+ movdqu(xmm1, xmm0);
+ pextrw(eax, xmm0, 3);
+ por(xmm0, xmm2);
+ movl(ecx, 16352);
+ psrlq(xmm0, 27);
+ lea(tmp2, ExternalAddress(L_tbl));
+ psrld(xmm0, 2);
+ rcpps(xmm0, xmm0);
+ psllq(xmm1, 12);
+ pshufd(xmm6, xmm5, 228);
+ psrlq(xmm1, 12);
+ subl(eax, 16);
+ cmpl(eax, 32736);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+
+ bind(L_2TAG_PACKET_1_0_2);
+ paddd(xmm0, xmm4);
+ por(xmm1, xmm3);
+ movdl(edx, xmm0);
+ psllq(xmm0, 29);
+ pand(xmm5, xmm1);
+ pand(xmm0, xmm6);
+ subsd(xmm1, xmm5);
+ mulpd(xmm5, xmm0);
+ andl(eax, 32752);
+ subl(eax, ecx);
+ cvtsi2sdl(xmm7, eax);
+ mulsd(xmm1, xmm0);
+ movq(xmm6, ExternalAddress(log2)); // 0xfefa3800UL, 0x3fa62e42UL
+ movdqu(xmm3, ExternalAddress(coeff)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
+ subsd(xmm5, xmm2);
+ andl(edx, 16711680);
+ shrl(edx, 12);
+ movdqu(xmm0, Address(tmp2, edx));
+ movdqu(xmm4, ExternalAddress(16 + coeff)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
+ addsd(xmm1, xmm5);
+ movdqu(xmm2, ExternalAddress(32 + coeff)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
+ mulsd(xmm6, xmm7);
+ movddup(xmm5, xmm1);
+ mulsd(xmm7, ExternalAddress(8 + log2)); // 0x93c76730UL, 0x3ceef357UL
+ mulsd(xmm3, xmm1);
+ addsd(xmm0, xmm6);
+ mulpd(xmm4, xmm5);
+ mulpd(xmm5, xmm5);
+ movddup(xmm6, xmm0);
+ addsd(xmm0, xmm1);
+ addpd(xmm4, xmm2);
+ mulpd(xmm3, xmm5);
+ subsd(xmm6, xmm0);
+ mulsd(xmm4, xmm1);
+ pshufd(xmm2, xmm0, 238);
+ addsd(xmm1, xmm6);
+ mulsd(xmm5, xmm5);
+ addsd(xmm7, xmm2);
+ addpd(xmm4, xmm3);
+ addsd(xmm1, xmm7);
+ mulpd(xmm4, xmm5);
+ addsd(xmm1, xmm4);
+ pshufd(xmm5, xmm4, 238);
+ addsd(xmm1, xmm5);
+ addsd(xmm0, xmm1);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_0_0_2);
+ movq(xmm0, Address(rsp, 0));
+ movq(xmm1, Address(rsp, 0));
+ addl(eax, 16);
+ cmpl(eax, 32768);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_2);
+ cmpl(eax, 16);
+ jcc(Assembler::below, L_2TAG_PACKET_3_0_2);
+
+ bind(L_2TAG_PACKET_4_0_2);
+ addsd(xmm0, xmm0);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_5_0_2);
+ jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
+ cmpl(edx, 0);
+ jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_3_0_2);
+ xorpd(xmm1, xmm1);
+ addsd(xmm1, xmm0);
+ movdl(edx, xmm1);
+ psrlq(xmm1, 32);
+ movdl(ecx, xmm1);
+ orl(edx, ecx);
+ cmpl(edx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
+ xorpd(xmm1, xmm1);
+ movl(eax, 18416);
+ pinsrw(xmm1, eax, 3);
+ mulsd(xmm0, xmm1);
+ movdqu(xmm1, xmm0);
+ pextrw(eax, xmm0, 3);
+ por(xmm0, xmm2);
+ psrlq(xmm0, 27);
+ movl(ecx, 18416);
+ psrld(xmm0, 2);
+ rcpps(xmm0, xmm0);
+ psllq(xmm1, 12);
+ pshufd(xmm6, xmm5, 228);
+ psrlq(xmm1, 12);
+ jmp(L_2TAG_PACKET_1_0_2);
+
+ bind(L_2TAG_PACKET_2_0_2);
+ movdl(edx, xmm1);
+ psrlq(xmm1, 32);
+ movdl(ecx, xmm1);
+ addl(ecx, ecx);
+ cmpl(ecx, -2097152);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_5_0_2);
+ orl(edx, ecx);
+ cmpl(edx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
+
+ bind(L_2TAG_PACKET_6_0_2);
+ xorpd(xmm1, xmm1);
+ xorpd(xmm0, xmm0);
+ movl(eax, 32752);
+ pinsrw(xmm1, eax, 3);
+ mulsd(xmm0, xmm1);
+ movl(Address(rsp, 16), 3);
+ jmp(L_2TAG_PACKET_8_0_2);
+ bind(L_2TAG_PACKET_7_0_2);
+ xorpd(xmm1, xmm1);
+ xorpd(xmm0, xmm0);
+ movl(eax, 49136);
+ pinsrw(xmm0, eax, 3);
+ divsd(xmm0, xmm1);
+ movl(Address(rsp, 16), 2);
+
+ bind(L_2TAG_PACKET_8_0_2);
+ movq(Address(rsp, 8), xmm0);
+
+ bind(B1_3);
+ movq(xmm0, Address(rsp, 8));
+
+ bind(B1_5);
+ addq(rsp, 24);
+}
+
+#endif
+
+#ifndef _LP64
+
+ALIGNED_(16) juint _static_const_table_log[] =
+{
+ 0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
+ 0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
+ 0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
+ 0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
+ 0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
+ 0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
+ 0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
+ 0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
+ 0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
+ 0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
+ 0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
+ 0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
+ 0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
+ 0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
+ 0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
+ 0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
+ 0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
+ 0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
+ 0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
+ 0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
+ 0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
+ 0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
+ 0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
+ 0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
+ 0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
+ 0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
+ 0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
+ 0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
+ 0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
+ 0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
+ 0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
+ 0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
+ 0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
+ 0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
+ 0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
+ 0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
+ 0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
+ 0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
+ 0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
+ 0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
+ 0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
+ 0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
+ 0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
+ 0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
+ 0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
+ 0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
+ 0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
+ 0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
+ 0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
+ 0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
+ 0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
+ 0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
+ 0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
+ 0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
+ 0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
+ 0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
+ 0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
+ 0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
+ 0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
+ 0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
+ 0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
+ 0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
+ 0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
+ 0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
+ 0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
+ 0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
+ 0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
+ 0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
+ 0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
+ 0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
+ 0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
+ 0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
+ 0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
+ 0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
+ 0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
+ 0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
+ 0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
+ 0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
+ 0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
+ 0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
+ 0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
+ 0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
+ 0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
+ 0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
+ 0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
+ 0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
+ 0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
+ 0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
+ 0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
+ 0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
+ 0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
+ 0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
+ 0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
+ 0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
+ 0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
+ 0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
+ 0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
+ 0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
+ 0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
+ 0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
+ 0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
+ 0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
+ 0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+ 0x80000000UL, 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL,
+ 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
+ 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
+ 0x00000000UL, 0xbfe00000UL, 0x00000000UL, 0xffffe000UL, 0x00000000UL,
+ 0xffffe000UL
+};
+//registers,
+// input: xmm0
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+// rax, rdx, rcx, rbx (tmp)
+
+void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
+ Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+ Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+ Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2;
+ Label L_2TAG_PACKET_10_0_2, start;
+
+ assert_different_registers(tmp, eax, ecx, edx);
+ jmp(start);
+ address static_const_table = (address)_static_const_table_log;
+
+ bind(start);
+ subl(rsp, 104);
+ movl(Address(rsp, 40), tmp);
+ lea(tmp, ExternalAddress(static_const_table));
+ xorpd(xmm2, xmm2);
+ movl(eax, 16368);
+ pinsrw(xmm2, eax, 3);
+ xorpd(xmm3, xmm3);
+ movl(edx, 30704);
+ pinsrw(xmm3, edx, 3);
+ movsd(xmm0, Address(rsp, 112));
+ movapd(xmm1, xmm0);
+ movl(ecx, 32768);
+ movdl(xmm4, ecx);
+ movsd(xmm5, Address(tmp, 2128)); // 0x00000000UL, 0xffffe000UL
+ pextrw(eax, xmm0, 3);
+ por(xmm0, xmm2);
+ psllq(xmm0, 5);
+ movl(ecx, 16352);
+ psrlq(xmm0, 34);
+ rcpss(xmm0, xmm0);
+ psllq(xmm1, 12);
+ pshufd(xmm6, xmm5, 228);
+ psrlq(xmm1, 12);
+ subl(eax, 16);
+ cmpl(eax, 32736);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+
+ bind(L_2TAG_PACKET_1_0_2);
+ paddd(xmm0, xmm4);
+ por(xmm1, xmm3);
+ movdl(edx, xmm0);
+ psllq(xmm0, 29);
+ pand(xmm5, xmm1);
+ pand(xmm0, xmm6);
+ subsd(xmm1, xmm5);
+ mulpd(xmm5, xmm0);
+ andl(eax, 32752);
+ subl(eax, ecx);
+ cvtsi2sdl(xmm7, eax);
+ mulsd(xmm1, xmm0);
+ movsd(xmm6, Address(tmp, 2064)); // 0xfefa3800UL, 0x3fa62e42UL
+ movdqu(xmm3, Address(tmp, 2080)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
+ subsd(xmm5, xmm2);
+ andl(edx, 16711680);
+ shrl(edx, 12);
+ movdqu(xmm0, Address(tmp, edx));
+ movdqu(xmm4, Address(tmp, 2096)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
+ addsd(xmm1, xmm5);
+ movdqu(xmm2, Address(tmp, 2112)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
+ mulsd(xmm6, xmm7);
+ pshufd(xmm5, xmm1, 68);
+ mulsd(xmm7, Address(tmp, 2072)); // 0x93c76730UL, 0x3ceef357UL, 0x92492492UL, 0x3fc24924UL
+ mulsd(xmm3, xmm1);
+ addsd(xmm0, xmm6);
+ mulpd(xmm4, xmm5);
+ mulpd(xmm5, xmm5);
+ pshufd(xmm6, xmm0, 228);
+ addsd(xmm0, xmm1);
+ addpd(xmm4, xmm2);
+ mulpd(xmm3, xmm5);
+ subsd(xmm6, xmm0);
+ mulsd(xmm4, xmm1);
+ pshufd(xmm2, xmm0, 238);
+ addsd(xmm1, xmm6);
+ mulsd(xmm5, xmm5);
+ addsd(xmm7, xmm2);
+ addpd(xmm4, xmm3);
+ addsd(xmm1, xmm7);
+ mulpd(xmm4, xmm5);
+ addsd(xmm1, xmm4);
+ pshufd(xmm5, xmm4, 238);
+ addsd(xmm1, xmm5);
+ addsd(xmm0, xmm1);
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_0_0_2);
+ movsd(xmm0, Address(rsp, 112));
+ movdqu(xmm1, xmm0);
+ addl(eax, 16);
+ cmpl(eax, 32768);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_3_0_2);
+ cmpl(eax, 16);
+ jcc(Assembler::below, L_2TAG_PACKET_4_0_2);
+
+ bind(L_2TAG_PACKET_5_0_2);
+ addsd(xmm0, xmm0);
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_6_0_2);
+ jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
+ cmpl(edx, 0);
+ jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
+ jmp(L_2TAG_PACKET_7_0_2);
+
+ bind(L_2TAG_PACKET_3_0_2);
+ movdl(edx, xmm1);
+ psrlq(xmm1, 32);
+ movdl(ecx, xmm1);
+ addl(ecx, ecx);
+ cmpl(ecx, -2097152);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_6_0_2);
+ orl(edx, ecx);
+ cmpl(edx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
+
+ bind(L_2TAG_PACKET_7_0_2);
+ xorpd(xmm1, xmm1);
+ xorpd(xmm0, xmm0);
+ movl(eax, 32752);
+ pinsrw(xmm1, eax, 3);
+ movl(edx, 3);
+ mulsd(xmm0, xmm1);
+
+ bind(L_2TAG_PACKET_9_0_2);
+ movsd(Address(rsp, 0), xmm0);
+ movsd(xmm0, Address(rsp, 112));
+ fld_d(Address(rsp, 0));
+ jmp(L_2TAG_PACKET_10_0_2);
+
+ bind(L_2TAG_PACKET_8_0_2);
+ xorpd(xmm1, xmm1);
+ xorpd(xmm0, xmm0);
+ movl(eax, 49136);
+ pinsrw(xmm0, eax, 3);
+ divsd(xmm0, xmm1);
+ movl(edx, 2);
+ jmp(L_2TAG_PACKET_9_0_2);
+
+ bind(L_2TAG_PACKET_4_0_2);
+ movdl(edx, xmm1);
+ psrlq(xmm1, 32);
+ movdl(ecx, xmm1);
+ orl(edx, ecx);
+ cmpl(edx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
+ xorpd(xmm1, xmm1);
+ movl(eax, 18416);
+ pinsrw(xmm1, eax, 3);
+ mulsd(xmm0, xmm1);
+ movapd(xmm1, xmm0);
+ pextrw(eax, xmm0, 3);
+ por(xmm0, xmm2);
+ psllq(xmm0, 5);
+ movl(ecx, 18416);
+ psrlq(xmm0, 34);
+ rcpss(xmm0, xmm0);
+ psllq(xmm1, 12);
+ pshufd(xmm6, xmm5, 228);
+ psrlq(xmm1, 12);
+ jmp(L_2TAG_PACKET_1_0_2);
+
+ bind(L_2TAG_PACKET_2_0_2);
+ movsd(Address(rsp, 24), xmm0);
+ fld_d(Address(rsp, 24));
+
+ bind(L_2TAG_PACKET_10_0_2);
+ movl(tmp, Address(rsp, 40));
+}
+
+#endif
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2095,14 +2095,6 @@
void generate_math_stubs() {
{
- StubCodeMark mark(this, "StubRoutines", "log");
- StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
-
- __ fld_d(Address(rsp, 4));
- __ flog();
- __ ret(0);
- }
- {
StubCodeMark mark(this, "StubRoutines", "log10");
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
@@ -3065,6 +3057,32 @@
}
+ address generate_libmLog() {
+ address start = __ pc();
+
+ const XMMRegister x0 = xmm0;
+ const XMMRegister x1 = xmm1;
+ const XMMRegister x2 = xmm2;
+ const XMMRegister x3 = xmm3;
+
+ const XMMRegister x4 = xmm4;
+ const XMMRegister x5 = xmm5;
+ const XMMRegister x6 = xmm6;
+ const XMMRegister x7 = xmm7;
+
+ const Register tmp = rbx;
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+ __ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+
+ }
+
+
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
@@ -3288,6 +3306,7 @@
}
if (VM_Version::supports_sse2()) {
StubRoutines::_dexp = generate_libmExp();
+ StubRoutines::_dlog = generate_libmLog();
}
}
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2974,19 +2974,6 @@
void generate_math_stubs() {
{
- StubCodeMark mark(this, "StubRoutines", "log");
- StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
-
- __ subq(rsp, 8);
- __ movdbl(Address(rsp, 0), xmm0);
- __ fld_d(Address(rsp, 0));
- __ flog();
- __ fstp_d(Address(rsp, 0));
- __ movdbl(xmm0, Address(rsp, 0));
- __ addq(rsp, 8);
- __ ret(0);
- }
- {
StubCodeMark mark(this, "StubRoutines", "log10");
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
@@ -4187,15 +4174,58 @@
#ifdef _WIN64
// save the xmm registers which must be preserved 6-7
- __ movdqu(xmm_save(6), as_XMMRegister(6));
- __ movdqu(xmm_save(7), as_XMMRegister(7));
+ __ subptr(rsp, 4 * wordSize);
+ __ movdqu(Address(rsp, 0), xmm6);
+ __ movdqu(Address(rsp, 2 * wordSize), xmm7);
#endif
__ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
#ifdef _WIN64
// restore xmm regs belonging to calling function
- __ movdqu(as_XMMRegister(6), xmm_save(6));
- __ movdqu(as_XMMRegister(7), xmm_save(7));
+ __ movdqu(xmm6, Address(rsp, 0));
+ __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+ __ addptr(rsp, 4 * wordSize);
+#endif
+
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+
+ }
+
+ address generate_libmLog() {
+ address start = __ pc();
+
+ const XMMRegister x0 = xmm0;
+ const XMMRegister x1 = xmm1;
+ const XMMRegister x2 = xmm2;
+ const XMMRegister x3 = xmm3;
+
+ const XMMRegister x4 = xmm4;
+ const XMMRegister x5 = xmm5;
+ const XMMRegister x6 = xmm6;
+ const XMMRegister x7 = xmm7;
+
+ const Register tmp1 = r11;
+ const Register tmp2 = r8;
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+#ifdef _WIN64
+ // save the xmm registers which must be preserved 6-7
+ __ subptr(rsp, 4 * wordSize);
+ __ movdqu(Address(rsp, 0), xmm6);
+ __ movdqu(Address(rsp, 2 * wordSize), xmm7);
+#endif
+ __ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2);
+
+#ifdef _WIN64
+ // restore xmm regs belonging to calling function
+ __ movdqu(xmm6, Address(rsp, 0));
+ __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+ __ addptr(rsp, 4 * wordSize);
#endif
__ leave(); // required for proper stackwalking of RuntimeStub frame
@@ -4392,7 +4422,10 @@
StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
}
- StubRoutines::_dexp = generate_libmExp();
+ if (VM_Version::supports_sse2()) {
+ StubRoutines::_dexp = generate_libmExp();
+ StubRoutines::_dlog = generate_libmLog();
+ }
}
void generate_all() {
--- a/hotspot/src/cpu/x86/vm/x86.ad Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86.ad Wed Jul 05 20:59:18 2017 +0200
@@ -1707,6 +1707,10 @@
if (!VM_Version::supports_cx8())
ret_value = false;
break;
+ case Op_CMoveVD:
+ if (UseAVX < 1 || UseAVX > 2)
+ ret_value = false;
+ break;
}
return ret_value; // Per default match rules are supported.
@@ -2089,6 +2093,29 @@
interface(REG_INTER);
%}
+// Comparison Code for FP conditional move
+operand cmpOp_vcmppd() %{
+ match(Bool);
+
+ predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
+ n->as_Bool()->_test._test != BoolTest::no_overflow);
+ format %{ "" %}
+ interface(COND_INTER) %{
+ equal (0x0, "eq");
+ less (0x1, "lt");
+ less_equal (0x2, "le");
+ not_equal (0xC, "ne");
+ greater_equal(0xD, "ge");
+ greater (0xE, "gt");
+ //TODO cannot compile (adlc breaks) without two next lines with error:
+ // x86_64.ad(13987) Syntax Error: :In operand cmpOp_vcmppd: Do not support this encode constant: ' %{
+ // equal' for overflow.
+ overflow (0x20, "o"); // not really supported by the instruction
+ no_overflow (0x21, "no"); // not really supported by the instruction
+ %}
+%}
+
+
// INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
// ============================================================================
@@ -7393,6 +7420,22 @@
ins_pipe( pipe_slow );
%}
+instruct vcmov4D_reg(vecY dst, vecY src1, vecY src2, immI8 cop, cmpOp_vcmppd copnd) %{
+ predicate(UseAVX > 0 && UseAVX < 3 && n->as_Vector()->length() == 4);
+ match(Set dst (CMoveVD (Binary copnd cop) (Binary src1 src2)));
+ effect(TEMP dst, USE src1, USE src2);
+ format %{ "cmppd.$copnd $dst, $src1, $src2 ! vcmovevd, cond=$cop\n\t"
+ "vpblendd $dst,$src1,$src2,$dst ! vcmovevd\n\t"
+ %}
+ ins_encode %{
+ int vector_len = 1;
+ int cond = (Assembler::Condition)($copnd$$cmpcode);
+ __ cmppd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cond, vector_len);
+ __ vpblendd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
// --------------------------------- DIV --------------------------------------
// Floats vector div
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Jul 05 20:59:18 2017 +0200
@@ -9950,41 +9950,6 @@
ins_pipe( pipe_slow );
%}
-instruct logDPR_reg(regDPR1 dst, regDPR1 src) %{
- predicate (UseSSE<=1);
- // The source Double operand on FPU stack
- match(Set dst (LogD src));
- // fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
- // fxch ; swap ST(0) with ST(1)
- // fyl2x ; compute log_e(2) * log_2(x)
- format %{ "FLDLN2 \t\t\t#Log_e\n\t"
- "FXCH \n\t"
- "FYL2X \t\t\t# Q=Log_e*Log_2(x)"
- %}
- ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
- Opcode(0xD9), Opcode(0xC9), // fxch
- Opcode(0xD9), Opcode(0xF1)); // fyl2x
-
- ins_pipe( pipe_slow );
-%}
-
-instruct logD_reg(regD dst, regD src, eFlagsReg cr) %{
- predicate (UseSSE>=2);
- effect(KILL cr);
- // The source and result Double operands in XMM registers
- match(Set dst (LogD src));
- // fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
- // fyl2x ; compute log_e(2) * log_2(x)
- format %{ "FLDLN2 \t\t\t#Log_e\n\t"
- "FYL2X \t\t\t# Q=Log_e*Log_2(x)"
- %}
- ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
- Push_SrcD(src),
- Opcode(0xD9), Opcode(0xF1), // fyl2x
- Push_ResultD(dst));
- ins_pipe( pipe_slow );
-%}
-
//-------------Float Instructions-------------------------------
// Float Math
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Jul 05 20:59:18 2017 +0200
@@ -9870,21 +9870,6 @@
ins_pipe( pipe_slow );
%}
-instruct logD_reg(regD dst) %{
- // The source and result Double operands in XMM registers
- match(Set dst (LogD dst));
- // fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
- // fyl2x ; compute log_e(2) * log_2(x)
- format %{ "fldln2\t\t\t#Log_e\n\t"
- "fyl2x\t\t\t# Q=Log_e*Log_2(x)\n\t"
- %}
- ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
- Push_SrcXD(dst),
- Opcode(0xD9), Opcode(0xF1), // fyl2x
- Push_ResultXD(dst));
- ins_pipe( pipe_slow );
-%}
-
instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power
effect(KILL rax, KILL rdx, KILL rcx, KILL cr);
--- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -60,7 +60,7 @@
// ----------------------------------------------------------------------------
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
ShouldNotReachHere(); // Only needed for COMPILER2.
return NULL;
}
--- a/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -59,11 +59,6 @@
ShouldNotCallThis();
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
- CodeBuffer* dst) {
- ShouldNotCallThis();
-}
-
void metadata_Relocation::pd_fix_value(address x) {
ShouldNotCallThis();
}
--- a/hotspot/src/cpu/zero/vm/vm_version_zero.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/vm_version_zero.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -37,4 +37,5 @@
warning("Unaligned memory access is not available on this CPU");
FLAG_SET_DEFAULT(UseUnalignedAccesses, false);
}
+ FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0);
}
--- a/hotspot/src/share/vm/adlc/formssel.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -4006,7 +4006,6 @@
strcmp(opType,"DivD")==0 ||
strcmp(opType,"DivF")==0 ||
strcmp(opType,"DivI")==0 ||
- strcmp(opType,"LogD")==0 ||
strcmp(opType,"Log10D")==0 ||
strcmp(opType,"ModD")==0 ||
strcmp(opType,"ModF")==0 ||
@@ -4141,6 +4140,7 @@
"AddVB","AddVS","AddVI","AddVL","AddVF","AddVD",
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
"MulVS","MulVI","MulVL","MulVF","MulVD",
+ "CMoveVD",
"DivVF","DivVD",
"AbsVF","AbsVD",
"NegVF","NegVD",
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -34,6 +34,7 @@
#include "c1/c1_ValueStack.hpp"
#include "code/debugInfoRec.hpp"
#include "compiler/compileLog.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "runtime/sharedRuntime.hpp"
typedef enum {
@@ -418,9 +419,9 @@
exception_handler_table(),
implicit_exception_table(),
compiler(),
- _env->comp_level(),
has_unsafe_access(),
- SharedRuntime::is_wide_vector(max_vector_size())
+ SharedRuntime::is_wide_vector(max_vector_size()),
+ directive()
);
}
@@ -445,7 +446,7 @@
dependency_recorder()->assert_evol_method(method());
}
- if (method()->break_at_execute()) {
+ if (directive()->BreakAtCompileOption) {
BREAKPOINT;
}
@@ -534,9 +535,10 @@
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
- int osr_bci, BufferBlob* buffer_blob)
+ int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
: _compiler(compiler)
, _env(env)
+, _directive(directive)
, _log(env->log())
, _method(method)
, _osr_bci(osr_bci)
@@ -587,7 +589,6 @@
_env->set_compiler_data(NULL);
}
-
void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
#ifndef PRODUCT
if (PrintExceptionHandlers && Verbose) {
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -67,6 +67,7 @@
int _next_id;
int _next_block_id;
AbstractCompiler* _compiler;
+ DirectiveSet* _directive;
ciEnv* _env;
CompileLog* _log;
ciMethod* _method;
@@ -118,7 +119,7 @@
public:
// creation
Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
- int osr_bci, BufferBlob* buffer_blob);
+ int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
~Compilation();
@@ -128,6 +129,7 @@
// accessors
ciEnv* env() const { return _env; }
+ DirectiveSet* directive() const { return _directive; }
CompileLog* log() const { return _log; }
AbstractCompiler* compiler() const { return _compiler; }
bool has_exception_handlers() const { return _has_exception_handlers; }
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -238,7 +238,7 @@
return true;
}
-void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
+void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
assert(buffer_blob != NULL, "Must exist");
// invoke compilation
@@ -247,7 +247,7 @@
// of Compilation to occur before we release the any
// competing compiler thread
ResourceMark rm;
- Compilation c(this, env, method, entry_bci, buffer_blob);
+ Compilation c(this, env, method, entry_bci, buffer_blob, directive);
}
}
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -26,6 +26,7 @@
#define SHARE_VM_C1_C1_COMPILER_HPP
#include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
// There is one instance of the Compiler per CompilerThread.
@@ -50,7 +51,7 @@
virtual void initialize();
// Compilation entry point for methods
- virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+ virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
// Print compilation timers and statistics
virtual void print_timers();
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -3365,7 +3365,7 @@
// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg
const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
- if ( callee->should_not_inline()) return "disallowed by CompileCommand";
+ if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
if ( callee->dont_inline()) return "don't inline by annotation";
return NULL;
}
@@ -3494,8 +3494,7 @@
{
VM_ENTRY_MARK;
methodHandle mh(THREAD, callee->get_Method());
- methodHandle ct(THREAD, method()->get_Method());
- is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
+ is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
}
if (!is_available) {
@@ -3690,13 +3689,14 @@
}
// now perform tests that are based on flag settings
- if (callee->force_inline() || callee->should_inline()) {
+ bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
+ if (callee->force_inline() || inlinee_by_directive) {
if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel");
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
const char* msg = "";
if (callee->force_inline()) msg = "force inline by annotation";
- if (callee->should_inline()) msg = "force inline by CompileCommand";
+ if (inlinee_by_directive) msg = "force inline by CompileCommand";
print_inlining(callee, msg);
} else {
// use heuristic controls on inlining
@@ -4207,7 +4207,8 @@
event.commit();
}
#endif // INCLUDE_TRACE
- if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
+
+ if (!compilation()->directive()->PrintInliningOption) {
return;
}
CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -731,7 +731,6 @@
case lir_tan:
case lir_sin:
case lir_cos:
- case lir_log:
case lir_log10: {
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
@@ -1769,7 +1768,6 @@
case lir_sin: s = "sin"; break;
case lir_cos: s = "cos"; break;
case lir_tan: s = "tan"; break;
- case lir_log: s = "log"; break;
case lir_log10: s = "log10"; break;
case lir_pow: s = "pow"; break;
case lir_logic_and: s = "logic_and"; break;
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -959,7 +959,6 @@
, lir_sin
, lir_cos
, lir_tan
- , lir_log
, lir_log10
, lir_pow
, lir_logic_and
@@ -2193,7 +2192,6 @@
void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); }
void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
- void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, LIR_OprFact::illegalOpr, to, tmp)); }
void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -738,7 +738,6 @@
case lir_sin:
case lir_tan:
case lir_cos:
- case lir_log:
case lir_log10:
case lir_pow:
intrinsic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -153,8 +153,13 @@
// only the classes below belong in the same file
class LIRGenerator: public InstructionVisitor, public BlockClosure {
+ // LIRGenerator should never get instatiated on the heap.
+ private:
+ void* operator new(size_t size) throw();
+ void* operator new[](size_t size) throw();
+ void operator delete(void* p);
+ void operator delete[](void* p);
- private:
Compilation* _compilation;
ciMethod* _method; // method that we are compiling
PhiResolverState _resolver_state;
@@ -244,7 +249,7 @@
void do_getClass(Intrinsic* x);
void do_currentThread(Intrinsic* x);
void do_MathIntrinsic(Intrinsic* x);
- void do_ExpIntrinsic(Intrinsic* x);
+ void do_LibmIntrinsic(Intrinsic* x);
void do_ArrayCopy(Intrinsic* x);
void do_CompareAndSwap(Intrinsic* x, ValueType* type);
void do_NIOCheckIndex(Intrinsic* x);
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -6586,7 +6586,6 @@
case lir_cos:
case lir_abs:
case lir_log10:
- case lir_log:
case lir_pow:
case lir_logic_and:
case lir_logic_or:
--- a/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -45,8 +45,14 @@
define_stack(IntegerStack, intArray)
define_array(IntegerMap, IntegerStack*)
- class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure {
+ class Verification : public BlockClosure {
+ // RangeCheckEliminator::Verification should never get instatiated on the heap.
private:
+ void* operator new(size_t size) throw();
+ void* operator new[](size_t size) throw();
+ void operator delete(void* p);
+ void operator delete[](void* p);
+
IR *_ir;
boolArray _used;
BlockBeginList _current;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -318,6 +318,7 @@
#endif
FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32());
FUNCTION_CASE(entry, StubRoutines::dexp());
+ FUNCTION_CASE(entry, StubRoutines::dlog());
#undef FUNCTION_CASE
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -38,7 +38,8 @@
#include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp"
@@ -956,9 +957,9 @@
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* inc_table,
AbstractCompiler* compiler,
- int comp_level,
bool has_unsafe_access,
bool has_wide_vectors,
+ DirectiveSet* directives,
RTMState rtm_state) {
VM_ENTRY_MARK;
nmethod* nm = NULL;
@@ -1034,11 +1035,20 @@
debug_info(), dependencies(), code_buffer,
frame_words, oop_map_set,
handler_table, inc_table,
- compiler, comp_level);
+ compiler, task()->comp_level());
+
// Free codeBlobs
code_buffer->free_blob();
if (nm != NULL) {
+ bool printnmethods = directives->PrintAssemblyOption || directives->PrintNMethodsOption;
+ if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+ nm->print_nmethod(printnmethods);
+ }
+ if (directives->PrintAssemblyOption) {
+ Disassembler::decode(nm);
+ }
+
nm->set_has_unsafe_access(has_unsafe_access);
nm->set_has_wide_vectors(has_wide_vectors);
#if INCLUDE_RTM_OPT
@@ -1069,7 +1079,7 @@
char *method_name = method->name_and_sig_as_C_string();
ttyLocker ttyl;
tty->print_cr("Installing method (%d) %s ",
- comp_level,
+ task()->comp_level(),
method_name);
}
// Allow the code to be executed
@@ -1080,7 +1090,7 @@
char *method_name = method->name_and_sig_as_C_string();
ttyLocker ttyl;
tty->print_cr("Installing osr method (%d) %s @ %d",
- comp_level,
+ task()->comp_level(),
method_name,
entry_bci);
}
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -32,9 +32,11 @@
#include "code/dependencies.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "compiler/oopMap.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "runtime/thread.hpp"
class CompileTask;
+class DirectiveSet;
// ciEnv
//
@@ -352,6 +354,7 @@
// The compiler task which has created this env.
// May be useful to find out compile_id, comp_level, etc.
CompileTask* task() { return _task; }
+
// Handy forwards to the task:
int comp_level(); // task()->comp_level()
uint compile_id(); // task()->compile_id()
@@ -367,9 +370,9 @@
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* inc_table,
AbstractCompiler* compiler,
- int comp_level,
bool has_unsafe_access,
bool has_wide_vectors,
+ DirectiveSet* directives,
RTMState rtm_state = NoRTM);
--- a/hotspot/src/share/vm/ci/ciField.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciField.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -190,6 +190,14 @@
// so there is no hacking of finals going on with them.
if (holder->is_anonymous())
return true;
+ // Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
+ // more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
+ if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
+ holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
+ holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
+ holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
+ return true;
+ }
return TrustFinalNonStaticFields;
}
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -35,7 +35,6 @@
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/abstractCompiler.hpp"
-#include "compiler/compilerOracle.hpp"
#include "compiler/methodLiveness.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
@@ -1044,51 +1043,6 @@
}
// ------------------------------------------------------------------
-// ciMethod::should_inline
-//
-// Should this method be inlined during compilation?
-bool ciMethod::should_inline() {
- check_is_loaded();
- VM_ENTRY_MARK;
- methodHandle mh(THREAD, get_Method());
- return CompilerOracle::should_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_not_inline
-//
-// Should this method be disallowed from inlining during compilation?
-bool ciMethod::should_not_inline() {
- check_is_loaded();
- VM_ENTRY_MARK;
- methodHandle mh(THREAD, get_Method());
- return CompilerOracle::should_not_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_print_assembly
-//
-// Should the compiler print the generated code for this method?
-bool ciMethod::should_print_assembly() {
- check_is_loaded();
- VM_ENTRY_MARK;
- methodHandle mh(THREAD, get_Method());
- return CompilerOracle::should_print(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::break_at_execute
-//
-// Should the compiler insert a breakpoint into the generated code
-// method?
-bool ciMethod::break_at_execute() {
- check_is_loaded();
- VM_ENTRY_MARK;
- methodHandle mh(THREAD, get_Method());
- return CompilerOracle::should_break_at(mh);
-}
-
-// ------------------------------------------------------------------
// ciMethod::has_option
//
bool ciMethod::has_option(const char* option) {
@@ -1101,20 +1055,12 @@
// ------------------------------------------------------------------
// ciMethod::has_option_value
//
-template<typename T>
-bool ciMethod::has_option_value(const char* option, T& value) {
+bool ciMethod::has_option_value(const char* option, double& value) {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::has_option_value(mh, option, value);
}
-// Explicit instantiation for all OptionTypes supported.
-template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
-template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
-template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
-template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
-template bool ciMethod::has_option_value<double>(const char* option, double& value);
-
// ------------------------------------------------------------------
// ciMethod::can_be_compiled
//
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -104,8 +104,6 @@
void load_code();
- void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
-
bool ensure_method_data(methodHandle h_m);
void code_at_put(int bci, Bytecodes::Code code) {
@@ -120,6 +118,8 @@
void assert_call_type_ok(int bci);
public:
+ void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
+
// Basic method information.
ciFlags flags() const { check_is_loaded(); return _flags; }
ciSymbol* name() const { return _name; }
@@ -265,14 +265,8 @@
// Find the proper vtable index to invoke this method.
int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
- // Compilation directives
- bool should_inline();
- bool should_not_inline();
- bool should_print_assembly();
- bool break_at_execute();
bool has_option(const char *option);
- template<typename T>
- bool has_option_value(const char* option, T& value);
+ bool has_option_value(const char* option, double& value);
bool can_be_compiled();
bool can_be_osr_compiled(int entry_bci);
void set_not_compilable(const char* reason = NULL);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -417,36 +417,10 @@
}
}
-bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) {
+bool vmIntrinsics::is_disabled_by_flags(methodHandle method) {
vmIntrinsics::ID id = method->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
- // Check if the intrinsic corresponding to 'method' has been disabled on
- // the command line by using the DisableIntrinsic flag (either globally
- // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
- // for details).
- // Usually, the compilation context is the caller of the method 'method'.
- // The only case when for a non-recursive method 'method' the compilation context
- // is not the caller of the 'method' (but it is the method itself) is
- // java.lang.ref.Referene::get.
- // For java.lang.ref.Reference::get, the intrinsic version is used
- // instead of the compiled version so that the value in the referent
- // field can be registered by the G1 pre-barrier code. The intrinsified
- // version of Reference::get also adds a memory barrier to prevent
- // commoning reads from the referent field across safepoint since GC
- // can change the referent field's value. See Compile::Compile()
- // in src/share/vm/opto/compile.cpp or
- // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
- // for more details.
- ccstr disable_intr = NULL;
- if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
- (!compilation_context.is_null() &&
- CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
- strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
- ) {
- return true;
- }
-
// -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
// the following switch statement.
if (!InlineNatives) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -202,7 +202,11 @@
template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \
\
/* Concurrency support */ \
- template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
+ template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
+ template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
+ template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
+ template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
+ template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
\
/* class symbols needed by intrinsics */ \
@@ -1402,7 +1406,7 @@
// Returns true if a compiler intrinsic is disabled by command-line flags
// and false otherwise.
- static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context);
+ static bool is_disabled_by_flags(methodHandle method);
};
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -32,7 +32,7 @@
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/bytecode.hpp"
#include "oops/methodData.hpp"
@@ -582,9 +582,6 @@
basic_lock_owner_sp_offset,
basic_lock_sp_offset, oop_maps);
NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm));
- if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
- Disassembler::decode(nm);
- }
}
// verify nmethod
debug_only(if (nm) nm->verify();) // might block
@@ -666,9 +663,6 @@
}
}
NOT_PRODUCT(if (nm != NULL) note_java_nmethod(nm));
- if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
- Disassembler::decode(nm);
- }
}
}
// Do verification and logging outside CodeCache_lock.
@@ -908,13 +902,6 @@
_method->is_static() == (entry_point() == _verified_entry_point),
" entry points must be same for static methods and vice versa");
}
-
- bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
- || CompilerOracle::should_print(_method)
- || CompilerOracle::has_option_string(_method, "PrintNMethods");
- if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
- print_nmethod(printnmethods);
- }
}
// Print a short set of xml attributes to identify this nmethod. The
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -26,6 +26,7 @@
#define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
#include "ci/compilerInterface.hpp"
+#include "compiler/compilerDirectives.hpp"
typedef void (*initializer)(void);
@@ -114,36 +115,33 @@
// Determine if the current compiler provides an intrinsic
// for method 'method'. An intrinsic is available if:
- // - the intrinsic is enabled (by using the appropriate command-line flag) and
+ // - the intrinsic is enabled (by using the appropriate command-line flag,
+ // the command-line compile ommand, or a compiler directive)
// - the platform on which the VM is running supports the intrinsic
// (i.e., the platform provides the instructions necessary for the compiler
// to generate the intrinsic code).
//
- // The second parameter, 'compilation_context', is needed to implement functionality
- // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
- // be used to prohibit the compilers to use an intrinsic. There are three ways to
- // disable an intrinsic using the DisableIntrinsic flag:
+ // The directive provides the compilation context and includes pre-evaluated values
+ // dependent on VM flags, compile commands, and compiler directives.
//
- // (1) -XX:DisableIntrinsic=_hashCode,_getClass
- // Disables intrinsification of _hashCode and _getClass globally
- // (i.e., the intrinsified version the methods will not be used at all).
- // (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
- // Disables intrinsification of _hashCode if it is called from
- // aClass::aMethod (but not for any other call site of _hashCode)
- // (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
- // Some methods are not compiled by C2. Instead, the C2 compiler
- // returns directly the intrinsified version of these methods.
- // The command above forces C2 to compile _Reference_get, but
- // allows using the intrinsified version of _Reference_get at all
- // other call sites.
- //
- // From the modes above, (1) disable intrinsics globally, (2) and (3)
- // disable intrinsics on a per-method basis. In cases (2) and (3) the
- // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
- // respectively.
- virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+ // Usually, the compilation context is the caller of the method 'method'.
+ // The only case when for a non-recursive method 'method' the compilation context
+ // is not the caller of the 'method' (but it is the method itself) is
+ // java.lang.ref.Referene::get.
+ // For java.lang.ref.Reference::get, the intrinsic version is used
+ // instead of the compiled version so that the value in the referent
+ // field can be registered by the G1 pre-barrier code. The intrinsified
+ // version of Reference::get also adds a memory barrier to prevent
+ // commoning reads from the referent field across safepoint since GC
+ // can change the referent field's value. See Compile::Compile()
+ // in src/share/vm/opto/compile.cpp or
+ // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
+ // for more details.
+
+ virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) {
return is_intrinsic_supported(method) &&
- !vmIntrinsics::is_disabled_by_flags(method, compilation_context);
+ !directive->is_intrinsic_disabled(method) &&
+ !vmIntrinsics::is_disabled_by_flags(method);
}
// Determines if an intrinsic is supported by the compiler, that is,
@@ -176,7 +174,7 @@
void set_state (int state);
void set_shut_down () { set_state(shut_down); }
// Compilation entry point for methods
- virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+ virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
ShouldNotReachHere();
}
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -29,6 +29,7 @@
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp"
+#include "compiler/directivesParser.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/methodData.hpp"
@@ -202,10 +203,22 @@
static CompilationLog* _compilation_log = NULL;
-void compileBroker_init() {
+bool compileBroker_init() {
if (LogEvents) {
_compilation_log = new CompilationLog();
}
+
+ // init directives stack, adding default directive
+ DirectivesStack::init();
+
+ if (DirectivesParser::has_file()) {
+ return DirectivesParser::parse_from_flag();
+ } else if (PrintCompilerDirectives) {
+ // Print default directive even when no other was added
+ DirectivesStack::print(tty);
+ }
+
+ return true;
}
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
@@ -1180,12 +1193,16 @@
return true;
}
+ // Breaking the abstraction - directives are only used inside a compilation otherwise.
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
+ bool excluded = directive->ExcludeOption;
+ DirectivesStack::release(directive);
+
// The method may be explicitly excluded by the user.
- bool quietly;
double scale;
- if (CompilerOracle::should_exclude(method, quietly)
- || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
- if (!quietly) {
+ if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
+ bool quietly = CompilerOracle::should_exclude_quietly();
+ if (PrintCompilation && !quietly) {
// This does not happen quietly...
ResourceMark rm;
tty->print("### Excluding %s:%s",
@@ -1194,7 +1211,7 @@
method->print_short_name(tty);
tty->cr();
}
- method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompileCommand");
+ method->set_not_compilable(comp_level, !quietly, "excluded by CompileCommand");
}
return false;
@@ -1357,7 +1374,6 @@
ThreadInVMfromNative tv(thread);
ResetNoHandleMark rnhm;
-
if (!comp->is_shark()) {
// Perform per-thread and global initializations
comp->initialize();
@@ -1629,6 +1645,10 @@
}
}
+int DirectivesStack::_depth = 0;
+CompilerDirectives* DirectivesStack::_top = NULL;
+CompilerDirectives* DirectivesStack::_bottom = NULL;
+
// ------------------------------------------------------------------
// CompileBroker::invoke_compiler_on_method
//
@@ -1655,16 +1675,20 @@
bool should_log = (thread->log() != NULL);
bool should_break = false;
int task_level = task->comp_level();
+
+ // Look up matching directives
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(task->method(), compiler(task_level));
+
+ should_break = directive->BreakAtExecuteOption || task->check_break_at_flags();
+ if (should_log && !directive->LogOption) {
+ should_log = false;
+ }
{
// create the handle inside it's own block so it can't
// accidentally be referenced once the thread transitions to
// native. The NoHandleMark before the transition should catch
// any cases where this occurs in the future.
methodHandle method(thread, task->method());
- should_break = check_break_at(method, compile_id, is_osr);
- if (should_log && !CompilerOracle::should_log(method)) {
- should_log = false;
- }
assert(!method->is_native(), "no longer compile natives");
// Save information about this method in case of failure.
@@ -1732,7 +1756,7 @@
locker.wait(Mutex::_no_safepoint_check_flag);
}
}
- comp->compile_method(&ci_env, target, osr_bci);
+ comp->compile_method(&ci_env, target, osr_bci, directive);
}
if (!ci_env.failing() && task->code() == NULL) {
@@ -1762,6 +1786,7 @@
post_compile(thread, task, event, !ci_env.failing(), &ci_env);
}
+ DirectivesStack::release(directive);
pop_jni_handle_block();
methodHandle method(thread, task->method());
@@ -1947,21 +1972,6 @@
JNIHandleBlock::release_block(compile_handles, thread); // may block
}
-
-// ------------------------------------------------------------------
-// CompileBroker::check_break_at
-//
-// Should the compilation break at the current compilation.
-bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) {
- if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
- return true;
- } else if( CompilerOracle::should_break_at(method) ) { // break when compiling
- return true;
- } else {
- return (compile_id == CIBreakAt);
- }
-}
-
// ------------------------------------------------------------------
// CompileBroker::collect_statistics
//
@@ -2232,3 +2242,4 @@
st->cr();
#endif
}
+
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -28,8 +28,10 @@
#include "ci/compilerInterface.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileTask.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "runtime/perfData.hpp"
#include "trace/tracing.hpp"
+#include "utilities/stack.hpp"
class nmethod;
class nmethodLocker;
@@ -129,13 +131,12 @@
~CompileTaskWrapper();
};
-
// Compilation
//
// The broker for all compilation requests.
class CompileBroker: AllStatic {
friend class Threads;
- friend class CompileTaskWrapper;
+ friend class CompileTaskWrapper;
public:
enum {
@@ -238,7 +239,6 @@
static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
static void push_jni_handle_block();
static void pop_jni_handle_block();
- static bool check_break_at(methodHandle method, int compile_id, bool is_osr);
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
static void compile_method_base(methodHandle method,
@@ -253,7 +253,11 @@
static bool init_compiler_runtime();
static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
- public:
+public:
+
+ static DirectivesStack* dirstack();
+ static void set_dirstack(DirectivesStack* stack);
+
enum {
// The entry bci used for non-OSR compilations.
standard_entry_bci = InvocationEntryBci
@@ -267,6 +271,7 @@
static bool compilation_is_in_queue(methodHandle method);
static void print_compile_queues(outputStream* st);
+ static void print_directives(outputStream* st);
static int queue_size(int comp_level) {
CompileQueue *q = compile_queue(comp_level);
return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/compiler/compileTask.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -26,6 +26,7 @@
#include "compiler/compileTask.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
CompileTask* CompileTask::_task_free_list = NULL;
#ifdef ASSERT
@@ -372,6 +373,19 @@
}
// ------------------------------------------------------------------
+// CompileTask::check_break_at_flags
+bool CompileTask::check_break_at_flags() {
+ int compile_id = this->_compile_id;
+ bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
+
+ if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
+ return true;
+ } else {
+ return (compile_id == CIBreakAt);
+ }
+}
+
+// ------------------------------------------------------------------
// CompileTask::print_inlining
void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
// 1234567
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/compilerOracle.hpp"
+
+CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
+ _c1_store = new DirectiveSet(this);
+ _c2_store = new DirectiveSet(this);
+};
+
+CompilerDirectives::~CompilerDirectives() {
+ if (_c1_store != NULL) {
+ delete _c1_store;
+ }
+ if (_c2_store != NULL) {
+ delete _c2_store;
+ }
+
+ // remove all linked method matchers
+ BasicMatcher* tmp = _match;
+ while (tmp != NULL) {
+ BasicMatcher* next = tmp->next();
+ delete tmp;
+ tmp = next;
+ }
+}
+
+void CompilerDirectives::print(outputStream* st) {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ if (_match != NULL) {
+ st->cr();
+ st->print("Directive:");
+ if (is_default_directive()) {
+ st->print_cr(" (default)");
+ } else {
+ st->cr();
+ }
+ st->print(" matching: ");
+ _match->print(st);
+ BasicMatcher* tmp = _match->next();
+ while (tmp != NULL) {
+ st->print(", ");
+ tmp->print(st);
+ tmp = tmp->next();
+ }
+ st->cr();
+ } else {
+ assert(0, "There should always be a match");
+ }
+
+ if (_c1_store != NULL) {
+ st->print_cr(" c1 directives:");
+ _c1_store->print(st);
+ }
+ if (_c2_store != NULL) {
+ st->cr();
+ st->print_cr(" c2 directives:");
+ _c2_store->print(st);
+ }
+ //---
+}
+
+void CompilerDirectives::finalize() {
+ if (_c1_store != NULL) {
+ _c1_store->finalize();
+ }
+ if (_c2_store != NULL) {
+ _c2_store->finalize();
+ }
+}
+
+void DirectiveSet::finalize() {
+ // if any flag has been modified - set directive as enabled
+ // unless it already has been explicitly set.
+ if (!_modified[EnableIndex]) {
+ if (_inlinematchers != NULL) {
+ EnableOption = true;
+ return;
+ }
+ int i;
+ for (i = 0; i < number_of_flags; i++) {
+ if (_modified[i]) {
+ EnableOption = true;
+ return;
+ }
+ }
+ }
+}
+
+CompilerDirectives* CompilerDirectives::next() {
+ return _next;
+}
+
+bool CompilerDirectives::match(methodHandle method) {
+ if (is_default_directive()) {
+ return true;
+ }
+ if (method == NULL) {
+ return false;
+ }
+ if (_match->match(method)) {
+ return true;
+ }
+ return false;
+}
+
+bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
+ BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
+ if (bm == NULL) {
+ assert(error_msg != NULL, "Must have error message");
+ return false;
+ } else {
+ bm->set_next(_match);
+ _match = bm;
+ return true;
+ }
+}
+
+void CompilerDirectives::inc_refcount() {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ _ref_count++;
+}
+
+void CompilerDirectives::dec_refcount() {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ _ref_count--;
+}
+
+int CompilerDirectives::refcount() {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ return _ref_count;
+}
+
+DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ inc_refcount(); // The compiling thread is responsible to decrement this when finished.
+ if (comp == NULL) { // Xint
+ return _c1_store;
+ } else if (comp->is_c2()) {
+ return _c2_store;
+ } else if (comp->is_c1()) {
+ return _c1_store;
+ } else if (comp->is_shark()) {
+ return NULL;
+ } else if (comp->is_jvmci()) {
+ return NULL;
+ }
+ ShouldNotReachHere();
+ return NULL;
+}
+
+// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
+// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
+// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
+// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
+//
+// To simplify the processing of the list, the canonicalize_disableintrinsic() method
+// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
+ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
+ char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
+ int i = 0;
+ char current;
+ while ((current = option_value[i]) != '\0') {
+ if (current == '\n' || current == ' ') {
+ canonicalized_list[i] = ',';
+ } else {
+ canonicalized_list[i] = current;
+ }
+ i++;
+ }
+ canonicalized_list[i] = '\0';
+ return canonicalized_list;
+}
+
+DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
+#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
+ compilerdirectives_common_flags(init_defaults_definition)
+ compilerdirectives_c2_flags(init_defaults_definition)
+ compilerdirectives_c1_flags(init_defaults_definition)
+ memset(_modified, 0, sizeof _modified);
+
+ // Canonicalize DisableIntrinsic to contain only ',' as a separator.
+ this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
+}
+
+DirectiveSet::~DirectiveSet() {
+ // remove all linked methodmatchers
+ InlineMatcher* tmp = _inlinematchers;
+ while (tmp != NULL) {
+ InlineMatcher* next = tmp->next();
+ delete tmp;
+ tmp = next;
+ }
+
+ // When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
+ // into a new string. Therefore, that string is deallocated when
+ // the DirectiveSet is destroyed.
+ assert(this->DisableIntrinsicOption != NULL, "");
+ FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
+}
+
+// Backward compatibility for CompileCommands
+// Breaks the abstraction and causes lots of extra complexity
+// - if some option is changed we need to copy directiveset since it no longer can be shared
+// - Need to free copy after use
+// - Requires a modified bit so we don't overwrite options that is set by directives
+
+DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
+ // Early bail out - checking all options is expensive - we rely on them not being used
+ // Only set a flag if it has not been modified and value changes.
+ // Only copy set if a flag needs to be set
+ if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
+ DirectiveSet* set = DirectiveSet::clone(this);
+
+ bool changed = false; // Track if we actually change anything
+
+ // All CompileCommands are not equal so this gets a bit verbose
+ // When CompileCommands have been refactored less clutter will remain.
+ if (CompilerOracle::should_break_at(method)) {
+ if (!_modified[BreakAtCompileIndex]) {
+ set->BreakAtCompileOption = true;
+ changed = true;
+ }
+ if (!_modified[BreakAtExecuteIndex]) {
+ set->BreakAtExecuteOption = true;
+ changed = true;
+ }
+ }
+ if (CompilerOracle::should_log(method)) {
+ if (!_modified[LogIndex]) {
+ set->LogOption = true;
+ changed = true;
+ }
+ }
+ if (CompilerOracle::should_print(method)) {
+ if (!_modified[PrintAssemblyIndex]) {
+ set->PrintAssemblyOption = true;
+ changed = true;
+ }
+ }
+ // Exclude as in should not compile == Enabled
+ if (CompilerOracle::should_exclude(method)) {
+ if (!_modified[ExcludeIndex]) {
+ set->ExcludeOption = true;
+ changed = true;
+ }
+ }
+
+ // inline and dontinline (including exclude) are implemented in the directiveset accessors
+#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
+ compilerdirectives_common_flags(init_default_cc)
+ compilerdirectives_c2_flags(init_default_cc)
+ compilerdirectives_c1_flags(init_default_cc)
+
+ // Canonicalize DisableIntrinsic to contain only ',' as a separator.
+ ccstrlist option_value;
+ if (!_modified[DisableIntrinsicIndex] &&
+ CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
+ set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
+ }
+
+
+ if (!changed) {
+ // We didn't actually update anything, discard.
+ delete set;
+ } else {
+ // We are returning a (parentless) copy. The originals parent don't need to account for this.
+ DirectivesStack::release(this);
+ return set;
+ }
+ }
+ // Nothing changed
+ return this;
+}
+
+CompilerDirectives* DirectiveSet::directive() {
+ assert(_directive != NULL, "Must have been initialized");
+ return _directive;
+}
+
+bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
+ if (_inlinematchers != NULL) {
+ if (_inlinematchers->match(method, InlineMatcher::force_inline)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DirectiveSet::should_inline(ciMethod* inlinee) {
+ inlinee->check_is_loaded();
+ VM_ENTRY_MARK;
+ methodHandle mh(THREAD, inlinee->get_Method());
+
+ if (matches_inline(mh, InlineMatcher::force_inline)) {
+ return true;
+ }
+ if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_inline(mh)) {
+ return true;
+ }
+ return false;
+}
+
+bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
+ inlinee->check_is_loaded();
+ VM_ENTRY_MARK;
+ methodHandle mh(THREAD, inlinee->get_Method());
+
+ if (matches_inline(mh, InlineMatcher::dont_inline)) {
+ return true;
+ }
+ if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_not_inline(mh)) {
+ return true;
+ }
+ return false;
+}
+
+bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
+ InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
+ if (m != NULL) {
+ // add matcher last in chain - the order is significant
+ append_inline(m);
+ return true;
+ } else {
+ assert(error_msg != NULL, "Error message must be set");
+ return false;
+ }
+}
+
+void DirectiveSet::append_inline(InlineMatcher* m) {
+ if (_inlinematchers == NULL) {
+ _inlinematchers = m;
+ return;
+ }
+ InlineMatcher* tmp = _inlinematchers;
+ while (tmp->next() != NULL) {
+ tmp = tmp->next();
+ }
+ tmp->set_next(m);
+}
+
+void DirectiveSet::print_inline(outputStream* st) {
+ if (_inlinematchers == NULL) {
+ st->print_cr(" inline: -");
+ } else {
+ st->print(" inline: ");
+ _inlinematchers->print(st);
+ InlineMatcher* tmp = _inlinematchers->next();
+ while (tmp != NULL) {
+ st->print(", ");
+ tmp->print(st);
+ tmp = tmp->next();
+ }
+ st->cr();
+ }
+}
+
+bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
+ vmIntrinsics::ID id = method->intrinsic_id();
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ ResourceMark rm;
+
+ // Create a copy of the string that contains the list of disabled
+ // intrinsics. The copy is created because the string
+ // will be modified by strtok(). Then, the list is tokenized with
+ // ',' as a separator.
+ size_t length = strlen(DisableIntrinsicOption);
+ char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
+ strncpy(local_list, DisableIntrinsicOption, length + 1);
+
+ char* token = strtok(local_list, ",");
+ while (token != NULL) {
+ if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
+ return true;
+ } else {
+ token = strtok(NULL, ",");
+ }
+ }
+
+ return false;
+}
+
+DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
+ DirectiveSet* set = new DirectiveSet(NULL);
+ memcpy(set->_modified, src->_modified, sizeof(src->_modified));
+
+ InlineMatcher* tmp = src->_inlinematchers;
+ while (tmp != NULL) {
+ set->append_inline(tmp->clone());
+ tmp = tmp->next();
+ }
+
+ #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
+ compilerdirectives_common_flags(copy_members_definition)
+ compilerdirectives_c2_flags(copy_members_definition)
+ compilerdirectives_c1_flags(copy_members_definition)
+
+ // Create a local copy of the DisableIntrinsicOption.
+ assert(src->DisableIntrinsicOption != NULL, "");
+ size_t len = strlen(src->DisableIntrinsicOption) + 1;
+ char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
+ strncpy(s, src->DisableIntrinsicOption, len);
+ assert(s[len-1] == '\0', "");
+ set->DisableIntrinsicOption = s;
+ return set;
+}
+
+// Create a new dirstack and push a default directive
+void DirectivesStack::init() {
+ CompilerDirectives* _default_directives = new CompilerDirectives();
+ char str[] = "*.*";
+ const char* error_msg = NULL;
+ _default_directives->add_match(str, error_msg);
+#ifdef COMPILER1
+ _default_directives->_c1_store->EnableOption = true;
+#endif
+#ifdef COMPILER2
+ _default_directives->_c2_store->EnableOption = true;
+#endif
+ assert(error_msg == NULL, "Must succeed.");
+ push(_default_directives);
+}
+
+DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+ assert(_bottom != NULL, "Must never be empty");
+ return _bottom->get_for(comp);
+}
+
+void DirectivesStack::push(CompilerDirectives* directive) {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+ directive->inc_refcount();
+ if (_top == NULL) {
+ assert(_bottom == NULL, "There can only be one default directive");
+ _bottom = directive; // default directive, can never be removed.
+ }
+
+ directive->set_next(_top);
+ _top = directive;
+ _depth++;
+}
+
+void DirectivesStack::pop() {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+ pop_inner();
+}
+
+void DirectivesStack::pop_inner() {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+
+ if (_top->next() == NULL) {
+ return; // Do nothing - don't allow an empty stack
+ }
+ CompilerDirectives* tmp = _top;
+ _top = _top->next();
+ _depth--;
+
+ DirectivesStack::release(tmp);
+}
+
+void DirectivesStack::clear() {
+ // holding the lock during the whole operation ensuring consistent result
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+ while (_top->next() != NULL) {
+ pop_inner();
+ }
+}
+
+void DirectivesStack::print(outputStream* st) {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+ CompilerDirectives* tmp = _top;
+ while (tmp != NULL) {
+ tmp->print(st);
+ tmp = tmp->next();
+ st->cr();
+ }
+}
+
+void DirectivesStack::release(DirectiveSet* set) {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+ if (set->is_exclusive_copy()) {
+ // Old CompilecCmmands forced us to create an exclusive copy
+ delete set;
+ } else {
+ assert(set->directive() != NULL, "");
+ release(set->directive());
+ }
+}
+
+
+void DirectivesStack::release(CompilerDirectives* dir) {
+ assert(DirectivesStack_lock->owned_by_self(), "");
+ dir->dec_refcount();
+ if (dir->refcount() == 0) {
+ delete dir;
+ }
+}
+
+DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
+ assert(_depth > 0, "Must never be empty");
+ CompilerDirectives* dir = _top;
+ assert(dir != NULL, "Must be initialized");
+
+ DirectiveSet* match = NULL;
+ {
+ MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+ while (dir != NULL) {
+ if (dir->is_default_directive() || dir->match(method)) {
+ match = dir->get_for(comp);
+ if (match == NULL) {
+ // temporary workaround for compilers without directives.
+ if (dir->is_default_directive()) {
+ // default dir is always enabled
+ // match c1 store - it contains all common flags even if C1 is unavailable
+ match = dir->_c1_store;
+ break;
+ }
+ }
+ if (match->EnableOption) {
+ // The directiveSet for this compile is also enabled -> success
+ break;
+ }
+ }
+ dir = dir->next();
+ }
+ }
+
+ guarantee(match != NULL, "There should always be a default directive that matches");
+ // Check for legacy compile commands update, without DirectivesStack_lock
+ return match->compilecommand_compatibility_init(method);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+#define SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+
+#include "ci/ciMetadata.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/methodMatcher.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/exceptions.hpp"
+
+ // Directives flag name, type, default value, compile command name
+ #define compilerdirectives_common_flags(cflags) \
+ cflags(Enable, bool, false, X) \
+ cflags(Exclude, bool, false, X) \
+ cflags(BreakAtExecute, bool, false, X) \
+ cflags(BreakAtCompile, bool, false, X) \
+ cflags(Log, bool, false, X) \
+ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
+ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
+ cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
+ cflags(ReplayInline, bool, false, ReplayInline) \
+ cflags(DumpReplay, bool, false, DumpReplay) \
+ cflags(DumpInline, bool, false, DumpInline) \
+ cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
+ cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic)
+
+#ifdef COMPILER1
+ #define compilerdirectives_c1_flags(cflags)
+#else
+ #define compilerdirectives_c1_flags(cflags)
+#endif
+
+#ifdef COMPILER2
+ #define compilerdirectives_c2_flags(cflags) \
+ cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \
+ cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \
+ cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \
+ cflags(TraceOptoPipelining, bool, false, TraceOptoPipelining) \
+ cflags(TraceOptoOutput, bool, false, TraceOptoOutput) \
+ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \
+ cflags(Vectorize, bool, false, Vectorize) \
+ cflags(VectorizeDebug, bool, false, VectorizeDebug) \
+ cflags(CloneMapDebug, bool, false, CloneMapDebug) \
+ cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
+ NOT_PRODUCT( cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \
+ cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
+#else
+ #define compilerdirectives_c2_flags(cflags)
+#endif
+
+class CompilerDirectives;
+class DirectiveSet;
+
+class DirectivesStack : AllStatic {
+private:
+ static CompilerDirectives* _top;
+ static CompilerDirectives* _bottom;
+ static int _depth;
+
+ static void pop_inner(); // no lock version of pop
+public:
+ static void init();
+ static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
+ static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
+ static void push(CompilerDirectives* directive);
+ static void pop();
+ static void clear();
+ static void print(outputStream* st);
+ static void release(DirectiveSet* set);
+ static void release(CompilerDirectives* dir);
+};
+
+class DirectiveSet : public CHeapObj<mtCompiler> {
+private:
+ InlineMatcher* _inlinematchers;
+ CompilerDirectives* _directive;
+
+ static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
+
+public:
+ DirectiveSet(CompilerDirectives* directive);
+ ~DirectiveSet();
+ CompilerDirectives* directive();
+ bool parse_and_add_inline(char* str, const char*& error_msg);
+ void append_inline(InlineMatcher* m);
+ bool should_inline(ciMethod* inlinee);
+ bool should_not_inline(ciMethod* inlinee);
+ void print_inline(outputStream* st);
+ DirectiveSet* compilecommand_compatibility_init(methodHandle method);
+ bool is_exclusive_copy() { return _directive == NULL; }
+ bool matches_inline(methodHandle method, int inline_action);
+ static DirectiveSet* clone(DirectiveSet const* src);
+ bool is_intrinsic_disabled(methodHandle method);
+ void finalize();
+
+ typedef enum {
+#define enum_of_flags(name, type, dvalue, cc_flag) name##Index,
+ compilerdirectives_common_flags(enum_of_flags)
+ compilerdirectives_c2_flags(enum_of_flags)
+ compilerdirectives_c1_flags(enum_of_flags)
+ number_of_flags
+ } flags;
+
+ bool _modified[number_of_flags];
+
+#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
+ compilerdirectives_common_flags(flag_store_definition)
+ compilerdirectives_c2_flags(flag_store_definition)
+ compilerdirectives_c1_flags(flag_store_definition)
+
+// Casting to get the same function signature for all setters. Used from parser.
+#define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = 1; }
+ compilerdirectives_common_flags(set_function_definition)
+ compilerdirectives_c2_flags(set_function_definition)
+ compilerdirectives_c1_flags(set_function_definition)
+
+ void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } }
+ void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } }
+ void print_double(outputStream* st, ccstr n, double v, bool mod) { if (mod) { st->print("%s:%f ", n, v); } }
+ void print_ccstr(outputStream* st, ccstr n, ccstr v, bool mod) { if (mod) { st->print("%s:%s ", n, v); } }
+ void print_ccstrlist(outputStream* st, ccstr n, ccstr v, bool mod) { print_ccstr(st, n, v, mod); }
+
+void print(outputStream* st) {
+ print_inline(st);
+ st->print(" ");
+#define print_function_definition(name, type, dvalue, cc_flag) print_##type(st, #name, this->name##Option, true);//(bool)_modified[name##Index]);
+ compilerdirectives_common_flags(print_function_definition)
+ compilerdirectives_c2_flags(print_function_definition)
+ compilerdirectives_c1_flags(print_function_definition)
+ st->cr();
+ }
+};
+
+class CompilerDirectives : public CHeapObj<mtCompiler> {
+private:
+ CompilerDirectives* _next;
+ BasicMatcher* _match;
+ int _ref_count;
+
+public:
+
+ CompilerDirectives();
+ ~CompilerDirectives();
+
+ CompilerDirectives* next();
+ void set_next(CompilerDirectives* next) {_next = next; }
+
+ bool match(methodHandle method);
+ BasicMatcher* match() { return _match; }
+ bool add_match(char* str, const char*& error_msg);
+ DirectiveSet* get_for(AbstractCompiler *comp);
+ void print(outputStream* st);
+ bool is_default_directive() { return _next == NULL; }
+ void finalize();
+
+ void inc_refcount();
+ void dec_refcount();
+ int refcount();
+
+ DirectiveSet* _c1_store;
+ DirectiveSet* _c2_store;
+};
+
+#endif // SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -106,6 +106,7 @@
static BasicMatcher* lists[OracleCommandCount] = { 0, };
static TypedMethodOptionMatcher* option_list = NULL;
+static bool any_set = false;
class TypedMethodOptionMatcher : public MethodMatcher {
private:
@@ -292,6 +293,7 @@
matcher->init(option, get_type_for<T>(), option_list);
matcher->set_value<T>(value);
option_list = matcher;
+ any_set = true;
return;
}
@@ -308,7 +310,9 @@
}
bm->set_next(lists[command]);
lists[command] = bm;
-
+ if ((command != DontInlineCommand) && (command != InlineCommand)) {
+ any_set = true;
+ }
return;
}
@@ -324,6 +328,10 @@
return false;
}
+bool CompilerOracle::has_any_option() {
+ return any_set;
+}
+
// Explicit instantiation for all OptionTypes supported.
template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
@@ -337,15 +345,10 @@
return value;
}
-bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
- quietly = true;
- if (lists[ExcludeCommand] != NULL) {
- if (lists[ExcludeCommand]->match(method)) {
- quietly = _quiet;
- return true;
- }
+bool CompilerOracle::should_exclude(methodHandle method) {
+ if (check_predicate(ExcludeCommand, method)) {
+ return true;
}
-
if (lists[CompileOnlyCommand] != NULL) {
return !lists[CompileOnlyCommand]->match(method);
}
@@ -356,8 +359,6 @@
return (check_predicate(InlineCommand, method));
}
-// Check both DontInlineCommand and ExcludeCommand here
-// - consistent behavior for all compilers
bool CompilerOracle::should_not_inline(methodHandle method) {
return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
}
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -46,7 +46,8 @@
static void parse_from_file();
// Tells whether we to exclude compilation of method
- static bool should_exclude(methodHandle method, bool& quietly);
+ static bool should_exclude(methodHandle method);
+ static bool should_exclude_quietly() { return _quiet; }
// Tells whether we want to inline this method
static bool should_inline(methodHandle method);
@@ -71,6 +72,9 @@
template<typename T>
static bool has_option_value(methodHandle method, const char* option, T& value);
+ // Fast check if there is any option available that compile control needs to know about
+ static bool has_any_option();
+
// Reads from string instead of file
static void parse_from_string(const char* command_string, void (*parser)(char*));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
+#include <string.h>
+
+void DirectivesParser::push_tmp(CompilerDirectives* dir) {
+ dir->set_next(_tmp_top);
+ _tmp_top = dir;
+}
+
+CompilerDirectives* DirectivesParser::pop_tmp() {
+ if (_tmp_top == NULL) {
+ return NULL;
+ }
+ CompilerDirectives* tmp = _tmp_top;
+ _tmp_top = _tmp_top->next();
+ tmp->set_next(NULL);
+ return tmp;
+}
+
+bool DirectivesParser::parse_string(const char* text, outputStream* st) {
+ DirectivesParser cd(text, st);
+ if (cd.valid()) {
+ return cd.install_directives();
+ }
+ st->flush();
+ st->print_cr("Parsing of compiler directives failed");
+ return false;
+}
+
+bool DirectivesParser::has_file() {
+ return CompilerDirectivesFile != NULL;
+}
+
+bool DirectivesParser::parse_from_flag() {
+ return parse_from_file(CompilerDirectivesFile, tty);
+}
+
+bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
+ assert(filename != NULL, "Test before calling this");
+ if (!parse_from_file_inner(filename, st)) {
+ st->print_cr("Could not load file: %s", filename);
+ return false;
+ }
+ return true;
+}
+
+bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
+ struct stat st;
+ ResourceMark rm;
+ if (os::stat(filename, &st) == 0) {
+ // found file, open it
+ int file_handle = os::open(filename, 0, 0);
+ if (file_handle != -1) {
+ // read contents into resource array
+ char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
+ size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
+ buffer[num_read] = '\0';
+ // close file
+ os::close(file_handle);
+ return parse_string(buffer, stream);
+ }
+ }
+ return false;
+}
+
+bool DirectivesParser::install_directives() {
+ // Pop from internal temporary stack and push to compileBroker.
+ CompilerDirectives* tmp = pop_tmp();
+ int i = 0;
+ while (tmp != NULL) {
+ i++;
+ DirectivesStack::push(tmp);
+ tmp = pop_tmp();
+ }
+ if (i == 0) {
+ _st->print_cr("No directives in file");
+ return false;
+ } else {
+ _st->print_cr("%i compiler directives added", i);
+ if (PrintCompilerDirectives) {
+ // Print entire directives stack after new has been pushed.
+ DirectivesStack::print(_st);
+ }
+ return true;
+ }
+}
+
+DirectivesParser::DirectivesParser(const char* text, outputStream* st)
+: JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) {
+#ifndef PRODUCT
+ memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
+#endif
+ parse();
+}
+
+DirectivesParser::~DirectivesParser() {
+}
+
+const DirectivesParser::key DirectivesParser::keys[] = {
+ // name, keytype, allow_array, allowed_mask, set_function
+ { "c1", type_c1, 0, mask(type_directives), NULL, UnknownFlagType },
+ { "c2", type_c2, 0, mask(type_directives), NULL, UnknownFlagType },
+ { "match", type_match, 1, mask(type_directives), NULL, UnknownFlagType },
+ { "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+ { "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+ { "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+
+ // Global flags
+ #define common_flag_key(name, type, dvalue, compiler) \
+ { #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
+ compilerdirectives_common_flags(common_flag_key)
+ compilerdirectives_c2_flags(common_flag_key)
+ compilerdirectives_c1_flags(common_flag_key)
+ #undef common_flag_key
+};
+
+const DirectivesParser::key DirectivesParser::dir_array_key = {
+ "top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::dir_key = {
+ "top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::value_array_key = {
+ "value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
+};
+
+const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
+ for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
+ if (strncasecmp(keys[i].name, str, len) == 0) {
+ return &keys[i];
+ }
+ }
+ return NULL;
+}
+
+uint DirectivesParser::mask(keytype kt) {
+ return 1 << (kt + 1);
+}
+
+bool DirectivesParser::push_key(const char* str, size_t len) {
+ bool result = true;
+ const key* k = lookup_key(str, len);
+
+ if (k == NULL) {
+ // os::strdup
+ char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
+ strncpy(s, str, len);
+ s[len] = '\0';
+ error(KEY_ERROR, "No such key: '%s'.", s);
+ FREE_C_HEAP_ARRAY(char, s);
+ return false;
+ }
+
+ return push_key(k);
+}
+
+bool DirectivesParser::push_key(const key* k) {
+ assert(k->allowedmask != 0, "not allowed anywhere?");
+
+ // Exceeding the stack should not be possible with a valid compiler directive,
+ // and an invalid should abort before this happens
+ assert(depth < MAX_DEPTH, "exceeded stack depth");
+ if (depth >= MAX_DEPTH) {
+ error(INTERNAL_ERROR, "Stack depth exceeded.");
+ return false;
+ }
+
+ assert(stack[depth] == NULL, "element not nulled, something is wrong");
+
+ if (depth == 0 && !(k->allowedmask & 1)) {
+ error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
+ return false;
+ }
+
+ if (depth > 0) {
+ const key* prev = stack[depth - 1];
+ if (!(k->allowedmask & mask(prev->type))) {
+ error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
+ return false;
+ }
+ }
+
+ stack[depth] = k;
+ depth++;
+ return true;
+}
+
+const DirectivesParser::key* DirectivesParser::current_key() {
+ assert(depth > 0, "getting key from empty stack");
+ if (depth == 0) {
+ return NULL;
+ }
+ return stack[depth - 1];
+}
+
+const DirectivesParser::key* DirectivesParser::pop_key() {
+ assert(depth > 0, "popping empty stack");
+ if (depth == 0) {
+ error(INTERNAL_ERROR, "Popping empty stack.");
+ return NULL;
+ }
+ depth--;
+
+ const key* k = stack[depth];
+#ifndef PRODUCT
+ stack[depth] = NULL;
+#endif
+
+ return k;
+}
+
+bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
+
+ void (DirectiveSet::*test)(void *args);
+ test = option_key->set;
+
+ switch (t) {
+ case JSON_TRUE:
+ if (option_key->flag_type != boolFlag) {
+ error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+ return false;
+ } else {
+ bool val = true;
+ (set->*test)((void *)&val);
+ }
+ break;
+
+ case JSON_FALSE:
+ if (option_key->flag_type != boolFlag) {
+ error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+ return false;
+ } else {
+ bool val = false;
+ (set->*test)((void *)&val);
+ }
+ break;
+
+ case JSON_NUMBER_INT:
+ if (option_key->flag_type != intxFlag) {
+ if (option_key->flag_type == doubleFlag) {
+ double dval = (double)v->int_value;
+ (set->*test)((void *)&dval);
+ break;
+ }
+ error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
+ return false;
+ } else {
+ intx ival = v->int_value;
+ (set->*test)((void *)&ival);
+ }
+ break;
+
+ case JSON_NUMBER_FLOAT:
+ if (option_key->flag_type != doubleFlag) {
+ error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
+ return false;
+ } else {
+ double dval = v->double_value;
+ (set->*test)((void *)&dval);
+ }
+ break;
+
+ case JSON_STRING:
+ if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
+ error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
+ return false;
+ } else {
+ char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler);
+ strncpy(s, v->str.start, v->str.length + 1);
+ s[v->str.length] = '\0';
+ (set->*test)((void *)&s);
+ }
+ break;
+
+ default:
+ assert(0, "Should not reach here.");
+ }
+ return true;
+}
+
+bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
+
+ const key* option_key = pop_key();
+ const key* enclosing_key = current_key();
+
+ if (option_key->type == value_array_key.type) {
+ // Multi value array, we are really setting the value
+ // for the key one step further up.
+ option_key = pop_key();
+ enclosing_key = current_key();
+
+ // Repush option_key and multi value marker, since
+ // we need to keep them until all multi values are set.
+ push_key(option_key);
+ push_key(&value_array_key);
+ }
+
+ switch (option_key->type) {
+ case type_flag:
+ {
+ if (current_directiveset == NULL) {
+ assert(depth == 2, "Must not have active directive set");
+
+ if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
+ return false;
+ }
+ if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
+ return false;
+ }
+ } else {
+ assert(depth > 2, "Must have active current directive set");
+ if (!set_option_flag(t, v, option_key, current_directiveset)) {
+ return false;
+ }
+ }
+ break;
+ }
+
+ case type_match:
+ if (t != JSON_STRING) {
+ error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+ return false;
+ }
+ if (enclosing_key->type != type_directives) {
+ error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
+ return false;
+ }
+ {
+ char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+ strncpy(s, v->str.start, v->str.length);
+ s[v->str.length] = '\0';
+
+ const char* error_msg = NULL;
+ if (!current_directive->add_match(s, error_msg)) {
+ assert (error_msg != NULL, "Must have valid error message");
+ error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+ }
+ FREE_C_HEAP_ARRAY(char, s);
+ }
+ break;
+
+ case type_inline:
+ if (t != JSON_STRING) {
+ error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+ return false;
+ }
+ {
+ //char* s = strndup(v->str.start, v->str.length);
+ char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+ strncpy(s, v->str.start, v->str.length);
+ s[v->str.length] = '\0';
+
+ const char* error_msg = NULL;
+ if (current_directiveset == NULL) {
+ if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
+ assert (error_msg != NULL, "Must have valid error message");
+ error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+ }
+ if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
+ assert (error_msg != NULL, "Must have valid error message");
+ error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+ }
+ } else {
+ if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
+ assert (error_msg != NULL, "Must have valid error message");
+ error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, s);
+ }
+ break;
+
+ case type_c1:
+ current_directiveset = current_directive->_c1_store;
+ if (t != JSON_TRUE && t != JSON_FALSE) {
+ error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+ return false;
+ }
+ break;
+
+ case type_c2:
+ current_directiveset = current_directive->_c2_store;
+ if (t != JSON_TRUE && t != JSON_FALSE) {
+ error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+ return false;
+ }
+ break;
+
+ case type_enable:
+ switch (enclosing_key->type) {
+ case type_c1:
+ case type_c2:
+ {
+ if (t != JSON_TRUE && t != JSON_FALSE) {
+ error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name);
+ return false;
+ }
+ int val = (t == JSON_TRUE);
+ current_directiveset->set_Enable(&val);
+ break;
+ }
+
+ case type_directives:
+ error(VALUE_ERROR, "Enable keyword not available for generic directive");
+ return false;
+
+ default:
+ error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name);
+ ShouldNotReachHere();
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
+ const key* k;
+
+ if (depth == 0) {
+ switch (t) {
+ case JSON_ARRAY_BEGIN:
+ return push_key(&dir_array_key);
+
+ case JSON_OBJECT_BEGIN:
+ // push synthetic dir_array
+ push_key(&dir_array_key);
+ assert(depth == 1, "Make sure the stack are aligned with the directives");
+ break;
+
+ default:
+ error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+ return false;
+ }
+ }
+ if (depth == 1) {
+ switch (t) {
+ case JSON_OBJECT_BEGIN:
+ // Parsing a new directive.
+ current_directive = new CompilerDirectives();
+ return push_key(&dir_key);
+
+ case JSON_ARRAY_END:
+ k = pop_key();
+
+ if (k->type != type_dir_array) {
+ error(SYNTAX_ERROR, "Expected end of directives array");
+ return false;
+ }
+ return true;
+
+ default:
+ error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+ return false;
+ }
+ } else {
+ switch (t) {
+ case JSON_OBJECT_BEGIN:
+ k = current_key();
+ switch (k->type) {
+ case type_c1:
+ current_directiveset = current_directive->_c1_store;
+ return true;
+ case type_c2:
+ current_directiveset = current_directive->_c2_store;
+ return true;
+
+ case type_dir_array:
+ return push_key(&dir_key);
+
+ default:
+ error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
+ return false;
+ }
+ return false;
+
+ case JSON_OBJECT_END:
+ k = pop_key();
+ switch (k->type) {
+ case type_c1:
+ case type_c2:
+ // This is how we now if options apply to a single or both directive sets
+ current_directiveset = NULL;
+ break;
+
+ case type_directives:
+ // Check, finish and push to stack!
+ if (current_directive->match() == NULL) {
+ error(INTERNAL_ERROR, "Directive missing required match.");
+ return false;
+ }
+ current_directive->finalize();
+ push_tmp(current_directive);
+ current_directive = NULL;
+ break;
+
+ default:
+ error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
+ ShouldNotReachHere();
+ return false;
+ }
+ return true;
+
+ case JSON_ARRAY_BEGIN:
+ k = current_key();
+ if (!(k->allow_array_value)) {
+ if (k->type == type_dir_array) {
+ error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
+ } else {
+ error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
+ }
+ return false;
+ }
+ return push_key(&value_array_key);
+
+ case JSON_ARRAY_END:
+ k = pop_key(); // Pop multi value marker
+ assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
+ k = pop_key(); // Pop key for option that was set
+ return true;
+
+ case JSON_KEY:
+ return push_key(v->str.start, v->str.length);
+
+ case JSON_STRING:
+ case JSON_NUMBER_INT:
+ case JSON_NUMBER_FLOAT:
+ case JSON_TRUE:
+ case JSON_FALSE:
+ case JSON_NULL:
+ return set_option(t, v);
+
+ default:
+ error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
+ ShouldNotReachHere();
+ return false;
+ }
+ }
+}
+
+#ifndef PRODUCT
+void DirectivesParser::test(const char* text, bool should_pass) {
+ DirectivesParser cd(text, tty);
+ if (should_pass) {
+ assert(cd.valid() == true, "failed on a valid DirectivesParser string");
+ if (VerboseInternalVMTests) {
+ tty->print("-- DirectivesParser test passed as expected --\n");
+ }
+ } else {
+ assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string");
+ if (VerboseInternalVMTests) {
+ tty->print("-- DirectivesParser test failed as expected --\n");
+ }
+ }
+}
+
+bool DirectivesParser::test() {
+ DirectivesParser::test("{}", false);
+ DirectivesParser::test("[]", true);
+ DirectivesParser::test("[{}]", false);
+ DirectivesParser::test("[{},{}]", false);
+ DirectivesParser::test("{},{}", false);
+
+ DirectivesParser::test(
+ "[" "\n"
+ " {" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ " inline : \"+java/util.*\"," "\n"
+ " PrintAssembly: true," "\n"
+ " BreakAtExecute: true," "\n"
+ " }" "\n"
+ "]" "\n", true);
+
+ DirectivesParser::test(
+ "[" "\n"
+ " [" "\n"
+ " {" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ " inline : \"+java/util.*\"," "\n"
+ " PrintAssembly: true," "\n"
+ " BreakAtExecute: true," "\n"
+ " }" "\n"
+ " ]" "\n"
+ "]" "\n", false);
+
+ /*DirectivesParser::test(
+ "[" "\n"
+ " {" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ " c1: {"
+ " PrintIntrinsics: false," "\n"
+ " }" "\n"
+ " }" "\n"
+ "]" "\n", false);*/
+
+ DirectivesParser::test(
+ "[" "\n"
+ " {" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ " c2: {" "\n"
+ " PrintInlining: false," "\n"
+ " }" "\n"
+ " }" "\n"
+ "]" "\n", true);
+
+ DirectivesParser::test(
+ "[" "\n"
+ " {" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ " PrintInlining: [" "\n"
+ " true," "\n"
+ " false" "\n"
+ " ]," "\n"
+ " }" "\n"
+ "]" "\n", false);
+
+ DirectivesParser::test(
+ "[" "\n"
+ " {"
+ " // pattern to match against class+method+signature" "\n"
+ " // leading and trailing wildcard (*) allowed" "\n"
+ " match: \"foo/bar.*\"," "\n"
+ "" "\n"
+ " // override defaults for specified compiler" "\n"
+ " // we may differentiate between levels too. TBD." "\n"
+ " c1: {" "\n"
+ " //override c1 presets " "\n"
+ " DumpReplay: false," "\n"
+ " BreakAtCompile: true," "\n"
+ " }," "\n"
+ "" "\n"
+ " c2: {" "\n"
+ " // control inlining of method" "\n"
+ " // + force inline, - dont inline" "\n"
+ " inline : \"+java/util.*\"," "\n"
+ " PrintInlining: true," "\n"
+ " }," "\n"
+ "" "\n"
+ " // directives outside a specific preset applies to all compilers" "\n"
+ " inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
+ " BreakAtExecute: true," "\n"
+ " Log: true," "\n"
+ " }," "\n"
+ " {" "\n"
+ " // matching several patterns require an array" "\n"
+ " match: [\"baz.*\",\"frob.*\"]," "\n"
+ "" "\n"
+ " // applies to all compilers" "\n"
+ " // + force inline, - dont inline" "\n"
+ " inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
+ " PrintInlining: true," "\n"
+ "" "\n"
+ " // force matching compiles to be blocking/syncronous" "\n"
+ " PrintNMethods: true" "\n"
+ " }," "\n"
+ "]" "\n", true);
+
+ // Test max stack depth
+ DirectivesParser::test(
+ "[" "\n" // depth 1: type_dir_array
+ " {" "\n" // depth 2: type_directives
+ " match: \"*.*\"," // match required
+ " c1:" "\n" // depth 3: type_c1
+ " {" "\n"
+ " inline:" "\n" // depth 4: type_inline
+ " [" "\n" // depth 5: type_value_array
+ " \"foo\"," "\n"
+ " \"bar\"," "\n"
+ " ]" "\n" // depth 3: pop type_value_array and type_inline keys
+ " }" "\n" // depth 2: pop type_c1 key
+ " }" "\n" // depth 1: pop type_directives key
+ "]" "\n", true); // depth 0: pop type_dir_array key
+
+ // Test max stack depth
+ DirectivesParser::test(
+ "[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false);
+
+ DirectivesParser::test(
+ "[" "\n"
+ " {" "\n"
+ " c1: true," "\n"
+ " c2: true," "\n"
+ " match: true," "\n"
+ " inline: true," "\n"
+ " enable: true," "\n"
+ " c1: {" "\n"
+ " preset: true," "\n"
+ " }" "\n"
+ " }" "\n"
+ "]" "\n", false);
+
+ return true;
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+#define SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+
+#include "utilities/json.hpp"
+#include "compiler/compilerDirectives.hpp"
+
+enum FlagType {
+ boolFlag,
+ intxFlag,
+ doubleFlag,
+ ccstrFlag,
+ ccstrlistFlag,
+ UnknownFlagType
+};
+
+static const char* flag_type_names[] = {
+ "bool",
+ "int",
+ "double",
+ "string",
+ "string list",
+ "unknown"
+};
+
+class DirectivesParser : public JSON {
+public:
+ static bool has_file();
+ static bool parse_from_flag();
+ static bool parse_from_file(const char* filename, outputStream* st);
+ static bool parse_string(const char* string, outputStream* st);
+ bool install_directives();
+
+private:
+ DirectivesParser(const char* text, outputStream* st);
+ ~DirectivesParser();
+
+ bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+ static bool parse_from_file_inner(const char* filename, outputStream* st);
+
+ // types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
+ typedef enum {
+ type_c1,
+ type_c2,
+ type_enable,
+ type_preset,
+ type_match,
+ type_inline,
+
+ // After here, there is no correlation between
+ // keytype and keys array
+ //type_strategy,
+ type_flag,
+ //type_dir,
+
+ // Synthetic.
+ type_dir_array,
+ type_directives,
+ type_value_array
+ } keytype;
+
+ // name, type, dtd info and maybe a setter
+ // this is how we map key-values
+ typedef struct {
+ const char *name;
+ keytype type;
+ uint allow_array_value : 1;
+ uint allowedmask;
+ void (DirectiveSet::*set)(void* arg);
+ FlagType flag_type;
+ } key;
+
+ // Array with valid keys for the directive file
+ static const key keys[];
+ // Marker for outermost moosewings/array
+ static const key dir_array_key;
+ // Marker for a directives set (these are "implicit" objects, as in not named)
+ static const key dir_key;
+ // Marker for a multi value
+ static const key value_array_key;
+
+ // A compiler directive shouldn't be able to use more than 5 stack slots.
+ // Example of max stack usage:
+ // depth 1: type_dir_array [
+ // depth 2: type_directives {
+ // depth 3: type_c1 c1: {
+ // depth 4: type_inline inline:
+ // depth 5: type_value_array [ ...
+ static const uint MAX_DEPTH = 5;
+ const key* stack[MAX_DEPTH];
+ uint depth;
+
+ bool push_key(const char* str, size_t len);
+ bool push_key(const key* k);
+ const key* current_key();
+ const key* pop_key();
+ static const key* lookup_key(const char* s, size_t len);
+
+ bool set_option(JSON_TYPE t, JSON_VAL* v);
+ bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
+
+ CompilerDirectives* current_directive;
+ DirectiveSet* current_directiveset;
+
+ void push_tmp(CompilerDirectives* dir);
+ CompilerDirectives* pop_tmp();
+ CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
+
+ static uint mask(keytype kt);
+
+#ifndef PRODUCT
+ static void test(const char* json, bool valid);
+public:
+ static bool test();
+#endif
+};
+
+#endif // SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
--- a/hotspot/src/share/vm/compiler/methodMatcher.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -320,13 +320,11 @@
}
void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
- ResourceMark rm;
-
if (mode == Suffix || mode == Substring || mode == Any) {
st->print("*");
}
if (mode != Any) {
- h->print_symbol_on(st);
+ h->print_utf8_on(st);
}
if (mode == Prefix || mode == Substring) {
st->print("*");
@@ -334,14 +332,117 @@
}
void MethodMatcher::print_base(outputStream* st) {
+ ResourceMark rm;
+
print_symbol(st, class_name(), _class_mode);
st->print(".");
print_symbol(st, method_name(), _method_mode);
if (signature() != NULL) {
- signature()->print_symbol_on(st);
+ signature()->print_utf8_on(st);
}
}
+BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+ assert(error_msg == NULL, "Don't call here with error_msg already set");
+ BasicMatcher* bm = new BasicMatcher();
+ MethodMatcher::parse_method_pattern(line, error_msg, bm);
+ if (error_msg != NULL) {
+ delete bm;
+ return NULL;
+ }
+ // check for bad trailing characters
+ int bytes_read = 0;
+ sscanf(line, "%*[ \t]%n", &bytes_read);
+ if (line[bytes_read] != '\0') {
+ error_msg = "Unrecognized trailing text after method pattern";
+ delete bm;
+ return NULL;
+ }
+ return bm;
+}
+
+bool BasicMatcher::match(methodHandle method) {
+ for (BasicMatcher* current = this; current != NULL; current = current->next()) {
+ if (current->matches(method)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void InlineMatcher::print(outputStream* st) {
+ if (_inline_action == InlineMatcher::force_inline) {
+ st->print("+");
+ } else {
+ st->print("-");
+ }
+ print_base(st);
+}
+
+InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+ assert(error_msg == NULL, "Dont call here with error_msg already set");
+ InlineMatcher* im = new InlineMatcher();
+ MethodMatcher::parse_method_pattern(line, error_msg, im);
+ if (error_msg != NULL) {
+ delete im;
+ return NULL;
+ }
+ return im;
+}
+bool InlineMatcher::match(methodHandle method, int inline_action) {
+ for (InlineMatcher* current = this; current != NULL; current = current->next()) {
+ if (current->matches(method)) {
+ return (current->_inline_action == inline_action);
+ }
+ }
+ return false;
+}
+InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error_msg) {
+ // check first token is +/-
+ InlineType _inline_action;
+ switch (str[0]) {
+ case '-':
+ _inline_action = InlineMatcher::dont_inline;
+ break;
+ case '+':
+ _inline_action = InlineMatcher::force_inline;
+ break;
+ default:
+ error_msg = "Missing leading inline type (+/-)";
+ return NULL;
+ }
+ str++;
+
+ int bytes_read = 0;
+ assert(error_msg== NULL, "error_msg must not be set yet");
+ InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
+ if (im == NULL) {
+ assert(error_msg != NULL, "Must have error message");
+ return NULL;
+ }
+ im->set_action(_inline_action);
+ return im;
+}
+
+InlineMatcher* InlineMatcher::clone() {
+ InlineMatcher* m = new InlineMatcher();
+ m->_class_mode = _class_mode;
+ m->_method_mode = _method_mode;
+ m->_inline_action = _inline_action;
+ m->_class_name = _class_name;
+ if(_class_name != NULL) {
+ _class_name->increment_refcount();
+ }
+ m->_method_name = _method_name;
+ if (_method_name != NULL) {
+ _method_name->increment_refcount();
+ }
+ m->_signature = _signature;
+ if (_signature != NULL) {
+ _signature->increment_refcount();
+ }
+ return m;
+}
--- a/hotspot/src/share/vm/compiler/methodMatcher.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -81,35 +81,8 @@
_next(next) {
}
- static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg) {
- assert(error_msg == NULL, "Dont call here with error_msg already set");
- BasicMatcher* bm = new BasicMatcher();
- MethodMatcher::parse_method_pattern(line, error_msg, bm);
- if (error_msg != NULL) {
- delete bm;
- return NULL;
- }
-
- // check for bad trailing characters
- int bytes_read = 0;
- sscanf(line, "%*[ \t]%n", &bytes_read);
- if (line[bytes_read] != '\0') {
- error_msg = "Unrecognized trailing text after method pattern";
- delete bm;
- return NULL;
- }
- return bm;
- }
-
- bool match(methodHandle method) {
- for (BasicMatcher* current = this; current != NULL; current = current->next()) {
- if (current->matches(method)) {
- return true;
- }
- }
- return false;
- }
-
+ static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
+ bool match(methodHandle method);
void set_next(BasicMatcher* next) { _next = next; }
BasicMatcher* next() { return _next; }
@@ -122,5 +95,33 @@
}
};
+class InlineMatcher : public MethodMatcher {
+public:
+ enum InlineType {
+ unknown_inline,
+ dont_inline,
+ force_inline
+ };
+
+private:
+ InlineType _inline_action;
+ InlineMatcher * _next;
+
+ InlineMatcher() : MethodMatcher(),
+ _inline_action(unknown_inline), _next(NULL) {
+ }
+
+public:
+ static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
+ bool match(methodHandle method, int inline_action);
+ void print(outputStream* st);
+ void set_next(InlineMatcher* next) { _next = next; }
+ InlineMatcher* next() { return _next; }
+ void set_action(InlineType inline_action) { _inline_action = inline_action; }
+ int inline_action() { return _inline_action; }
+ static InlineMatcher* parse_inline_pattern(char* line, const char*& error_msg);
+ InlineMatcher* clone();
+};
+
#endif // SHARE_VM_COMPILER_METHODMATCHER_HPP
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -145,7 +145,7 @@
// Compilation entry point for methods
-void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
ShouldNotReachHere();
}
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -69,7 +69,7 @@
void bootstrap();
// Compilation entry point for methods
- virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+ virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
--- a/hotspot/src/share/vm/oops/symbol.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/oops/symbol.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -154,6 +154,10 @@
return as_C_string(str, buf_len);
}
+void Symbol::print_utf8_on(outputStream* st) const {
+ st->print("%s", as_C_string());
+}
+
void Symbol::print_symbol_on(outputStream* st) const {
ResourceMark rm;
st = st ? st : tty;
--- a/hotspot/src/share/vm/oops/symbol.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/oops/symbol.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -225,6 +225,7 @@
// Printing
void print_symbol_on(outputStream* st = NULL) const;
+ void print_utf8_on(outputStream* st) const;
void print_on(outputStream* st) const; // First level print
void print_value_on(outputStream* st) const; // Second level print.
--- a/hotspot/src/share/vm/opto/block.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/block.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.inline.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "opto/block.hpp"
#include "opto/cfgnode.hpp"
#include "opto/chaitin.hpp"
@@ -365,7 +366,7 @@
, _node_to_block_mapping(arena)
, _node_latency(NULL)
#ifndef PRODUCT
-, _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining"))
+, _trace_opto_pipelining(C->directive()->TraceOptoPipeliningOption)
#endif
#ifdef ASSERT
, _raw_oops(arena)
--- a/hotspot/src/share/vm/opto/block.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/block.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -368,7 +368,6 @@
class PhaseCFG : public Phase {
friend class VMStructs;
private:
-
// Root of whole program
RootNode* _root;
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -108,7 +108,7 @@
int caller_bci, ciCallProfile& profile,
WarmCallInfo* wci_result) {
// Allows targeted inlining
- if (callee_method->should_inline()) {
+ if (C->directive()->should_inline(callee_method)) {
*wci_result = *(WarmCallInfo::always_hot());
if (C->print_inlining() && Verbose) {
CompileTask::print_inline_indent(inline_level());
@@ -222,12 +222,12 @@
}
// ignore heuristic controls on inlining
- if (callee_method->should_inline()) {
+ if (C->directive()->should_inline(callee_method)) {
set_msg("force inline by CompileCommand");
return false;
}
- if (callee_method->should_not_inline()) {
+ if (C->directive()->should_not_inline(callee_method)) {
set_msg("disallowed by CompileCommand");
return true;
}
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -154,7 +154,7 @@
notproduct(bool, PrintOptoStatistics, false, \
"Print New compiler statistics") \
\
- notproduct(bool, PrintOptoAssembly, false, \
+ diagnostic(bool, PrintOptoAssembly, false, \
"Print New compiler assembly output") \
\
develop_pd(bool, OptoPeephole, \
@@ -342,6 +342,9 @@
product(bool, SuperWordReductions, true, \
"Enable reductions support in superword.") \
\
+ product(bool, UseCMoveUnconditionally, false, \
+ "Use CMove (scalar and vector) ignoring profitability test.") \
+ \
product(bool, DoReserveCopyInSuperWord, true, \
"Create reserve copy of graph in SuperWord.") \
\
@@ -368,18 +371,18 @@
product(bool, UseRDPCForConstantTableBase, false, \
"Use Sparc RDPC instruction for the constant table base.") \
\
- develop(bool, PrintIdealGraph, false, \
+ notproduct(bool, PrintIdealGraph, false, \
"Print ideal graph to XML file / network interface. " \
"By default attempts to connect to the visualizer on a socket.") \
\
- develop(intx, PrintIdealGraphLevel, 0, \
+ notproduct(intx, PrintIdealGraphLevel, 0, \
"Level of detail of the ideal graph printout. " \
- "System-wide value, 0=nothing is printed, 3=all details printed. "\
+ "System-wide value, 0=nothing is printed, 4=all details printed. "\
"Level of detail of printouts can be set on a per-method level " \
"as well by using CompileCommand=option.") \
- range(0, 3) \
+ range(0, 4) \
\
- develop(intx, PrintIdealGraphPort, 4444, \
+ notproduct(intx, PrintIdealGraphPort, 4444, \
"Ideal graph printer to network port") \
range(0, SHRT_MAX) \
\
@@ -632,7 +635,7 @@
develop(bool, PrintDominators, false, \
"Print out dominator trees for GVN") \
\
- notproduct(bool, TraceSpilling, false, \
+ diagnostic(bool, TraceSpilling, false, \
"Trace spilling") \
\
diagnostic(bool, TraceTypeProfile, false, \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -94,15 +94,16 @@
}
}
-void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
assert(is_initialized(), "Compiler thread must be initialized");
bool subsume_loads = SubsumeLoads;
bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
bool eliminate_boxing = EliminateAutoBox;
+
while (!env->failing()) {
// Attempt to compile while subsuming loads into machine instructions.
- Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing);
+ Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
// Check result and retry if appropriate.
if (C.failure_reason() != NULL) {
--- a/hotspot/src/share/vm/opto/c2compiler.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -41,7 +41,8 @@
// Compilation entry point for methods
void compile_method(ciEnv* env,
ciMethod* target,
- int entry_bci);
+ int entry_bci,
+ DirectiveSet* directive);
// sentinel value used to trigger backtracking in compile_method().
static const char* retry_no_subsuming_loads();
--- a/hotspot/src/share/vm/opto/chaitin.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -211,7 +211,7 @@
, _scratch_int_pressure(0, INTPRESSURE)
, _scratch_float_pressure(0, FLOATPRESSURE)
#ifndef PRODUCT
- , _trace_spilling(TraceSpilling || C->method_has_option("TraceSpilling"))
+ , _trace_spilling(C->directive()->TraceSpillingOption)
#endif
{
Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]);
--- a/hotspot/src/share/vm/opto/classes.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/classes.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -64,6 +64,7 @@
macro(ClearArray)
macro(ConstraintCast)
macro(CMoveD)
+macro(CMoveVD)
macro(CMoveF)
macro(CMoveI)
macro(CMoveL)
@@ -161,7 +162,6 @@
macro(LoadRange)
macro(LoadS)
macro(Lock)
-macro(LogD)
macro(Log10D)
macro(Loop)
macro(LoopLimit)
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -464,7 +464,7 @@
Type::Initialize(compile);
_compile->set_scratch_buffer_blob(NULL);
_compile->begin_method();
- _compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name));
+ _compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
}
CompileWrapper::~CompileWrapper() {
_compile->end_method();
@@ -496,7 +496,7 @@
tty->print_cr("** Bailout: Recompile without boxing elimination **");
tty->print_cr("*********************************************************");
}
- if (env()->break_at_compile()) {
+ if (C->directive()->BreakAtCompileOption) {
// Open the debugger when compiling this method.
tty->print("### Breaking when compiling: ");
method()->print_short_name();
@@ -617,9 +617,10 @@
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci,
- bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing )
+ bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
: Phase(Compiler),
_env(ci_env),
+ _directive(directive),
_log(ci_env->log()),
_compile_id(ci_env->compile_id()),
_save_argument_registers(false),
@@ -649,7 +650,7 @@
_dead_node_list(comp_arena()),
_dead_node_count(0),
#ifndef PRODUCT
- _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
+ _trace_opto_output(directive->TraceOptoOutputOption),
_in_dump_cnt(0),
_printer(IdealGraphPrinter::printer()),
#endif
@@ -673,7 +674,11 @@
_interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) {
C = this;
-
+#ifndef PRODUCT
+ if (_printer != NULL) {
+ _printer->set_compile(this);
+ }
+#endif
CompileWrapper cw(this);
if (CITimeVerbose) {
@@ -687,9 +692,9 @@
TraceTime t2(NULL, &_t_methodCompilation, CITime, false);
#ifndef PRODUCT
- bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly");
+ bool print_opto_assembly = directive->PrintOptoAssemblyOption;
if (!print_opto_assembly) {
- bool print_assembly = (PrintAssembly || _method->should_print_assembly());
+ bool print_assembly = directive->PrintAssemblyOption;
if (print_assembly && !Disassembler::can_decode()) {
tty->print_cr("PrintAssembly request changed to PrintOptoAssembly");
print_opto_assembly = true;
@@ -698,12 +703,12 @@
set_print_assembly(print_opto_assembly);
set_parsed_irreducible_loop(false);
- if (method()->has_option("ReplayInline")) {
+ if (directive->ReplayInlineOption) {
_replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level());
}
#endif
- set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
- set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
+ set_print_inlining(directive->PrintInliningOption NOT_PRODUCT( || PrintOptoInlining));
+ set_print_intrinsics(directive->PrintIntrinsicsOption);
set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
@@ -837,8 +842,8 @@
// Drain the list.
Finish_Warm();
#ifndef PRODUCT
- if (_printer && _printer->should_print(_method)) {
- _printer->print_inlining(this);
+ if (_printer && _printer->should_print(1)) {
+ _printer->print_inlining();
}
#endif
@@ -871,10 +876,10 @@
NOT_PRODUCT( verify_barriers(); )
// Dump compilation data to replay it.
- if (method()->has_option("DumpReplay")) {
+ if (directive->DumpReplayOption) {
env()->dump_replay_data(_compile_id);
}
- if (method()->has_option("DumpInline") && (ilt() != NULL)) {
+ if (directive->DumpInlineOption && (ilt() != NULL)) {
env()->dump_inline_data(_compile_id);
}
@@ -918,9 +923,9 @@
frame_size_in_words(), _oop_map_set,
&_handler_table, &_inc_table,
compiler,
- env()->comp_level(),
has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size()),
+ _directive,
rtm_state()
);
@@ -938,9 +943,11 @@
int is_fancy_jump,
bool pass_tls,
bool save_arg_registers,
- bool return_pc )
+ bool return_pc,
+ DirectiveSet* directive)
: Phase(Compiler),
_env(ci_env),
+ _directive(directive),
_log(ci_env->log()),
_compile_id(0),
_save_argument_registers(save_arg_registers),
@@ -1090,7 +1097,7 @@
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
set_decompile_count(0);
- set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
+ set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption);
set_num_loop_opts(LoopOptsCount);
set_do_inlining(Inline);
set_max_inline_size(MaxInlineSize);
@@ -1101,24 +1108,22 @@
set_do_vector_loop(false);
- bool do_vector = false;
if (AllowVectorizeOnDemand) {
- if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) {
+ if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) {
set_do_vector_loop(true);
+ NOT_PRODUCT(if (do_vector_loop() && Verbose) {tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());})
} else if (has_method() && method()->name() != 0 &&
method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
set_do_vector_loop(true);
}
-#ifndef PRODUCT
- if (do_vector_loop() && Verbose) {
- tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());
- }
-#endif
}
+ set_use_cmove(UseCMoveUnconditionally /* || do_vector_loop()*/); //TODO: consider do_vector_loop() mandate use_cmove unconditionally
+ NOT_PRODUCT(if (use_cmove() && Verbose && has_method()) {tty->print("Compile::Init: use CMove without profitability tests for method %s\n", method()->name()->as_quoted_ascii());})
set_age_code(has_method() && method()->profile_aging());
set_rtm_state(NoRTM); // No RTM lock eliding by default
- method_has_option_value("MaxNodeLimit", _max_node_limit);
+ _max_node_limit = _directive->MaxNodeLimitOption;
+
#if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state();
@@ -2091,7 +2096,7 @@
TracePhase tp("optimizer", &timers[_t_optimizer]);
#ifndef PRODUCT
- if (env()->break_at_compile()) {
+ if (_directive->BreakAtCompileOption) {
BREAKPOINT;
}
@@ -4357,7 +4362,6 @@
return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
}
-const char* CloneMap::debug_option_name = "CloneMapDebug";
CloneMap& Compile::clone_map() { return _clone_map; }
void Compile::set_clone_map(Dict* d) { _clone_map._dict = d; }
--- a/hotspot/src/share/vm/opto/compile.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -374,6 +374,7 @@
bool _do_count_invocations; // True if we generate code to count invocations
bool _do_method_data_update; // True if we generate code to update MethodData*s
bool _do_vector_loop; // True if allowed to execute loop in parallel iterations
+ bool _use_cmove; // True if CMove should be used without profitability analysis
bool _age_code; // True if we need to profile code age (decrement the aging counter)
int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
bool _print_assembly; // True if we should dump assembly code for this compilation
@@ -391,6 +392,7 @@
// Compilation environment.
Arena _comp_arena; // Arena with lifetime equivalent to Compile
ciEnv* _env; // CI interface
+ DirectiveSet* _directive; // Compiler directive
CompileLog* _log; // from CompilerThread
const char* _failure_reason; // for record_failure/failing pattern
GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics.
@@ -527,6 +529,10 @@
print_inlining_stream()->print("%s", ss.as_string());
}
+#ifndef PRODUCT
+ IdealGraphPrinter* printer() { return _printer; }
+#endif
+
void log_late_inline(CallGenerator* cg);
void log_inline_id(CallGenerator* cg);
void log_inline_failure(const char* msg);
@@ -578,6 +584,7 @@
// ID for this compilation. Useful for setting breakpoints in the debugger.
int compile_id() const { return _compile_id; }
+ DirectiveSet* directive() const { return _directive; }
// Does this compilation allow instructions to subsume loads? User
// instructions that subsume a load may result in an unschedulable
@@ -651,6 +658,8 @@
void set_do_method_data_update(bool z) { _do_method_data_update = z; }
bool do_vector_loop() const { return _do_vector_loop; }
void set_do_vector_loop(bool z) { _do_vector_loop = z; }
+ bool use_cmove() const { return _use_cmove; }
+ void set_use_cmove(bool z) { _use_cmove = z; }
bool age_code() const { return _age_code; }
void set_age_code(bool z) { _age_code = z; }
int AliasLevel() const { return _AliasLevel; }
@@ -671,10 +680,7 @@
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);
}
- template<typename T>
- bool method_has_option_value(const char * option, T& value) {
- return method() != NULL && method()->has_option_value(option, value);
- }
+
#ifndef PRODUCT
bool trace_opto_output() const { return _trace_opto_output; }
bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
@@ -692,8 +698,8 @@
void begin_method() {
#ifndef PRODUCT
- if (_printer && _printer->should_print(_method)) {
- _printer->begin_method(this);
+ if (_printer && _printer->should_print(1)) {
+ _printer->begin_method();
}
#endif
C->_latest_stage_start_counter.stamp();
@@ -711,8 +717,8 @@
#ifndef PRODUCT
- if (_printer && _printer->should_print(_method)) {
- _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
+ if (_printer && _printer->should_print(level)) {
+ _printer->print_method(CompilerPhaseTypeHelper::to_string(cpt), level);
}
#endif
C->_latest_stage_start_counter.stamp();
@@ -728,7 +734,7 @@
event.commit();
}
#ifndef PRODUCT
- if (_printer && _printer->should_print(_method)) {
+ if (_printer && _printer->should_print(level)) {
_printer->end_method();
}
#endif
@@ -1107,7 +1113,7 @@
// continuation.
Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
int entry_bci, bool subsume_loads, bool do_escape_analysis,
- bool eliminate_boxing);
+ bool eliminate_boxing, DirectiveSet* directive);
// Second major entry point. From the TypeFunc signature, generate code
// to pass arguments from the Java calling convention to the C calling
@@ -1115,7 +1121,7 @@
Compile(ciEnv* ci_env, const TypeFunc *(*gen)(),
address stub_function, const char *stub_name,
int is_fancy_jump, bool pass_tls,
- bool save_arg_registers, bool return_pc);
+ bool save_arg_registers, bool return_pc, DirectiveSet* directive);
// From the TypeFunc signature, generate code to pass arguments
// from Compiled calling convention to Interpreter's calling convention
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -292,11 +292,11 @@
}
-void IdealGraphPrinter::print_inlining(Compile* compile) {
+void IdealGraphPrinter::print_inlining() {
// Print inline tree
if (_should_send_method) {
- InlineTree *inlineTree = compile->ilt();
+ InlineTree *inlineTree = C->ilt();
if (inlineTree != NULL) {
print_inline_tree(inlineTree);
} else {
@@ -306,9 +306,9 @@
}
// Has to be called whenever a method is compiled
-void IdealGraphPrinter::begin_method(Compile* compile) {
+void IdealGraphPrinter::begin_method() {
- ciMethod *method = compile->method();
+ ciMethod *method = C->method();
assert(_output, "output stream must exist!");
assert(method, "null methods are not allowed!");
assert(!_current_method, "current method must be null!");
@@ -662,16 +662,14 @@
}
}
-void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) {
- print(compile, name, (Node *)compile->root(), level, clear_nodes);
+void IdealGraphPrinter::print_method(const char *name, int level, bool clear_nodes) {
+ print(name, (Node *)C->root(), level, clear_nodes);
}
// Print current ideal graph
-void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {
+void IdealGraphPrinter::print(const char *name, Node *node, int level, bool clear_nodes) {
- if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return;
-
- this->C = compile;
+ if (!_current_method || !_should_send_method || !should_print(level)) return;
// Warning, unsafe cast?
_chaitin = (PhaseChaitin *)C->regalloc();
@@ -722,10 +720,8 @@
}
// Should method be printed?
-bool IdealGraphPrinter::should_print(ciMethod* method, int level) {
- intx ideal_graph_level = PrintIdealGraphLevel;
- method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
- return ideal_graph_level >= level;
+bool IdealGraphPrinter::should_print(int level) {
+ return C->directive()->IGVPrintLevelOption >= level;
}
extern const char *NodeClassNames[];
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -127,13 +127,14 @@
bool traverse_outs();
void set_traverse_outs(bool b);
- void print_inlining(Compile* compile);
- void begin_method(Compile* compile);
+ void print_inlining();
+ void begin_method();
void end_method();
- void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false);
- void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false);
+ void print_method(const char *name, int level=1, bool clear_nodes = false);
+ void print(const char *name, Node *root, int level=1, bool clear_nodes = false);
void print_xml(const char *name);
- static bool should_print(ciMethod* method, int level = 1);
+ bool should_print(int level);
+ void set_compile(Compile* compile) {C = compile; }
};
#endif
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -326,9 +326,10 @@
// methods access VM-internal data.
VM_ENTRY_MARK;
methodHandle mh(THREAD, m->get_Method());
- methodHandle ct(THREAD, method()->get_Method());
is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
- !vmIntrinsics::is_disabled_by_flags(mh, ct);
+ !C->directive()->is_intrinsic_disabled(mh) &&
+ !vmIntrinsics::is_disabled_by_flags(mh);
+
}
if (is_available) {
@@ -1368,7 +1369,6 @@
switch (id) {
case vmIntrinsics::_dabs: n = new AbsDNode( arg); break;
case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break;
- case vmIntrinsics::_dlog: n = new LogDNode(C, control(), arg); break;
case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg); break;
default: fatal_unexpected_iid(id); break;
}
@@ -1752,7 +1752,9 @@
case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN");
- case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_math(id) :
+ case vmIntrinsics::_dlog:
+ return StubRoutines::dlog() != NULL ?
+ runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG");
case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
--- a/hotspot/src/share/vm/opto/loopnode.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -1143,7 +1143,7 @@
// dominated in the outer loop by this node chain:
// intcon(1)->If->IfFalse->reserved_copy.
// The original loop is dominated by the the same node chain but IfTrue projection:
-// intcon(1)->If->IfTrue->original_loop.
+// intcon(0)->If->IfTrue->original_loop.
//
// In this implementation of CountedLoopReserveKit the ctor includes create_reserve()
// and the dtor, checks _use_new value.
--- a/hotspot/src/share/vm/opto/loopopts.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -512,8 +512,11 @@
PhiNode* phi = out->as_Phi();
BasicType bt = phi->type()->basic_type();
switch (bt) {
- case T_FLOAT:
- case T_DOUBLE: {
+ case T_DOUBLE:
+ if (C->use_cmove()) {
+ continue; //TODO: maybe we want to add some cost
+ }
+ case T_FLOAT: {
cost += Matcher::float_cmove_cost(); // Could be very expensive
break;
}
@@ -573,7 +576,7 @@
}
}
}
- }
+ }//for
Node* bol = iff->in(1);
assert(bol->Opcode() == Op_Bool, "");
int cmp_op = bol->in(1)->Opcode();
@@ -595,7 +598,8 @@
}
// Check for highly predictable branch. No point in CMOV'ing if
// we are going to predict accurately all the time.
- if (iff->_prob < infrequent_prob ||
+ if (C->use_cmove() && cmp_op == Op_CmpD) ;//keep going
+ else if (iff->_prob < infrequent_prob ||
iff->_prob > (1.0f - infrequent_prob))
return NULL;
--- a/hotspot/src/share/vm/opto/matcher.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2316,7 +2316,8 @@
case Op_CMoveI:
case Op_CMoveL:
case Op_CMoveN:
- case Op_CMoveP: {
+ case Op_CMoveP:
+ case Op_CMoveVD: {
// Restructure into a binary tree for Matching. It's possible that
// we could move this code up next to the graph reshaping for IfNodes
// or vice-versa, but I do not want to debug this for Ladybird.
--- a/hotspot/src/share/vm/opto/output.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -28,6 +28,7 @@
#include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp"
#include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "compiler/oopMap.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/ad.hpp"
@@ -89,9 +90,8 @@
}
-
// Break before main entry point
- if( (_method && _method->break_at_execute())
+ if( (_method && C->directive()->BreakAtExecuteOption)
#ifndef PRODUCT
||(OptoBreakpoint && is_method_compilation())
||(OptoBreakpointOSR && is_osr_compilation())
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2378,13 +2378,13 @@
}
#ifndef PRODUCT
- IdealGraphPrinter *printer = IdealGraphPrinter::printer();
- if (printer && printer->should_print(_method)) {
+ IdealGraphPrinter *printer = C->printer();
+ if (printer && printer->should_print(1)) {
char buffer[256];
sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
bool old = printer->traverse_outs();
printer->set_traverse_outs(true);
- printer->print_method(C, buffer, 4);
+ printer->print_method(buffer, 4);
printer->set_traverse_outs(old);
}
#endif
--- a/hotspot/src/share/vm/opto/runtime.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -159,9 +159,13 @@
const char *name, int is_fancy_jump,
bool pass_tls,
bool save_argument_registers,
- bool return_pc ) {
+ bool return_pc) {
+
+ // Matching the default directive, we currently have no method to match.
+ DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
ResourceMark rm;
- Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc );
+ Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc, directive);
+ DirectivesStack::release(directive);
return C.stub_entry_point();
}
--- a/hotspot/src/share/vm/opto/subnode.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/subnode.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -1510,17 +1510,6 @@
//=============================================================================
//------------------------------Value------------------------------------------
-// Compute log
-const Type *LogDNode::Value( PhaseTransform *phase ) const {
- const Type *t1 = phase->type( in(1) );
- if( t1 == Type::TOP ) return Type::TOP;
- if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
- double d = t1->getd();
- return TypeD::make( StubRoutines::intrinsic_log( d ) );
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
// Compute log10
const Type *Log10DNode::Value( PhaseTransform *phase ) const {
const Type *t1 = phase->type( in(1) );
--- a/hotspot/src/share/vm/opto/subnode.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/subnode.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -477,20 +477,6 @@
virtual const Type *Value( PhaseTransform *phase ) const;
};
-//------------------------------LogDNode---------------------------------------
-// Log_e of a double
-class LogDNode : public Node {
-public:
- LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
- init_flags(Flag_is_expensive);
- C->add_expensive_node(this);
- }
- virtual int Opcode() const;
- const Type *bottom_type() const { return Type::DOUBLE; }
- virtual uint ideal_reg() const { return Op_RegD; }
- virtual const Type *Value( PhaseTransform *phase ) const;
-};
-
//------------------------------Log10DNode---------------------------------------
// Log_10 of a double
class Log10DNode : public Node {
--- a/hotspot/src/share/vm/opto/superword.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -37,6 +37,7 @@
#include "opto/opaquenode.hpp"
#include "opto/superword.hpp"
#include "opto/vectornode.hpp"
+#include "opto/movenode.hpp"
//
// S U P E R W O R D T R A N S F O R M
@@ -55,6 +56,7 @@
_mem_slice_tail(arena(), 8, 0, NULL), // memory slice tails
_node_info(arena(), 8, 0, SWNodeInfo::initial), // info needed per node
_clone_map(phase->C->clone_map()), // map of nodes created in cloning
+ _cmovev_kit(_arena, this), // map to facilitate CMoveVD creation
_align_to_ref(NULL), // memory reference to align vectors to
_disjoint_ptrs(arena(), 8, 0, OrderedPair::initial), // runtime disambiguated pointer pairs
_dg(_arena), // dependence graph
@@ -72,6 +74,7 @@
_num_work_vecs(0), // amount of vector work we have
_num_reductions(0), // amount of reduction work we have
_do_vector_loop(phase->C->do_vector_loop()), // whether to do vectorization/simd style
+ _do_reserve_copy(DoReserveCopyInSuperWord),
_ii_first(-1), // first loop generation index - only if do_vector_loop()
_ii_last(-1), // last loop generation index - only if do_vector_loop()
_ii_order(arena(), 8, 0, 0)
@@ -79,12 +82,9 @@
#ifndef PRODUCT
_vector_loop_debug = 0;
if (_phase->C->method() != NULL) {
- _phase->C->method()->has_option_value("VectorizeDebug", _vector_loop_debug);
+ _vector_loop_debug = phase->C->directive()->VectorizeDebugOption;
}
- _CountedLoopReserveKit_debug = 0;
- if (_phase->C->method() != NULL) {
- _phase->C->method()->has_option_value("DoReserveCopyInSuperWordDebug", _CountedLoopReserveKit_debug);
- }
+
#endif
}
@@ -102,7 +102,18 @@
if (!cl->is_main_loop() ) return; // skip normal, pre, and post loops
// Check for no control flow in body (other than exit)
Node *cl_exit = cl->loopexit();
- if (cl_exit->in(0) != lpt->_head) return;
+ if (cl_exit->in(0) != lpt->_head) {
+ #ifndef PRODUCT
+ if (TraceSuperWord) {
+ tty->print_cr("SuperWord::transform_loop: loop too complicated, cl_exit->in(0) != lpt->_head");
+ tty->print("cl_exit %d", cl_exit->_idx); cl_exit->dump();
+ tty->print("cl_exit->in(0) %d", cl_exit->in(0)->_idx); cl_exit->in(0)->dump();
+ tty->print("lpt->_head %d", lpt->_head->_idx); lpt->_head->dump();
+ lpt->dump_head();
+ }
+ #endif
+ return;
+ }
// Make sure the are no extra control users of the loop backedge
if (cl->back_control()->outcnt() != 1) {
@@ -391,6 +402,10 @@
construct_my_pack_map();
+ if (_do_vector_loop) {
+ merge_packs_to_cmovd();
+ }
+
filter_packs();
schedule();
@@ -1071,6 +1086,17 @@
//------------------------------data_size---------------------------
int SuperWord::data_size(Node* s) {
+ Node* use = NULL; //test if the node is a candidate for CMoveVD optimization, then return the size of CMov
+ if (_do_vector_loop) {
+ use = _cmovev_kit.is_Bool_candidate(s);
+ if (use != NULL) {
+ return data_size(use);
+ }
+ use = _cmovev_kit.is_CmpD_candidate(s);
+ if (use != NULL) {
+ return data_size(use);
+ }
+ }
int bsize = type2aelembytes(velt_basic_type(s));
assert(bsize != 0, "valid size");
return bsize;
@@ -1117,6 +1143,7 @@
if (s1->is_Load()) return false;
int align = alignment(s1);
+ NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: s1 %d, align %d", s1->_idx, align);)
bool changed = false;
int start = s1->is_Store() ? MemNode::ValueIn : 1;
int end = s1->is_Store() ? MemNode::ValueIn+1 : s1->req();
@@ -1131,6 +1158,7 @@
pair->push(t1);
pair->push(t2);
_packset.append(pair);
+ NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: set_alignment(%d, %d, %d)", t1->_idx, t2->_idx, align);)
set_alignment(t1, t2, align);
changed = true;
}
@@ -1152,6 +1180,7 @@
if (s1->is_Store()) return false;
int align = alignment(s1);
+ NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: s1 %d, align %d", s1->_idx, align);)
int savings = -1;
int num_s1_uses = 0;
Node* u1 = NULL;
@@ -1183,6 +1212,7 @@
pair->push(u1);
pair->push(u2);
_packset.append(pair);
+ NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: set_alignment(%d, %d, %d)", u1->_idx, u2->_idx, align);)
set_alignment(u1, u2, align);
changed = true;
}
@@ -1458,6 +1488,196 @@
#endif
}
+//------------------------------merge_packs_to_cmovd---------------------------
+// Merge CMoveD into new vector-nodes
+// We want to catch this pattern and subsume CmpD and Bool into CMoveD
+//
+// SubD ConD
+// / | /
+// / | / /
+// / | / /
+// / | / /
+// / / /
+// / / | /
+// v / | /
+// CmpD | /
+// | | /
+// v | /
+// Bool | /
+// \ | /
+// \ | /
+// \ | /
+// \ | /
+// \ v /
+// CMoveD
+//
+
+void SuperWord::merge_packs_to_cmovd() {
+ for (int i = _packset.length() - 1; i >= 0; i--) {
+ _cmovev_kit.make_cmovevd_pack(_packset.at(i));
+ }
+ #ifndef PRODUCT
+ if (TraceSuperWord) {
+ tty->print_cr("\nSuperWord::merge_packs_to_cmovd(): After merge");
+ print_packset();
+ tty->cr();
+ }
+ #endif
+}
+
+Node* CMoveKit::is_Bool_candidate(Node* def) const {
+ Node* use = NULL;
+ if (!def->is_Bool() || def->in(0) != NULL || def->outcnt() != 1) {
+ return NULL;
+ }
+ for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
+ use = def->fast_out(j);
+ if (!_sw->same_generation(def, use) || !use->is_CMove()) {
+ return NULL;
+ }
+ }
+ return use;
+}
+
+Node* CMoveKit::is_CmpD_candidate(Node* def) const {
+ Node* use = NULL;
+ if (!def->is_Cmp() || def->in(0) != NULL || def->outcnt() != 1) {
+ return NULL;
+ }
+ for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
+ use = def->fast_out(j);
+ if (!_sw->same_generation(def, use) || (use = is_Bool_candidate(use)) == NULL || !_sw->same_generation(def, use)) {
+ return NULL;
+ }
+ }
+ return use;
+}
+
+Node_List* CMoveKit::make_cmovevd_pack(Node_List* cmovd_pk) {
+ Node *cmovd = cmovd_pk->at(0);
+ if (!cmovd->is_CMove()) {
+ return NULL;
+ }
+ if (pack(cmovd) != NULL) { // already in the cmov pack
+ return NULL;
+ }
+ if (cmovd->in(0) != NULL) {
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CMoveD %d has control flow, escaping...", cmovd->_idx); cmovd->dump();})
+ return NULL;
+ }
+
+ Node* bol = cmovd->as_CMove()->in(CMoveNode::Condition);
+ if (!bol->is_Bool()
+ || bol->outcnt() != 1
+ || !_sw->same_generation(bol, cmovd)
+ || bol->in(0) != NULL // BoolNode has control flow!!
+ || _sw->my_pack(bol) == NULL) {
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: Bool %d does not fit CMoveD %d for building vector, escaping...", bol->_idx, cmovd->_idx); bol->dump();})
+ return NULL;
+ }
+ Node_List* bool_pk = _sw->my_pack(bol);
+ if (bool_pk->size() != cmovd_pk->size() ) {
+ return NULL;
+ }
+
+ Node* cmpd = bol->in(1);
+ if (!cmpd->is_Cmp()
+ || cmpd->outcnt() != 1
+ || !_sw->same_generation(cmpd, cmovd)
+ || cmpd->in(0) != NULL // CmpDNode has control flow!!
+ || _sw->my_pack(cmpd) == NULL) {
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CmpD %d does not fit CMoveD %d for building vector, escaping...", cmpd->_idx, cmovd->_idx); cmpd->dump();})
+ return NULL;
+ }
+ Node_List* cmpd_pk = _sw->my_pack(cmpd);
+ if (cmpd_pk->size() != cmovd_pk->size() ) {
+ return NULL;
+ }
+
+ if (!test_cmpd_pack(cmpd_pk, cmovd_pk)) {
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: cmpd pack for CmpD %d failed vectorization test", cmpd->_idx); cmpd->dump();})
+ return NULL;
+ }
+
+ Node_List* new_cmpd_pk = new Node_List();
+ uint sz = cmovd_pk->size() - 1;
+ for (uint i = 0; i <= sz; ++i) {
+ Node* cmov = cmovd_pk->at(i);
+ Node* bol = bool_pk->at(i);
+ Node* cmp = cmpd_pk->at(i);
+
+ new_cmpd_pk->insert(i, cmov);
+
+ map(cmov, new_cmpd_pk);
+ map(bol, new_cmpd_pk);
+ map(cmp, new_cmpd_pk);
+
+ _sw->set_my_pack(cmov, new_cmpd_pk); // and keep old packs for cmp and bool
+ }
+ _sw->_packset.remove(cmovd_pk);
+ _sw->_packset.remove(bool_pk);
+ _sw->_packset.remove(cmpd_pk);
+ _sw->_packset.append(new_cmpd_pk);
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print_cr("CMoveKit::make_cmovevd_pack: added syntactic CMoveD pack"); _sw->print_pack(new_cmpd_pk);})
+ return new_cmpd_pk;
+}
+
+bool CMoveKit::test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk) {
+ Node* cmpd0 = cmpd_pk->at(0);
+ assert(cmpd0->is_Cmp(), "CMoveKit::test_cmpd_pack: should be CmpDNode");
+ assert(cmovd_pk->at(0)->is_CMove(), "CMoveKit::test_cmpd_pack: should be CMoveD");
+ assert(cmpd_pk->size() == cmovd_pk->size(), "CMoveKit::test_cmpd_pack: should be same size");
+ Node* in1 = cmpd0->in(1);
+ Node* in2 = cmpd0->in(2);
+ Node_List* in1_pk = _sw->my_pack(in1);
+ Node_List* in2_pk = _sw->my_pack(in2);
+
+ if (in1_pk != NULL && in1_pk->size() != cmpd_pk->size()
+ || in2_pk != NULL && in2_pk->size() != cmpd_pk->size() ) {
+ return false;
+ }
+
+ // test if "all" in1 are in the same pack or the same node
+ if (in1_pk == NULL) {
+ for (uint j = 1; j < cmpd_pk->size(); j++) {
+ if (cmpd_pk->at(j)->in(1) != in1) {
+ return false;
+ }
+ }//for: in1_pk is not pack but all CmpD nodes in the pack have the same in(1)
+ }
+ // test if "all" in2 are in the same pack or the same node
+ if (in2_pk == NULL) {
+ for (uint j = 1; j < cmpd_pk->size(); j++) {
+ if (cmpd_pk->at(j)->in(2) != in2) {
+ return false;
+ }
+ }//for: in2_pk is not pack but all CmpD nodes in the pack have the same in(2)
+ }
+ //now check if cmpd_pk may be subsumed in vector built for cmovd_pk
+ int cmovd_ind1, cmovd_ind2;
+ if (cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
+ && cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
+ cmovd_ind1 = CMoveNode::IfFalse;
+ cmovd_ind2 = CMoveNode::IfTrue;
+ } else if (cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
+ && cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
+ cmovd_ind2 = CMoveNode::IfFalse;
+ cmovd_ind1 = CMoveNode::IfTrue;
+ }
+ else {
+ return false;
+ }
+
+ for (uint j = 1; j < cmpd_pk->size(); j++) {
+ if (cmpd_pk->at(j)->in(1) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind1)
+ || cmpd_pk->at(j)->in(2) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind2)) {
+ return false;
+ }//if
+ }
+ NOT_PRODUCT(if(_sw->is_trace_cmov()) { tty->print("CMoveKit::test_cmpd_pack: cmpd pack for 1st CmpD %d is OK for vectorization: ", cmpd0->_idx); cmpd0->dump(); })
+ return true;
+}
+
//------------------------------implemented---------------------------
// Can code be generated for pack p?
bool SuperWord::implemented(Node_List* p) {
@@ -1477,21 +1697,31 @@
} else {
retValue = VectorNode::implemented(opc, size, velt_basic_type(p0));
}
+ if (!retValue) {
+ if (is_cmov_pack(p)) {
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::implemented: found cmpd pack"); print_pack(p);})
+ return true;
+ }
+ }
}
return retValue;
}
+bool SuperWord::is_cmov_pack(Node_List* p) {
+ return _cmovev_kit.pack(p->at(0)) != NULL;
+}
//------------------------------same_inputs--------------------------
// For pack p, are all idx operands the same?
-static bool same_inputs(Node_List* p, int idx) {
+bool SuperWord::same_inputs(Node_List* p, int idx) {
Node* p0 = p->at(0);
uint vlen = p->size();
Node* p0_def = p0->in(idx);
for (uint i = 1; i < vlen; i++) {
Node* pi = p->at(i);
Node* pi_def = pi->in(idx);
- if (p0_def != pi_def)
+ if (p0_def != pi_def) {
return false;
+ }
}
return true;
}
@@ -1509,8 +1739,9 @@
// the same. Later, implement PackNode and allow differing, non-vector inputs
// (maybe just the ones from outside the block.)
for (uint i = start; i < end; i++) {
- if (!is_vector_use(p0, i))
+ if (!is_vector_use(p0, i)) {
return false;
+ }
}
// Check if reductions are connected
if (p0->is_reduction()) {
@@ -1541,6 +1772,9 @@
// just the ones outside the block.)
for (uint i = 0; i < p->size(); i++) {
Node* def = p->at(i);
+ if (is_cmov_pack_internal_node(p, def)) {
+ continue;
+ }
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
Node* use = def->fast_out(j);
for (uint k = 0; k < use->req(); k++) {
@@ -1810,14 +2044,14 @@
uint max_vlen_in_bytes = 0;
uint max_vlen = 0;
- NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
-
- CountedLoopReserveKit make_reversable(_phase, _lpt, DoReserveCopyInSuperWord);
-
- NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
-
- if (DoReserveCopyInSuperWord && !make_reversable.has_reserved()) {
- NOT_PRODUCT({tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
+ NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
+
+ CountedLoopReserveKit make_reversable(_phase, _lpt, do_reserve_copy());
+
+ NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
+
+ if (do_reserve_copy() && !make_reversable.has_reserved()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
return;
}
@@ -1830,6 +2064,7 @@
Node* vn = NULL;
Node* low_adr = p->at(0);
Node* first = executed_first(p);
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d executed first, %d executed last in pack", first->_idx, n->_idx); print_pack(p);})
int opc = n->Opcode();
if (n->is_Load()) {
Node* ctl = n->in(MemNode::Control);
@@ -1855,13 +2090,21 @@
} else if (n->is_Store()) {
// Promote value to be stored to vector
Node* val = vector_opd(p, MemNode::ValueIn);
+ if (val == NULL) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
+
Node* ctl = n->in(MemNode::Control);
Node* mem = first->in(MemNode::Memory);
Node* adr = low_adr->in(MemNode::Address);
const TypePtr* atyp = n->adr_type();
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
vlen_in_bytes = vn->as_StoreVector()->memory_size();
- } else if (n->req() == 3) {
+ } else if (n->req() == 3 && !is_cmov_pack(p)) {
// Promote operands to vector
Node* in1 = NULL;
bool node_isa_reduction = n->is_reduction();
@@ -1870,8 +2113,22 @@
in1 = low_adr->in(1);
} else {
in1 = vector_opd(p, 1);
+ if (in1 == NULL) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
}
Node* in2 = vector_opd(p, 2);
+ if (in2 == NULL) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
if (VectorNode::is_invariant_vector(in1) && (node_isa_reduction == false) && (n->is_Add() || n->is_Mul())) {
// Move invariant vector input into second position to avoid register spilling.
Node* tmp = in1;
@@ -1895,10 +2152,71 @@
Node* in = vector_opd(p, 1);
vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
+ } else if (is_cmov_pack(p)) {
+ if (!n->is_CMove()) {
+ continue;
+ }
+ // place here CMoveVDNode
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: print before CMove vectorization"); print_loop(false);})
+ Node* bol = n->in(CMoveNode::Condition);
+ if (!bol->is_Bool() && bol->Opcode() == Op_ExtractI && bol->req() > 1 ) {
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d is not Bool node, trying its in(1) node %d", bol->_idx, bol->in(1)->_idx); bol->dump(); bol->in(1)->dump();})
+ bol = bol->in(1); //may be ExtractNode
+ }
+
+ assert(bol->is_Bool(), "should be BoolNode - too late to bail out!");
+ if (!bol->is_Bool()) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
+
+ int cond = (int)bol->as_Bool()->_test._test;
+ Node* in_cc = _igvn.intcon(cond);
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created intcon in_cc node %d", in_cc->_idx); in_cc->dump();})
+ Node* cc = bol->clone();
+ cc->set_req(1, in_cc);
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created bool cc node %d", cc->_idx); cc->dump();})
+
+ Node* src1 = vector_opd(p, 2); //2=CMoveNode::IfFalse
+ if (src1 == NULL) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
+ Node* src2 = vector_opd(p, 3); //3=CMoveNode::IfTrue
+ if (src2 == NULL) {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
+ BasicType bt = velt_basic_type(n);
+ const TypeVect* vt = TypeVect::make(bt, vlen);
+ vn = new CMoveVDNode(cc, src1, src2, vt);
+ NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created new CMove node %d: ", vn->_idx); vn->dump();})
} else {
+ if (do_reserve_copy()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
ShouldNotReachHere();
}
+
assert(vn != NULL, "sanity");
+ if (vn == NULL) {
+ if (do_reserve_copy()){
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");})
+ return; //and reverse to backup IG
+ }
+ ShouldNotReachHere();
+ }
+
_igvn.register_new_node_with_optimizer(vn);
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
for (uint j = 0; j < p->size(); j++) {
@@ -1918,7 +2236,8 @@
}
#endif
}
- }
+ }//for (int i = 0; i < _block.length(); i++)
+
C->set_max_vector_size(max_vlen_in_bytes);
if (SuperWordLoopUnrollAnalysis) {
@@ -1934,10 +2253,10 @@
}
}
- if (DoReserveCopyInSuperWord) {
+ if (do_reserve_copy()) {
make_reversable.use_new();
}
- NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
+ NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
return;
}
@@ -1951,6 +2270,10 @@
if (same_inputs(p, opd_idx)) {
if (opd->is_Vector() || opd->is_LoadVector()) {
assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector");
+ if (opd_idx == 2 && VectorNode::is_shift(p0)) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("shift's count can't be vector");})
+ return NULL;
+ }
return opd; // input is matching vector
}
if ((opd_idx == 2) && VectorNode::is_shift(p0)) {
@@ -1973,6 +2296,10 @@
_phase->set_ctrl(cnt, _phase->get_ctrl(opd));
}
assert(opd->bottom_type()->isa_int(), "int type only");
+ if (!opd->bottom_type()->isa_int()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should be int type only");})
+ return NULL;
+ }
// Move non constant shift count into vector register.
cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0));
}
@@ -1983,6 +2310,10 @@
return cnt;
}
assert(!opd->is_StoreVector(), "such vector is not expected here");
+ if (opd->is_StoreVector()) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("StoreVector is not expected here");})
+ return NULL;
+ }
// Convert scalar input to vector with the same number of elements as
// p0's vector. Use p0's type because size of operand's container in
// vector should match p0's size regardless operand's size.
@@ -2009,6 +2340,10 @@
Node* pi = p->at(i);
Node* in = pi->in(opd_idx);
assert(my_pack(in) == NULL, "Should already have been unpacked");
+ if (my_pack(in) != NULL) {
+ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should already have been unpacked");})
+ return NULL;
+ }
assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
pk->add_opd(in);
}
@@ -2040,8 +2375,9 @@
for (uint k = 0; k < use->req(); k++) {
Node* n = use->in(k);
if (def == n) {
- if (!is_vector_use(use, k)) {
- _n_idx_list.push(use, k);
+ Node_List* u_pk = my_pack(use);
+ if ((u_pk == NULL || !is_cmov_pack(u_pk) || use->is_CMove()) && !is_vector_use(use, k)) {
+ _n_idx_list.push(use, k);
}
}
}
--- a/hotspot/src/share/vm/opto/superword.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/superword.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -29,6 +29,7 @@
#include "opto/phaseX.hpp"
#include "opto/vectornode.hpp"
#include "utilities/growableArray.hpp"
+#include "libadt/dict.hpp"
//
// S U P E R W O R D T R A N S F O R M
@@ -200,6 +201,24 @@
static const SWNodeInfo initial;
};
+class SuperWord;
+class CMoveKit {
+ friend class SuperWord;
+ private:
+ SuperWord* _sw;
+ Dict* _dict;
+ CMoveKit(Arena* a, SuperWord* sw) : _sw(sw) {_dict = new Dict(cmpkey, hashkey, a);}
+ void* _2p(Node* key) const { return (void*)(intptr_t)key; } // 2 conversion functions to make gcc happy
+ Dict* dict() const { return _dict; }
+ void map(Node* key, Node_List* val) { assert(_dict->operator[](_2p(key)) == NULL, "key existed"); _dict->Insert(_2p(key), (void*)val); }
+ void unmap(Node* key) { _dict->Delete(_2p(key)); }
+ Node_List* pack(Node* key) const { return (Node_List*)_dict->operator[](_2p(key)); }
+ Node* is_Bool_candidate(Node* nd) const; // if it is the right candidate return corresponding CMove* ,
+ Node* is_CmpD_candidate(Node* nd) const; // otherwise return NULL
+ Node_List* make_cmovevd_pack(Node_List* cmovd_pk);
+ bool test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk);
+};//class CMoveKit
+
// JVMCI: OrderedPair is moved up to deal with compilation issues on Windows
//------------------------------OrderedPair---------------------------
// Ordered pair of Node*.
@@ -229,6 +248,7 @@
// Transforms scalar operations into packed (superword) operations.
class SuperWord : public ResourceObj {
friend class SWPointer;
+ friend class CMoveKit;
private:
PhaseIdealLoop* _phase;
Arena* _arena;
@@ -247,8 +267,8 @@
GrowableArray<Node*> _iteration_first; // nodes in the generation that has deps from phi
GrowableArray<Node*> _iteration_last; // nodes in the generation that has deps to phi
GrowableArray<SWNodeInfo> _node_info; // Info needed per node
- CloneMap& _clone_map; // map of nodes created in cloning
-
+ CloneMap& _clone_map; // map of nodes created in cloning
+ CMoveKit _cmovev_kit; // support for vectorization of CMov
MemNode* _align_to_ref; // Memory reference that pre-loop will align to
GrowableArray<OrderedPair> _disjoint_ptrs; // runtime disambiguated pointer pairs
@@ -282,8 +302,11 @@
bool is_trace_mem_slice() { return (_vector_loop_debug & 4) > 0; }
bool is_trace_loop() { return (_vector_loop_debug & 8) > 0; }
bool is_trace_adjacent() { return (_vector_loop_debug & 16) > 0; }
+ bool is_trace_cmov() { return (_vector_loop_debug & 32) > 0; }
+ bool is_trace_loop_reverse() { return (_vector_loop_debug & 64) > 0; }
#endif
bool do_vector_loop() { return _do_vector_loop; }
+ bool do_reserve_copy() { return _do_reserve_copy; }
private:
IdealLoopTree* _lpt; // Current loop tree node
LoopNode* _lp; // Current LoopNode
@@ -292,6 +315,7 @@
bool _race_possible; // In cases where SDMU is true
bool _early_return; // True if we do not initialize
bool _do_vector_loop; // whether to do vectorization/simd style
+ bool _do_reserve_copy; // do reserve copy of the graph(loop) before final modification in output
int _num_work_vecs; // Number of non memory vector operations
int _num_reductions; // Number of reduction expressions applied
int _ii_first; // generation with direct deps from mem phi
@@ -299,7 +323,6 @@
GrowableArray<int> _ii_order;
#ifndef PRODUCT
uintx _vector_loop_debug; // provide more printing in debug mode
- uintx _CountedLoopReserveKit_debug; // for debugging CountedLoopReserveKit
#endif
// Accessors
@@ -360,9 +383,13 @@
bool same_velt_type(Node* n1, Node* n2);
// my_pack
- Node_List* my_pack(Node* n) { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; }
- void set_my_pack(Node* n, Node_List* p) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; }
-
+ Node_List* my_pack(Node* n) { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; }
+ void set_my_pack(Node* n, Node_List* p) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; }
+ // is pack good for converting into one vector node replacing 12 nodes of Cmp, Bool, CMov
+ bool is_cmov_pack(Node_List* p);
+ bool is_cmov_pack_internal_node(Node_List* p, Node* nd) { return is_cmov_pack(p) && !nd->is_CMove(); }
+ // For pack p, are all idx operands the same?
+ bool same_inputs(Node_List* p, int idx);
// CloneMap utilities
bool same_origin_idx(Node* a, Node* b) const;
bool same_generation(Node* a, Node* b) const;
@@ -439,6 +466,8 @@
void construct_my_pack_map();
// Remove packs that are not implemented or not profitable.
void filter_packs();
+ // Merge CMoveD into new vector-nodes
+ void merge_packs_to_cmovd();
// Adjust the memory graph for the packed operations
void schedule();
// Remove "current" from its current position in the memory graph and insert
--- a/hotspot/src/share/vm/opto/vectornode.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/vectornode.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -86,6 +86,9 @@
case Op_MulD:
assert(bt == T_DOUBLE, "must be");
return Op_MulVD;
+ case Op_CMoveD:
+ assert(bt == T_DOUBLE, "must be");
+ return Op_CMoveVD;
case Op_DivF:
assert(bt == T_FLOAT, "must be");
return Op_DivVF;
@@ -185,7 +188,7 @@
(vlen > 1) && is_power_of_2(vlen) &&
Matcher::vector_size_supported(bt, vlen)) {
int vopc = VectorNode::opcode(opc, bt);
- return vopc > 0 && Matcher::match_rule_supported(vopc);
+ return vopc > 0 && Matcher::match_rule_supported(vopc) && (vopc != Op_CMoveD || vlen == 4);
}
return false;
}
--- a/hotspot/src/share/vm/opto/vectornode.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/opto/vectornode.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -44,6 +44,13 @@
init_req(2, n2);
}
+ VectorNode(Node* n1, Node* n2, Node* n3, const TypeVect* vt) : TypeNode(vt, 4) {
+ init_class_id(Class_Vector);
+ init_req(1, n1);
+ init_req(2, n2);
+ init_req(3, n3);
+ }
+
const TypeVect* vect_type() const { return type()->is_vect(); }
uint length() const { return vect_type()->length(); } // Vector length
uint length_in_bytes() const { return vect_type()->length_in_bytes(); }
@@ -253,6 +260,14 @@
virtual int Opcode() const;
};
+//------------------------------CMoveVDNode--------------------------------------
+// Vector multiply double
+class CMoveVDNode : public VectorNode {
+public:
+ CMoveVDNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {}
+ virtual int Opcode() const;
+};
+
//------------------------------MulReductionVINode--------------------------------------
// Vector multiply int as a reduction
class MulReductionVINode : public ReductionNode {
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -3840,7 +3840,9 @@
#if INCLUDE_ALL_GCS
#include "gc/g1/heapRegionRemSet.hpp"
#endif
+#include "compiler/directivesParser.hpp"
#include "memory/guardedMemory.hpp"
+#include "utilities/json.hpp"
#include "utilities/ostream.hpp"
#include "utilities/quickSort.hpp"
#if INCLUDE_VM_STRUCTS
@@ -3904,6 +3906,8 @@
run_unit_test(ObjectMonitor::sanity_checks());
run_unit_test(Test_linked_list());
run_unit_test(TestChunkedList_test());
+ run_unit_test(JSONTest::test());
+ run_unit_test(DirectivesParser::test());
#if INCLUDE_VM_STRUCTS
run_unit_test(VMStructs::test());
#endif
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -551,14 +551,20 @@
method_id = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
+
+ DirectiveSet* directive;
if (compilation_context != NULL) {
compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
- return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch);
+ directive = DirectivesStack::getMatchingDirective(cch, CompileBroker::compiler((int)compLevel));
} else {
- return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL);
+ // Calling with NULL matches default directive
+ directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler((int)compLevel));
}
+ bool result = CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, directive);
+ DirectivesStack::release(directive);
+ return result;
WB_END
WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
@@ -624,6 +630,47 @@
return (mh->queued_for_compilation() || nm != NULL);
WB_END
+WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method))
+ jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+ CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+ methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple));
+ bool result = directive->PrintAssemblyOption;
+ DirectivesStack::release(directive);
+
+ return result;
+WB_END
+
+WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
+ jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+ CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+ methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+
+ ResourceMark rm;
+ const char* error_msg = NULL;
+ char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
+ InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
+
+ if (m == NULL) {
+ assert(error_msg != NULL, "Always have an error message");
+ tty->print_cr("Got error: %s", error_msg);
+ return -1; // Pattern failed
+ }
+
+ // Pattern works - now check if it matches
+ int result;
+ if (m->match(mh, InlineMatcher::force_inline)) {
+ result = 2; // Force inline match
+ } else if (m->match(mh, InlineMatcher::dont_inline)) {
+ result = 1; // Dont inline match
+ } else {
+ result = 0; // No match
+ }
+ delete m;
+ return result;
+WB_END
WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
@@ -1475,6 +1522,13 @@
{CC"matchesMethod",
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
(void*)&WB_MatchesMethod},
+ {CC"matchesInline",
+ CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
+ (void*)&WB_MatchesInline},
+ {CC"shouldPrintAssembly",
+ CC"(Ljava/lang/reflect/Executable;)Z",
+ (void*)&WB_ShouldPrintAssembly},
+
{CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
{CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -3667,6 +3667,9 @@
product(ccstr, CompileCommandFile, NULL, \
"Read compiler commands from this file [.hotspot_compiler]") \
\
+ diagnostic(ccstr, CompilerDirectivesFile, NULL, \
+ "Read compiler directives from this file") \
+ \
product(ccstrlist, CompileCommand, "", \
"Prepend to .hotspot_compiler; e.g. log,java/lang/String.<init>") \
\
@@ -4267,7 +4270,13 @@
"(3) no orphan methods exist for class C (i.e., methods for " \
"which the VM declares an intrinsic but that are not declared "\
"in the loaded class C. " \
- "Check (3) is available only in debug builds.")
+ "Check (3) is available only in debug builds.") \
+ \
+ diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \
+ "Disable backwards compatibility for compile commands.") \
+ \
+ diagnostic(bool, PrintCompilerDirectives, false, \
+ "Print compiler directives on installation.")
/*
* Macros for factoring of globals
--- a/hotspot/src/share/vm/runtime/init.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/init.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -71,7 +71,7 @@
void vtableStubs_init();
void InlineCacheBuffer_init();
void compilerOracle_init();
-void compileBroker_init();
+bool compileBroker_init();
// Initialization after compiler initialization
bool universe_post_init(); // must happen after compiler_init
@@ -131,7 +131,9 @@
vtableStubs_init();
InlineCacheBuffer_init();
compilerOracle_init();
- compileBroker_init();
+ if (!compileBroker_init()) {
+ return JNI_EINVAL;
+ }
VMRegImpl::set_regName();
if (!universe_post_init()) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -90,6 +90,7 @@
Monitor* Compilation_lock = NULL;
Mutex* CompileTaskAlloc_lock = NULL;
Mutex* CompileStatistics_lock = NULL;
+Mutex* DirectivesStack_lock = NULL;
Mutex* MultiArray_lock = NULL;
Monitor* Terminator_lock = NULL;
Monitor* BeforeExit_lock = NULL;
@@ -264,6 +265,7 @@
def(CompiledIC_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks VtableStubs_lock, InlineCacheBuffer_lock
def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true, Monitor::_safepoint_check_always);
def(CompileStatistics_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always);
+ def(DirectivesStack_lock , Mutex , special, true, Monitor::_safepoint_check_never);
def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock
def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -93,6 +93,7 @@
extern Monitor* Compilation_lock; // a lock used to pause compilation
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
+extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives
extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays
extern Monitor* Terminator_lock; // a lock used to guard termination of the vm
extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -2696,6 +2696,12 @@
if (nm != NULL) {
method->set_code(method, nm);
+
+ DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
+ if (directive->PrintAssemblyOption) {
+ Disassembler::decode(nm, tty);
+ }
+ DirectivesStack::release(directive);
}
}
} // Unlock AdapterHandlerLibrary_lock
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -149,8 +149,8 @@
address StubRoutines::_montgomerySquare = NULL;
address StubRoutines::_dexp = NULL;
+address StubRoutines::_dlog = NULL;
-double (* StubRoutines::_intrinsic_log )(double) = NULL;
double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
double (* StubRoutines::_intrinsic_pow )(double, double) = NULL;
double (* StubRoutines::_intrinsic_sin )(double) = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -208,6 +208,7 @@
static address _montgomerySquare;
static address _dexp;
+ static address _dlog;
// These are versions of the java.lang.Math methods which perform
// the same operations as the intrinsic version. They are used for
@@ -215,7 +216,6 @@
// intrinsic version returns the same result as the strict version
// then they can be set to the appropriate function from
// SharedRuntime.
- static double (*_intrinsic_log)(double);
static double (*_intrinsic_log10)(double);
static double (*_intrinsic_pow)(double, double);
static double (*_intrinsic_sin)(double);
@@ -376,18 +376,15 @@
static address montgomeryMultiply() { return _montgomeryMultiply; }
static address montgomerySquare() { return _montgomerySquare; }
- static address dexp() {return _dexp; }
+ static address dexp() { return _dexp; }
+ static address dlog() { return _dlog; }
static address select_fill_function(BasicType t, bool aligned, const char* &name);
static address zero_aligned_words() { return _zero_aligned_words; }
- static double intrinsic_log(double d) {
- assert(_intrinsic_log != NULL, "must be defined");
- return _intrinsic_log(d);
- }
static double intrinsic_log10(double d) {
- assert(_intrinsic_log != NULL, "must be defined");
+ assert(_intrinsic_log10 != NULL, "must be defined");
return _intrinsic_log10(d);
}
static double intrinsic_pow(double d, double d2) {
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -246,12 +246,6 @@
#ifndef REG_COUNT
#define REG_COUNT 0
#endif
-// whole purpose of this function is to work around bug c++/27724 in gcc 4.1.1
-// with optimization turned on it doesn't affect produced code
-static inline uint64_t cast_uint64_t(size_t x)
-{
- return x;
-}
#if INCLUDE_JVMTI
#define JVMTI_STRUCTS(static_field) \
@@ -868,6 +862,7 @@
static_field(StubRoutines, _squareToLen, address) \
static_field(StubRoutines, _mulAdd, address) \
static_field(StubRoutines, _dexp, address) \
+ static_field(StubRoutines, _dlog, address) \
static_field(StubRoutines, _jbyte_arraycopy, address) \
static_field(StubRoutines, _jshort_arraycopy, address) \
static_field(StubRoutines, _jint_arraycopy, address) \
@@ -2069,7 +2064,6 @@
declare_c2_type(TanDNode, Node) \
declare_c2_type(AtanDNode, Node) \
declare_c2_type(SqrtDNode, Node) \
- declare_c2_type(LogDNode, Node) \
declare_c2_type(Log10DNode, Node) \
declare_c2_type(PowDNode, Node) \
declare_c2_type(ReverseBytesINode, Node) \
@@ -2100,6 +2094,7 @@
declare_c2_type(MulVFNode, VectorNode) \
declare_c2_type(MulReductionVFNode, ReductionNode) \
declare_c2_type(MulVDNode, VectorNode) \
+ declare_c2_type(CMoveVDNode, VectorNode) \
declare_c2_type(MulReductionVDNode, ReductionNode) \
declare_c2_type(DivVFNode, VectorNode) \
declare_c2_type(DivVDNode, VectorNode) \
@@ -2896,7 +2891,7 @@
// This macro generates a VMStructEntry line for a nonstatic field
#define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
- { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL },
+ { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, offset_of(typeName, fieldName), NULL },
// This macro generates a VMStructEntry line for a static field
#define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
@@ -2906,7 +2901,7 @@
// nonstatic field, in which the size of the type is also specified.
// The type string is given as NULL, indicating an "opaque" type.
#define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size) \
- { QUOTE(typeName), QUOTE(fieldName), NULL, 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL },
+ { QUOTE(typeName), QUOTE(fieldName), NULL, 0, offset_of(typeName, fieldName), NULL },
// This macro generates a VMStructEntry line for an unchecked
// static field, in which the size of the type is also specified.
@@ -3089,10 +3084,10 @@
//
#define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \
- { QUOTE(name), cast_uint64_t(name) },
+ { QUOTE(name), name },
#define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \
- { name, cast_uint64_t(value) },
+ { name, value },
// This macro generates the sentinel value indicating the end of the list
#define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \
@@ -3540,43 +3535,40 @@
extern "C" {
-// see comments on cast_uint64_t at the top of this file
-#define ASSIGN_CONST_TO_64BIT_VAR(var, expr) \
- JNIEXPORT uint64_t var = cast_uint64_t(expr);
-#define ASSIGN_OFFSET_TO_64BIT_VAR(var, type, field) \
- ASSIGN_CONST_TO_64BIT_VAR(var, offset_of(type, field))
-#define ASSIGN_STRIDE_TO_64BIT_VAR(var, array) \
- ASSIGN_CONST_TO_64BIT_VAR(var, (char*)&array[1] - (char*)&array[0])
+#define STRIDE(array) ((char*)&array[1] - (char*)&array[0])
+
+JNIEXPORT VMStructEntry* gHotSpotVMStructs = VMStructs::localHotSpotVMStructs;
+JNIEXPORT uint64_t gHotSpotVMStructEntryTypeNameOffset = offset_of(VMStructEntry, typeName);
+JNIEXPORT uint64_t gHotSpotVMStructEntryFieldNameOffset = offset_of(VMStructEntry, fieldName);
+JNIEXPORT uint64_t gHotSpotVMStructEntryTypeStringOffset = offset_of(VMStructEntry, typeString);
+JNIEXPORT uint64_t gHotSpotVMStructEntryIsStaticOffset = offset_of(VMStructEntry, isStatic);
+JNIEXPORT uint64_t gHotSpotVMStructEntryOffsetOffset = offset_of(VMStructEntry, offset);
+JNIEXPORT uint64_t gHotSpotVMStructEntryAddressOffset = offset_of(VMStructEntry, address);
+JNIEXPORT uint64_t gHotSpotVMStructEntryArrayStride = STRIDE(gHotSpotVMStructs);
-JNIEXPORT VMStructEntry* gHotSpotVMStructs = VMStructs::localHotSpotVMStructs;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeNameOffset, VMStructEntry, typeName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryFieldNameOffset, VMStructEntry, fieldName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeStringOffset, VMStructEntry, typeString);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryIsStaticOffset, VMStructEntry, isStatic);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryOffsetOffset, VMStructEntry, offset);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryAddressOffset, VMStructEntry, address);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMStructEntryArrayStride, gHotSpotVMStructs);
-JNIEXPORT VMTypeEntry* gHotSpotVMTypes = VMStructs::localHotSpotVMTypes;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryTypeNameOffset, VMTypeEntry, typeName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySuperclassNameOffset, VMTypeEntry, superclassName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsOopTypeOffset, VMTypeEntry, isOopType);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsIntegerTypeOffset, VMTypeEntry, isIntegerType);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsUnsignedOffset, VMTypeEntry, isUnsigned);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySizeOffset, VMTypeEntry, size);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMTypeEntryArrayStride,gHotSpotVMTypes);
-JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants = VMStructs::localHotSpotVMIntConstants;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryNameOffset, VMIntConstantEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryValueOffset, VMIntConstantEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMIntConstantEntryArrayStride, gHotSpotVMIntConstants);
-JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants = VMStructs::localHotSpotVMLongConstants;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryNameOffset, VMLongConstantEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryValueOffset, VMLongConstantEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMLongConstantEntryArrayStride, gHotSpotVMLongConstants);
+JNIEXPORT VMTypeEntry* gHotSpotVMTypes = VMStructs::localHotSpotVMTypes;
+JNIEXPORT uint64_t gHotSpotVMTypeEntryTypeNameOffset = offset_of(VMTypeEntry, typeName);
+JNIEXPORT uint64_t gHotSpotVMTypeEntrySuperclassNameOffset = offset_of(VMTypeEntry, superclassName);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsOopTypeOffset = offset_of(VMTypeEntry, isOopType);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset = offset_of(VMTypeEntry, isIntegerType);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsUnsignedOffset = offset_of(VMTypeEntry, isUnsigned);
+JNIEXPORT uint64_t gHotSpotVMTypeEntrySizeOffset = offset_of(VMTypeEntry, size);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryArrayStride = STRIDE(gHotSpotVMTypes);
+
+JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants = VMStructs::localHotSpotVMIntConstants;
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryNameOffset = offset_of(VMIntConstantEntry, name);
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryValueOffset = offset_of(VMIntConstantEntry, value);
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryArrayStride = STRIDE(gHotSpotVMIntConstants);
+
+JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants = VMStructs::localHotSpotVMLongConstants;
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryNameOffset = offset_of(VMLongConstantEntry, name);
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryValueOffset = offset_of(VMLongConstantEntry, value);
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryArrayStride = STRIDE(gHotSpotVMLongConstants);
JNIEXPORT VMAddressEntry* gHotSpotVMAddresses = VMStructs::localHotSpotVMAddresses;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryNameOffset, VMAddressEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryValueOffset, VMAddressEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMAddressEntryArrayStride, gHotSpotVMAddresses);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryNameOffset = offset_of(VMAddressEntry, name);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryValueOffset = offset_of(VMAddressEntry, value);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryArrayStride = STRIDE(gHotSpotVMAddresses);
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -28,7 +28,6 @@
#include "code/codeCache.hpp"
#include "code/codeCacheExtensions.hpp"
#include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "memory/heapInspection.hpp"
#include "memory/resourceArea.hpp"
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -25,6 +25,8 @@
#include "precompiled.hpp"
#include "classfile/classLoaderStats.hpp"
#include "classfile/compactHashtable.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
#include "gc/shared/vmGCOperations.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/globals.hpp"
@@ -77,6 +79,11 @@
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export, true, false));
+
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
// appropriate permission is created for them
@@ -837,6 +844,38 @@
VMThread::execute(&printCodeCacheOp);
}
+void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
+ DirectivesStack::print(output());
+}
+
+CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _filename("filename","Name of the directives file", "STRING",true) {
+ _dcmdparser.add_dcmd_argument(&_filename);
+}
+
+void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
+ DirectivesParser::parse_from_file(_filename.value(), output());
+}
+
+int CompilerDirectivesAddDCmd::num_arguments() {
+ ResourceMark rm;
+ CompilerDirectivesAddDCmd* dcmd = new CompilerDirectivesAddDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
+void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
+ DirectivesStack::pop();
+}
+
+void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
+ DirectivesStack::clear();
+}
#if INCLUDE_SERVICES
ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -613,4 +613,90 @@
virtual void execute(DCmdSource source, TRAPS);
};
+class CompilerDirectivesPrintDCmd : public DCmd {
+public:
+ CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.directives_print";
+ }
+ static const char* description() {
+ return "Print all active compiler directives.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesRemoveDCmd : public DCmd {
+public:
+ CompilerDirectivesRemoveDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.directives_remove";
+ }
+ static const char* description() {
+ return "Remove latest added compiler directive.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesAddDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<char*> _filename;
+public:
+ CompilerDirectivesAddDCmd(outputStream* output, bool heap);
+ static const char* name() {
+ return "Compiler.directives_add";
+ }
+ static const char* description() {
+ return "Add compiler directives from file.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments();
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesClearDCmd : public DCmd {
+public:
+ CompilerDirectivesClearDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.directives_clear";
+ }
+ static const char* description() {
+ return "Remove all compiler directives.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/shark/sharkCompiler.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -145,7 +145,8 @@
void SharkCompiler::compile_method(ciEnv* env,
ciMethod* target,
- int entry_bci) {
+ int entry_bci,
+ DirectiveSet* directive) {
assert(is_initialized(), "should be");
ResourceMark rm;
const char *name = methodname(
@@ -216,8 +217,8 @@
&handler_table,
&inc_table,
this,
- env->comp_level(),
false,
+ directive(),
false);
}
--- a/hotspot/src/share/vm/shark/sharkCompiler.hpp Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -30,6 +30,7 @@
#include "ci/ciMethod.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkMemoryManager.hpp"
@@ -54,7 +55,7 @@
void initialize();
// Compile a normal (bytecode) method and install it in the VM
- void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+ void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* dirset);
// Print compilation timers and statistics
void print_timers();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * This is not really json in the state it is now.
+ * Some differences:
+ * - Double quotes around the key in an object is not enforced.
+ * i.e you can write: { foo : "bar" } instead of { "foo" : "bar" }.
+ * - Comments are allowed.
+ * - The last element in an object or array can have an ending comma.
+ */
+
+#include "precompiled.hpp"
+#include "utilities/json.hpp"
+#include "utilities/ostream.hpp"
+#include <math.h>
+
+const char* strchrnul_(const char *s, int c) {
+ const char* tmp = strchr(s, c);
+ return tmp == NULL ? s + strlen(s) : tmp;
+}
+
+JSON::JSON(const char* text, bool silent, outputStream* st)
+: start(text), pos(text), mark(text),
+ level(0), line(1), column(0), silent(silent), _valid(true), _st(st)
+{
+}
+
+void JSON::parse() {
+ assert(start != NULL, "Need something to parse");
+ if (start == NULL) {
+ _valid = false;
+ error(INTERNAL_ERROR, "JSON parser was called with a string that was NULL.");
+ } else {
+ _valid = parse_json_value();
+ }
+}
+
+bool JSON::valid() {
+ return _valid;
+}
+
+bool JSON::parse_json_value() {
+ int c;
+
+ c = skip_to_token();
+ if (c == -1) {
+ return false;
+ }
+
+ // Must start with object or array
+ if (level == 0) {
+
+ switch (c) {
+ case '{':
+ if (parse_json_object() == false) {
+ return false;
+ }
+ c = skip_to_token();
+ if (c > 0) {
+ mark_pos();
+ error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+ return false;
+ } else if (c < 0) {
+ return false;
+ }
+ return true;
+
+ case '[':
+ if (parse_json_array() == false) {
+ return false;
+ }
+ c = skip_to_token();
+ if (c > 0) {
+ mark_pos();
+ error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+ return false;
+ } else if (c < 0) {
+ return false;
+ }
+ return true;
+
+ case 0:
+ error(SYNTAX_ERROR, "EOS was encountered before any json declarations");
+ return false;
+
+ default:
+ error(SYNTAX_ERROR, "Json must start with an object or an array.");
+ return false;
+ }
+ } else { // level > 0
+ switch (c) {
+ case '{':
+ return parse_json_object();
+
+ case '[':
+ return parse_json_array();
+
+ case '"':
+ return parse_json_string();
+
+ case '-': case '0':
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ return parse_json_number();
+
+ case 't':
+ return parse_json_symbol("true", JSON_TRUE);
+
+ case 'f':
+ return parse_json_symbol("false", JSON_FALSE);
+
+ case 'n':
+ return parse_json_symbol("null", JSON_NULL);
+
+ case 0:
+ error(SYNTAX_ERROR, "EOS was encountered when expecting a json value.");
+ return false;
+
+ default:
+ error(SYNTAX_ERROR, "Could not parse as a json value (did you forget to quote your strings?).");
+ return false;
+ }
+ }
+}
+
+// Should only be called when we actually have the start of an object
+// Otherwise it is an internal error
+bool JSON::parse_json_object() {
+ NOT_PRODUCT(const char* prev_pos);
+ int c;
+
+ mark_pos();
+ // Check that we are not called in error
+ if (expect_any("{", "object start", INTERNAL_ERROR) <= 0) {
+ return false;
+ }
+
+ if (!callback(JSON_OBJECT_BEGIN, NULL, level++)) {
+ return false;
+ }
+
+ for (;;) {
+ mark_pos();
+ c = skip_to_token();
+ if (c == 0) {
+ error(SYNTAX_ERROR, "EOS when expecting an object key or object end");
+ return false;
+ } else if (c < 0) {
+ return false;
+ } else if (c == '}') {
+ // We got here from either empty object "{}" or ending comma "{a:1,}"
+ next();
+ break;
+ }
+
+ NOT_PRODUCT(prev_pos = pos);
+ if (parse_json_key() == false) {
+ return false;
+ }
+ assert(pos > prev_pos, "parsing stalled");
+
+ skip_to_token();
+ mark_pos();
+ if (expect_any(":", "object key-value separator") <= 0) {
+ return false;
+ }
+
+ skip_to_token();
+ mark_pos();
+ NOT_PRODUCT(prev_pos = pos);
+ if (parse_json_value() == false) {
+ return false;
+ }
+ assert(pos > prev_pos, "parsing stalled");
+
+ c = skip_to_token();
+ mark_pos();
+ if (expect_any(",}", "value separator or object end") <= 0) {
+ return false;
+ }
+ if (c == '}') {
+ break;
+ }
+ }
+
+ assert(c == '}', "array parsing ended without object end token ('}')");
+ return callback(JSON_OBJECT_END, NULL, --level);
+}
+
+// Should only be called when we actually have the start of an array
+// Otherwise it is an internal error
+bool JSON::parse_json_array() {
+ NOT_PRODUCT(const char* prev_pos);
+ int c;
+
+ mark_pos();
+ // Check that we are not called in error
+ if (expect_any("[", "array start character", INTERNAL_ERROR) <= 0) {
+ return false;
+ }
+
+ if (!callback(JSON_ARRAY_BEGIN, NULL, level++)) {
+ return false;
+ }
+
+ for (;;) {
+ mark_pos();
+ c = skip_to_token();
+ if (c == 0) {
+ error(SYNTAX_ERROR, "EOS when expecting a json value or array end");
+ return false;
+ } else if (c < 0) {
+ return false;
+ } else if (c == ']') {
+ // We got here from either empty array "[]" or ending comma "[1,]"
+ next();
+ break;
+ }
+
+ mark_pos();
+ NOT_PRODUCT(prev_pos = pos);
+ if (parse_json_value() == false) {
+ return false;
+ }
+ assert(pos > prev_pos, "parsing stalled");
+
+ c = skip_to_token();
+ mark_pos();
+ if (expect_any(",]", "value separator or array end") <= 0) {
+ return false;
+ }
+ if (c == ']') {
+ break;
+ }
+ }
+
+ assert(c == ']', "array parsing ended without array end token (']')");
+ return callback(JSON_ARRAY_END, NULL, --level);
+}
+
+bool JSON::parse_json_string(bool key) {
+ const char* end;
+ JSON_VAL v;
+
+ mark_pos();
+ if (expect_any("\"", "string start character", INTERNAL_ERROR) <= 0) {
+ return false;
+ }
+
+ end = strchr(pos, '"'); // TODO: escapes
+ if (end == NULL) {
+ error(SYNTAX_ERROR, "String started here never ended. Expected \'\"\' before EOS.");
+ return false;
+ }
+
+ v.str.start = pos;
+ v.str.length = end - pos;
+ skip(end - pos);
+
+ if (expect_any("\"", "string end character", INTERNAL_ERROR) <= 0) {
+ return false;
+ }
+
+ if (key == true) {
+ return callback(JSON_KEY, &v, level);
+ } else {
+ return callback(JSON_STRING, &v, level);
+ }
+}
+
+// TODO: hotspot equivalents?
+static bool is_alpha(u_char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+static bool is_numeric(u_char c) {
+ return (c >= '0' && c <= '9');
+}
+static bool is_alnum(u_char c) {
+ return is_alpha(c) || is_numeric(c);
+}
+static bool is_word(u_char c) {
+ return c == '_' || is_alnum(c);
+}
+
+// Allow object keys to be without quotation,
+// but then restrict to ([a-zA-Z0-9_])+
+bool JSON::parse_json_key() {
+ const char* begin;
+ JSON_VAL v;
+ u_char c;
+
+ mark_pos();
+ c = peek();
+ if (c == '"') {
+ return parse_json_string(true);
+ }
+
+ begin = pos;
+ c = peek();
+ if (c == 0) {
+ error(SYNTAX_ERROR, "Got EOS when expecting an object key.");
+ return false;
+ } else if (is_word(c) == false) {
+ error(SYNTAX_ERROR, "Expected an object key, which can be a double-quoted (\") string or a simple string (only alphanumeric characters and underscore, separated by whitespace) that doesn't need to be quoted.");
+ return false;
+ }
+
+ for (;;) {
+ c = peek();
+ // Allow the key to be delimited by control characters and the object key-value separator ':'
+ if (c <= ' ' || c == ':') {
+ break;
+ } else if (is_word(c) == false) {
+ error(SYNTAX_ERROR, "Object key need to be quoted, or consist entirely of alphanumeric characters and underscores.");
+ return false;
+ }
+ next();
+ }
+
+ v.str.start = begin;
+ v.str.length = pos - begin;
+ return callback(JSON_KEY, &v, level);
+}
+
+bool JSON::parse_json_number() {
+ double double_value;
+ int tokens, read;
+ JSON_VAL v;
+
+ mark_pos();
+
+ // Parsing number - for simplicity ints are limited to 2**53
+ // sscanf as a double and check if part is 0.
+ tokens = sscanf(pos, "%lf%n", &double_value, &read);
+ assert(tokens <= 1, "scanf implementation that counts as a token, parsing json numbers will always fail");
+ if (tokens == 1) {
+ assert(read > 0, "sanity");
+
+ if (floor(double_value) == double_value) {
+ // No exponent - treat as an int
+ v.int_value = (int)double_value;
+ if (!callback(JSON_NUMBER_INT, &v, level)) {
+ return false;
+ }
+ } else {
+ v.double_value = double_value;
+ if (!callback(JSON_NUMBER_FLOAT, &v, level)) {
+ return false;
+ }
+ }
+ skip(read);
+ return true;
+ }
+
+ error(SYNTAX_ERROR, "Couldn't parse json number (note that exponents are not supported).");
+ return false;
+}
+
+bool JSON::parse_json_symbol(const char* name, JSON_TYPE symbol) {
+ if (expect_string(name, "maybe you forgot to quote your strings?") == false) {
+ mark_pos();
+ return false;
+ }
+ return callback(symbol, NULL, level);
+}
+
+void JSON::mark_pos() {
+ assert((mark == start || *(mark - 1)) != 0, "buffer overrun");
+ assert(mark <= pos, "mark runahead");
+
+ u_char c;
+
+ while (mark < pos) {
+ c = *mark;
+ assert(c != 0, "pos buffer overrun?");
+ if (c != 0) {
+ mark++;
+ column++;
+ }
+ if (c == '\n') {
+ line++;
+ column = 0;
+ }
+ }
+
+ assert(mark <= pos, "mark runahead");
+}
+
+u_char JSON::next() {
+ assert((pos == start || *(pos - 1)) != 0, "buffer overrun");
+
+ u_char c = *pos;
+ if (c != 0) {
+ pos++;
+ }
+ return c;
+}
+
+u_char JSON::peek() {
+ return *pos;
+}
+
+// Peek ahead i chars (0 is same as peek())
+u_char JSON::peek(size_t i) {
+ u_char c;
+ const char* p;
+
+ p = pos;
+ c = *p;
+ while (i > 0 && c != 0) {
+ i--;
+ p++;
+ c = *p;
+ }
+ return c;
+}
+
+/*
+ * Check that one of the expected characters is next in the stream.
+ * If not, it is an error.
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if the next character was not one of the expected.
+ * Otherwise consumes and returns the expected character that was encountered.
+ */
+int JSON::expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e) {
+ size_t len;
+ u_char c;
+
+ len = strlen(valid_chars);
+ assert(len > 0, "need non-empty string");
+
+ c = peek();
+ if (c == 0) {
+ error(e, "Got EOS when expecting %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+ return 0;
+ }
+ for (size_t i = 0; i < len; i++) {
+ if (c == valid_chars[i]) {
+ return next();
+ }
+ }
+ error(e, "Expected %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+ return -1;
+}
+
+/*
+ * Check that the expected string is next in the stream.
+ * If not, it is an error.
+ * Consumes the expected characters if they are present.
+ * Returns true if the expected characters were present, otherwise false.
+ */
+bool JSON::expect_string(const char* expected_string, const char* error_msg, JSON_ERROR e) {
+ u_char c, expected_char;
+ size_t len;
+
+ assert(expected_string != NULL, "need non-null string");
+ len = strlen(expected_string);
+ assert(len > 0, "need non-empty string");
+
+ for (size_t i = 0; i < len; i++) {
+ expected_char = expected_string[i];
+ assert(expected_char > ' ', "not sane for control characters");
+ if (expected_char <= ' ') {
+ error(INTERNAL_ERROR, "expect got a control char");
+ }
+ c = pos[i];
+ if (c == 0) {
+ error(e, "EOS encountered when expecting %s (\"%s\")", error_msg, expected_string);
+ return false;
+ } else if (c != expected_char) {
+ error(e, "Expected \"%s\" (%s)", expected_string, error_msg);
+ return false;
+ }
+ }
+ skip(len);
+ return true;
+}
+
+/*
+ * Skip i characters.
+ * Returns number of characters skipped.
+ */
+size_t JSON::skip(size_t i) {
+ u_char c;
+ size_t j;
+
+ c = peek();
+ for (j = i; c != 0 && j > 0; j--) {
+ c = next();
+ }
+ return i - j;
+}
+
+/*
+ * Skip whitespace and comments.
+ * Returns the first token after whitespace/comments without consuming it
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if there is an error
+ */
+int JSON::skip_to_token() {
+ for (;;) {
+ int c = peek(0);
+ if (c == '/') {
+ u_char c2 = peek(1);
+ if (c2 == '/') {
+ c = skip_line_comment();
+ } else if (c2 == '*') {
+ c = skip_block_comment();
+ if (c < 0) {
+ return -1;
+ }
+ }
+ // Fall through to keep checking if there
+ // are more whitespace / comments to skip
+ }
+ if (c == 0 || c > ' ') {
+ return c;
+ }
+ next();
+ }
+ return 0;
+}
+
+/*
+ * Skip to, and return the wanted char without consuming it
+ * Returns 0 if EOS is encountered.
+ */
+u_char JSON::skip_to(u_char want) {
+ // We want the bookkeeping done in next().
+ // Otherwise strchr could have been used.
+ u_char c;
+ for(;;) {
+ c = peek();
+ if (c == 0 || c == want) {
+ return c;
+ }
+ next();
+ }
+}
+
+/*
+ * Should only be called when we actually have a line comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Will return the first token after the line comment without consuming it.
+ * Returns 0 if EOS is encoutered.
+ */
+u_char JSON::skip_line_comment() {
+ u_char c;
+
+ // Check that we are not called in error
+ expect_any("/", "line comment start", INTERNAL_ERROR);
+ expect_any("/", "line comment start", INTERNAL_ERROR);
+
+ c = skip_to('\n');
+ if (c == 0) {
+ return 0;
+ }
+ next();
+ return next();
+}
+
+/*
+ * Should only be called when we actually have a block comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Returns the first token after the block comment without consuming it.
+ * Returns -1 if EOS is encountered in the middle of a comment.
+ */
+int JSON::skip_block_comment() {
+ const char* current;
+
+ // Check that we are not called in error.
+ if (peek() != '/' || peek(1) != '*') {
+ // Let expect handle EOS.
+ expect_string("/*", "block comment start", INTERNAL_ERROR);
+ return 0;
+ }
+
+ current = pos;
+ for (;;) {
+ current = strchrnul_(current, '*');
+
+ if (current[0] == 0 || current[1] == 0) {
+ // Advance error marker to start of block comment
+ mark_pos();
+ error(SYNTAX_ERROR, "Block comment started here never ended. Expected \"*/\" before EOS.");
+ return -1;
+ }
+
+ if (current[1] == '/') {
+ pos = current;
+ if (expect_string("*/", "block comment end", INTERNAL_ERROR) == false) {
+ return -1;
+ }
+ // Found block comment end
+ return peek();
+ }
+ current++;
+ }
+}
+
+const char* JSON::strerror(JSON_ERROR e) {
+ switch (e) {
+ case SYNTAX_ERROR:
+ return "Syntax error";
+ case INTERNAL_ERROR:
+ return "Internal error";
+ case KEY_ERROR:
+ return "Key error";
+ case VALUE_ERROR:
+ return "Value error";
+ default:
+ ShouldNotReachHere();
+ return "Unknown error";
+ }
+}
+
+void JSON::error(JSON_ERROR e, const char* format, ...) {
+ _valid = false;
+
+ if (!silent) {
+ const char* line_start;
+ const char* tmp;
+ size_t line_length;
+ va_list args;
+ u_char c;
+
+ _st->print("%s on line %u byte %u: ", JSON::strerror(e), line, column + 1);
+ va_start(args, format);
+ _st->vprint(format, args);
+ _st->cr();
+ va_end(args);
+
+ line_start = mark - column;
+ assert(line_start >= start, "out of bounds");
+ assert(line_start <= mark, "out of bounds");
+ assert(line_start == start || line_start[-1] == '\n', "line counting error");
+
+ c = *pos;
+ if (c == 0) {
+ _st->print(" Got ");
+ _st->print_cr("EOS.");
+ }
+ tmp = mark;
+ c = *tmp;
+ if (c > ' ') {
+ _st->print(" At ");
+ _st->print("'");
+ while (c > ' ') {
+ _st->print("%c", c);
+ tmp++;
+ c = *tmp;
+ }
+ _st->print_cr("'.");
+ }
+
+ // Skip to newline or EOS
+ tmp = strchrnul_(mark, '\n');
+ line_length = tmp - line_start;
+
+ _st->print_cr("%s", line_start);
+ }
+}
+
+#ifndef PRODUCT
+void JSONTest::test(const char* text, bool should_pass) {
+ JSONTest json(text);
+ if (should_pass) {
+ assert(json.valid() == true, "failed on a valid json string");
+ if (VerboseInternalVMTests) {
+ tty->print_cr("-- json test passed as expected --");
+ }
+ } else {
+ assert(json.valid() == false, "succeeded on an invalid json string");
+ if (VerboseInternalVMTests) {
+ tty->print_cr("-- json test failed as expected --");
+ }
+ }
+}
+
+JSONTest::JSONTest(const char* text) : JSON(text, !VerboseInternalVMTests, tty) {
+ prev = JSON_NONE;
+ parse();
+}
+
+bool JSONTest::test() {
+ JSONTest::test("{}", true);
+ JSONTest::test("[]", true);
+ JSONTest::test(" { } ", true);
+ JSONTest::test(" [ ] ", true);
+
+ JSONTest::test("\"error\"", false);
+ JSONTest::test("error", false);
+ JSONTest::test("1", false);
+ JSONTest::test("1.2", false);
+ JSONTest::test("true", false);
+ JSONTest::test("false", false);
+ JSONTest::test("null", false);
+
+ JSONTest::test("[ 1 ]", true);
+ JSONTest::test("[ 1, ]", true);
+ JSONTest::test("[ true ]", true);
+ JSONTest::test("[ true, ]", true);
+ JSONTest::test("[ false ]", true);
+ JSONTest::test("[ false, ]", true);
+ JSONTest::test("[ null ]", true);
+ JSONTest::test("[ null, ]", true);
+ JSONTest::test("[ \"\" ]", true);
+ JSONTest::test("[ \"\", ]", true);
+ JSONTest::test("[ \"elem1\" ]", true);
+ JSONTest::test("[ \"elem1\", ]", true);
+ JSONTest::test("[ \"elem1\", ]", true);
+ JSONTest::test("[ \"elem1\" ]", true);
+ JSONTest::test("[ \"elem1\", \"elem2\" ]", true);
+ JSONTest::test("[ \"elem1\", \"elem2\", ]", true);
+
+
+ JSONTest::test("[ \"elem1\" ] { }", false);
+ JSONTest::test("[ elem1, \"elem2\" ]", false);
+ JSONTest::test("[ \"elem1\"", false);
+ JSONTest::test("[ \"elem1 ]", false);
+ JSONTest::test("[ \"elem1\", \"elem2\"", false);
+ JSONTest::test("[ truefoo ]", false);
+ JSONTest::test("[ falsefoo ]", false);
+ JSONTest::test("[ nullfoo ]", false);
+
+ JSONTest::test("{ key : 1 }", true);
+ JSONTest::test("{ key : 1, }", true);
+ JSONTest::test("{ key : 1.2 }", true);
+ JSONTest::test("{ key : true }", true);
+ JSONTest::test("{ key : true, }", true);
+ JSONTest::test("{ key : false }", true);
+ JSONTest::test("{ key : false, }", true);
+ JSONTest::test("{ key : null }", true);
+ JSONTest::test("{ key : null, }", true);
+ JSONTest::test("{ \"\" : \"\" }", true);
+ JSONTest::test("{ \"\" : \"\", }", true);
+ JSONTest::test("{ \"key1\" : \"val1\" }", true);
+ JSONTest::test("{ \"key1\" : \"val1\", }", true);
+ JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true);
+ JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true);
+
+ JSONTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false);
+ JSONTest::test("{ \"key\" : \"val\" ", false);
+
+ JSONTest::test("/**/ { }", true);
+ JSONTest::test("/* */ { }", true);
+ JSONTest::test("/*foo*/ { }", true);
+ JSONTest::test("/* *foo */ { }", true);
+ JSONTest::test("/* *foo* */ { }", true);
+ JSONTest::test("/* /*foo */ { }", true);
+ JSONTest::test("{ } /* foo */", true);
+ JSONTest::test("{ } /* foo */ ", true);
+ JSONTest::test("{ } //", true);
+ JSONTest::test("{ } // ", true);
+ JSONTest::test("{ } // foo", true);
+
+ JSONTest::test("/* * / { }", false);
+ JSONTest::test("/ * */ { }", false);
+ JSONTest::test("// { }", false);
+ JSONTest::test("/* { } */", false);
+ JSONTest::test("/* { } */ ", false);
+ JSONTest::test("/* { } ", false);
+ JSONTest::test("{ } /* ", false);
+ JSONTest::test("/* { } *", false);
+ JSONTest::test("{ /* } */", false);
+ JSONTest::test("[ /* ] */", false);
+ JSONTest::test("{ key : \"val\", /* } */", false);
+ JSONTest::test("[ \"val\", /* ] */", false);
+
+ JSONTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+ JSONTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+ JSONTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]},\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}", true);
+ JSONTest::test("/* comment */ { key1 error : { \"☃\" : { \"☃\" : [ \"☃\", \"☃\" ] }, \"☃\" : true }, \"baz\" : [ \"☃\" ], foo : \"☃\",}", false); // first key needs to be quoted since it contains a space
+
+
+ JSONTest::test("[\n]", true);
+
+ JSONTest::test(
+ "[" "\n"
+ " {"
+ " // pattern to match against class+method+signature" "\n"
+ " // leading and trailing wildcard (*) allowed" "\n"
+ " match: \"foo.bar.*\"," "\n"
+ " " "\n"
+ " // override defaults for specified compiler" "\n"
+ " // we may differentiate between levels too. TBD." "\n"
+ " c1: {" "\n"
+ " //override c1 presets " "\n"
+ " array_bounds_check_removal: false" "\n"
+ " }," "\n"
+ "" "\n"
+ " c2: {" "\n"
+ " // control inlining of method" "\n"
+ " // + force inline, - dont inline" "\n"
+ " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+ " }," "\n"
+ "" "\n"
+ " // directives outside a specific preset applies to all compilers" "\n"
+ " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+ " print_assembly: true," "\n"
+ " verify_oopmaps: true," "\n"
+ " max_loop_unrolling: 5" "\n"
+ " }," "\n"
+ " {" "\n"
+ " // matching several patterns require an array" "\n"
+ " match: [\"baz.*\",\"frob*\"]," "\n"
+ "" "\n"
+ " // only enable c1 for this directive" "\n"
+ " // all enabled by default. Command disables all not listed" "\n"
+ " enable: \"c1\"," "\n"
+ "" "\n"
+ " // applies to all compilers" "\n"
+ " // + force inline, - dont inline" "\n"
+ " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+ " print_inlining: true," "\n"
+ "" "\n"
+ " // force matching compiles to be blocking/syncronous" "\n"
+ " blocking_compile: true" "\n"
+ " }," "\n"
+ "]" "\n", true);
+
+ return true;
+}
+
+void JSONTest::log(uint indent, const char* format, ...) {
+ if (VerboseInternalVMTests) {
+ if (prev != JSON_KEY) {
+ for (uint i = 0; i < indent; i++) {
+ _st->print(" ");
+ }
+ }
+ va_list args;
+ va_start(args, format);
+ _st->vprint(format, args);
+ va_end(args);
+ }
+}
+
+bool JSONTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) {
+ switch (t) {
+ case JSON_OBJECT_BEGIN:
+ log(rlevel, "{\n");
+ prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly
+ return true;
+
+ case JSON_OBJECT_END:
+ log(rlevel, "},\n");
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_ARRAY_BEGIN:
+ log(rlevel, "[\n");
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_ARRAY_END:
+ log(rlevel, "],\n");
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_KEY:
+ if (VerboseInternalVMTests) {
+ for (uint i = 0; i < rlevel; i++) {
+ _st->print(" ");
+ }
+ _st->print("<key>");
+ for (size_t i = 0; i < v->str.length; i++) {
+ u_char c = v->str.start[i];
+ assert(c != 0, "string overrun");
+ if (c == 0) {
+ return false;
+ }
+ _st->print("%c", c);
+ }
+ _st->print(" : ");
+ }
+ prev = JSON_KEY;
+ return true;
+
+ case JSON_STRING:
+ if (VerboseInternalVMTests) {
+ if (prev != JSON_KEY) {
+ for (uint i = 0; i < rlevel; i++) {
+ _st->print(" ");
+ }
+ }
+ _st->print("<str>");
+ for (size_t i = 0; i < v->str.length; i++) {
+ u_char c = v->str.start[i];
+ assert(c != 0, "string overrun");
+ if (c == 0) {
+ return false;
+ }
+ _st->print("%c", c);
+ }
+ _st->print(",\n");
+ }
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_NUMBER_INT:
+ log(rlevel, "<int>%" PRId64 ",\n", v->int_value);
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_NUMBER_FLOAT:
+ log(rlevel, "<double>%lf,\n", v->double_value);
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_TRUE:
+ log(rlevel, "<true>,\n");
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_FALSE:
+ log(rlevel, "<false>,\n");
+ prev = JSON_NONE;
+ return true;
+
+ case JSON_NULL:
+ log(rlevel, "<null>,\n");
+ prev = JSON_NONE;
+ return true;
+
+ default:
+ error(INTERNAL_ERROR, "unknown JSON type");
+ return false;
+ }
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.hpp Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_JSON_HPP
+#define SHARE_VM_UTILITIES_JSON_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+
+class JSON : public ResourceObj {
+ protected:
+ JSON(const char* text, bool silent, outputStream* st);
+ void parse();
+ bool valid();
+
+ typedef enum {
+ JSON_NONE,
+ JSON_OBJECT_BEGIN,
+ JSON_OBJECT_END,
+ JSON_ARRAY_BEGIN,
+ JSON_ARRAY_END,
+ JSON_KEY,
+ JSON_STRING,
+ JSON_NUMBER_INT,
+ JSON_NUMBER_FLOAT,
+ JSON_TRUE,
+ JSON_FALSE,
+ JSON_NULL
+ } JSON_TYPE;
+
+ typedef union {
+ int64_t int_value;
+ double double_value;
+
+ struct {
+ const char* start;
+ size_t length;
+ } str;
+ } JSON_VAL;
+
+ typedef enum {
+ INTERNAL_ERROR,
+ SYNTAX_ERROR,
+ KEY_ERROR,
+ VALUE_ERROR
+ } JSON_ERROR;
+
+ void error(JSON_ERROR e, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+ outputStream* _st;
+
+ private:
+ const char* start;
+ const char* pos;
+
+ // For error printing
+ const char* mark; // Error marker
+ uint level;
+ uint line;
+ uint column;
+
+ bool silent;
+ bool _valid;
+
+ bool parse_json_value();
+ bool parse_json_object();
+ bool parse_json_array();
+ bool parse_json_string(bool key = false);
+ bool parse_json_key();
+ bool parse_json_number();
+ bool parse_json_symbol(const char* name, JSON_TYPE symbol);
+
+ virtual bool callback(JSON_TYPE t, JSON_VAL* v, uint level) = 0;
+
+ void mark_pos();
+ u_char next();
+ u_char peek();
+ u_char peek(size_t i);
+ int expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e = SYNTAX_ERROR);
+ bool expect_string(const char* expected_string, const char* error_msg = "", JSON_ERROR e = SYNTAX_ERROR);
+ size_t skip(size_t i);
+ int skip_to_token();
+ u_char skip_to(u_char want);
+ u_char skip_line_comment();
+ int skip_block_comment();
+
+ const char* strerror(JSON_ERROR e);
+};
+
+#ifndef PRODUCT
+class JSONTest : public JSON {
+ public:
+ static bool test();
+
+ private:
+ JSONTest(const char* text);
+ static void test(const char* json, bool valid);
+
+ void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+
+ bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+ JSON_TYPE prev;
+};
+#endif
+
+#endif // SHARE_VM_UTILITIES_JSON_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test InlineMatcherTest
+ * @bug 8074095
+ * @library /testlibrary /../../test/lib
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI InlineMatcherTest
+ * @summary Testing of compiler/InlineMatcher
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import sun.hotspot.WhiteBox;
+
+public class InlineMatcherTest {
+
+ /** Instance of WhiteBox */
+ protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ Method helper;
+ Method getDate;
+ Method inner;
+ Method toString;
+
+ final public static int FORCE_INLINE = 2;
+ final public static int DONT_INLINE = 1;
+ final public static int NO_MATCH = 0;
+ final public static int PARSING_FAILURE = -1;
+
+ public InlineMatcherTest() {
+
+ }
+
+ public void test() throws Exception {
+ // instantiate before calling getMethod on innerHelper
+ TestCases testCases = new TestCases();
+
+ helper = getMethod(InlineMatcherTest.class, "helper");
+
+ testCases.add(helper, "*.*", PARSING_FAILURE);
+ testCases.add(helper, "+*.*", FORCE_INLINE);
+ testCases.add(helper, "++*.*", NO_MATCH); // + is a valid part of the
+ // class name
+ testCases.add(helper, "-*.*", DONT_INLINE);
+ testCases.add(helper, "--*.*", NO_MATCH); // - is a valid part of the
+ // class name
+
+ testCases.add(helper, "+InlineMatcherTest.*", FORCE_INLINE);
+ testCases.add(helper, "+InlineMatcherTest.helper", FORCE_INLINE);
+ testCases.add(helper, "+InlineMatcherTest.helper()", FORCE_INLINE);
+ testCases.add(helper, "+InlineMatcherTest.helper()V", FORCE_INLINE);
+ testCases.add(helper, "+InlineMatcherTest.helper(", FORCE_INLINE);
+
+ testCases.add(helper, "-InlineMatcherTest.*", DONT_INLINE);
+ testCases.add(helper, "-InlineMatcherTest.helper", DONT_INLINE);
+ testCases.add(helper, "-InlineMatcherTest.helper()", DONT_INLINE);
+ testCases.add(helper, "-InlineMatcherTest.helper()V", DONT_INLINE);
+ testCases.add(helper, "-InlineMatcherTest.helper(", DONT_INLINE);
+
+ testCases.add(helper, "+abc.*", NO_MATCH);
+ testCases.add(helper, "+*.abc", NO_MATCH);
+ testCases.add(helper, "-abc.*", NO_MATCH);
+ testCases.add(helper, "-*.abcls ", NO_MATCH);
+
+ int failures = 0;
+
+ for (TestCase t : testCases) {
+ System.out.println("Test case: " + t.pattern);
+ if (!t.test()) {
+ failures++;
+ System.out.println(" * FAILED");
+ }
+ }
+ if (failures != 0) {
+ throw new Exception("There where " + failures + " failures in this test");
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+ InlineMatcherTest test = new InlineMatcherTest();
+ test.test();
+ }
+
+ public void helper() {
+
+ }
+
+ private static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+ try {
+ return klass.getDeclaredMethod(name, parameterTypes);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new RuntimeException("exception on getting method Helper." + name, e);
+ }
+ }
+
+ class TestCase {
+ String pattern;
+ Method testTarget;
+ int expectedResult;
+
+ public TestCase(Method testTarget, String pattern, int expectedResult) {
+ this.testTarget = testTarget;
+ this.pattern = pattern;
+ this.expectedResult = expectedResult;
+ }
+
+ public String resultAsStr(int errorCode) {
+ switch (errorCode) {
+ case PARSING_FAILURE:
+ return "Parsing failed";
+ case NO_MATCH:
+ return "No match";
+ case DONT_INLINE:
+ return "Dont Inline";
+ case FORCE_INLINE:
+ return "Force Inline";
+ default:
+ return "Unknown error";
+ }
+ }
+
+ boolean test() {
+ int result = WHITE_BOX.matchesInline(testTarget, pattern);
+ if (result != expectedResult) {
+ System.out
+ .println("FAIL Wrong result, Got: " + resultAsStr(result) + "\n TestCase: " + this.toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Method: '" + testTarget.toString() + "' Pattern: '" + pattern + "' Expected: "
+ + resultAsStr(expectedResult);
+ }
+
+ public void innerHelper() {
+
+ }
+ }
+
+ class TestCases extends ArrayList<TestCase> {
+ private static final long serialVersionUID = 1L;
+
+ public boolean add(Method testTarget, String pattern, int expectedResult) {
+ return super.add(new TestCase(testTarget, pattern, expectedResult));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityBase
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityBase {
+
+ public static final WhiteBox WB = WhiteBox.getWhiteBox();
+ public static String control_on, control_off;
+ Method method, nomatch;
+
+ public void run(CommandExecutor executor) throws Exception {
+
+ control_on = System.getProperty("test.src", ".") + File.separator + "control_on.txt";
+ control_off = System.getProperty("test.src", ".") + File.separator + "control_off.txt";
+ method = getMethod(TestCompilerDirectivesCompatibilityBase.class, "helper");
+ nomatch = getMethod(TestCompilerDirectivesCompatibilityBase.class, "another");
+
+ testCompatibility(executor);
+ }
+
+ public void testCompatibility(CommandExecutor executor) throws Exception {
+
+ // Call all validation twice to catch error when overwriting a directive
+ // Flag is default off
+ expect(!WB.getBooleanVMFlag("PrintAssembly"));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+
+ // load directives that turn it on
+ executor.execute("Compiler.directives_add " + control_on);
+ expect(WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+
+ // remove and see that it is true again
+ executor.execute("Compiler.directives_remove");
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ }
+
+ public void expect(boolean test) throws Exception {
+ if (!test) {
+ throw new Exception("Test failed");
+ }
+ }
+
+ public void expect(boolean test, String msg) throws Exception {
+ if (!test) {
+ throw new Exception(msg);
+ }
+ }
+
+ @Test
+ public void jmx() throws Exception {
+ run(new JMXExecutor());
+ }
+
+ public void helper() {
+ }
+
+ public void another() {
+ }
+
+ public static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+ try {
+ return klass.getDeclaredMethod(name, parameterTypes);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new RuntimeException("exception on getting method Helper." + name, e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityCommandOff
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOff extends TestCompilerDirectivesCompatibilityBase {
+
+ public void testCompatibility(CommandExecutor executor) throws Exception {
+
+ // Call all validation twice to catch error when overwriting a directive
+ // Flag is default off
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+
+ // load directives that turn it on
+ executor.execute("Compiler.directives_add " + control_on);
+ expect(WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+
+ // remove and see that it is false again
+ executor.execute("Compiler.directives_remove");
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(!WB.shouldPrintAssembly(nomatch));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityCommandOn
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOn
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOn extends TestCompilerDirectivesCompatibilityBase{
+
+ public void testCompatibility(CommandExecutor executor) throws Exception {
+
+ // Call all validation twice to catch error when overwriting a directive
+ // Flag is default on
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+
+ // load directives that turn it off
+ executor.execute("Compiler.directives_add " + control_off);
+ expect(!WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+
+ // remove and see that it is true again
+ executor.execute("Compiler.directives_remove");
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityFlag
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityFlag extends TestCompilerDirectivesCompatibilityBase {
+
+ public void testCompatibility(CommandExecutor executor) throws Exception {
+
+ // Call all validation twice to catch error when overwriting a directive
+ // Flag is default on
+ expect(WB.getBooleanVMFlag("PrintAssembly"));
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+
+ // load directives that turn it off
+ executor.execute("Compiler.directives_add " + control_off);
+ expect(!WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+
+ // remove and see that it is true again
+ executor.execute("Compiler.directives_remove");
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method));
+ expect(WB.shouldPrintAssembly(nomatch));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=compileonly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.COMPILEONLY, Scenario.Type.FILE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=exclude
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.ExcludeTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.EXCLUDE, Scenario.Type.FILE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=log
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.LogTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.LOG, Scenario.Type.FILE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=print
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.PrintTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.PRINT, Scenario.Type.FILE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=compileonly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.COMPILEONLY, Scenario.Type.OPTION).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=exclude
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.ExcludeTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.EXCLUDE, Scenario.Type.OPTION).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/LogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=log
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.LogTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.LOG, Scenario.Type.OPTION).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=print
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.PrintTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.PRINT, Scenario.Type.OPTION).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_off.txt Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+[
+ {
+ match: "*.helper",
+ PrintAssembly: false,
+ DisableIntrinsic:"x"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_on.txt Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+[
+ {
+ match: "*.helper",
+ PrintAssembly: true,
+ DisableIntrinsic:"_dsin"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to compile only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.COMPILEONLY, Scenario.Type.DIRECTIVE)
+ .test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to exclude methods from compilation
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.ExcludeTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.EXCLUDE, Scenario.Type.DIRECTIVE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/LogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to turn on LogCompilation
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.LogTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.LOG, Scenario.Type.DIRECTIVE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to turn on print_assembly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.PrintTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.PRINT, Scenario.Type.DIRECTIVE).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to add and remove directives
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddAndRemoveTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddAndRemoveTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class AddAndRemoveTest extends AbstractTestBase {
+ private static final int AMOUNT = Integer.getInteger(
+ "compiler.compilercontrol.jcmd.AddAndRemoveTest.amount", 10);
+
+ public static void main(String[] args) {
+ new AddAndRemoveTest().test();
+ }
+
+ @Override
+ public void test() {
+ Scenario.Builder builder = Scenario.getBuilder();
+ // Add some commands with JCMD
+ for (int i = 0; i < AMOUNT; i++) {
+ Executable exec = Utils.getRandomElement(METHODS).first;
+ MethodDescriptor md = getValidMethodDescriptor(exec);
+ CompileCommand compileCommand = new JcmdCommand(Command.COMPILEONLY,
+ md, null, Scenario.Type.JCMD, Scenario.JcmdType.ADD);
+ compileCommand.print();
+ builder.add(compileCommand);
+ }
+ // Remove half of them
+ for (int i = 0; i < AMOUNT / 2; i++) {
+ /* remove jcmd command doesn't need method, compiler etc.
+ command will be ignored */
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.REMOVE));
+ }
+ Scenario scenario = builder.build();
+ scenario.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to compile only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddCompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddCompileOnlyTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddCompileOnlyTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.COMPILEONLY, Scenario.Type.JCMD)
+ .test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to exclude only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddExcludeTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddExcludeTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.EXCLUDE, Scenario.Type.JCMD)
+ .test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to log only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddLogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddLogTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddLogTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.LOG, Scenario.Type.JCMD)
+ .test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to print assembly
+ * only for specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddPrintAssemblyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddPrintAssemblyTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddPrintAssemblyTest {
+ public static void main(String[] args) {
+ new SingleCommand(Command.PRINT, Scenario.Type.JCMD)
+ .test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @ignore 8140405
+ * @summary Tests jcmd to be able to clear directives added via options
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ClearDirectivesFileStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class ClearDirectivesFileStackTest extends AbstractTestBase {
+ private static final int AMOUNT = Utils.getRandomInstance().nextInt(100);
+ private final CommandGenerator cmdGen = new CommandGenerator();
+
+ public static void main(String[] args) {
+ new ClearDirectivesFileStackTest().test();
+ }
+
+ @Override
+ public void test() {
+ Scenario.Builder builder = Scenario.getBuilder();
+ // Add some commands with directives file
+ for (int i = 0; i < AMOUNT; i++) {
+ Executable exec = Utils.getRandomElement(METHODS).first;
+ MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec);
+ Command command = cmdGen.generateCommand();
+ if (command == Command.NONEXISTENT) {
+ // skip invalid command
+ command = Command.COMPILEONLY;
+ }
+ CompileCommand compileCommand = new CompileCommand(command,
+ methodDescriptor, cmdGen.generateCompiler(),
+ Scenario.Type.DIRECTIVE);
+ compileCommand.print();
+ builder.add(compileCommand);
+ }
+ // print all directives before
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+ // clear the stack
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));
+ // print all directives after the clear
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+ Scenario scenario = builder.build();
+ scenario.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests clear JCMD command
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ClearDirectivesStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesStackTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class ClearDirectivesStackTest extends AbstractTestBase {
+ private static final int AMOUNT = Utils.getRandomInstance().nextInt(100);
+ private final CommandGenerator cmdGen = new CommandGenerator();
+
+ public static void main(String[] args) {
+ new ClearDirectivesStackTest().test();
+ }
+
+ @Override
+ public void test() {
+ Scenario.Builder builder = Scenario.getBuilder();
+ // Add some commands with JCMD
+ for (int i = 0; i < AMOUNT; i++) {
+ Executable exec = Utils.getRandomElement(METHODS).first;
+ MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec);
+ CompileCommand compileCommand = new JcmdCommand(
+ cmdGen.generateCommand(), methodDescriptor,
+ cmdGen.generateCompiler(), Scenario.Type.JCMD,
+ Scenario.JcmdType.ADD);
+ compileCommand.print();
+ builder.add(compileCommand);
+ }
+ // print all directives before
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+ // clear the stack
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));
+ // print all directives after the clear
+ builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+ Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+ Scenario scenario = builder.build();
+ scenario.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Randomly generates commands with random types
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build RandomCommandsTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest
+ */
+
+package compiler.compilercontrol.mixed;
+
+import compiler.compilercontrol.share.MultiCommand;
+
+public class RandomCommandsTest {
+ public static void main(String[] args) {
+ MultiCommand.generateRandomTest(false).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @ignore 8140667
+ * @summary Randomly generates valid commands with random types
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build RandomValidCommandsTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomValidCommandsTest
+ */
+
+package compiler.compilercontrol.mixed;
+
+import compiler.compilercontrol.share.MultiCommand;
+
+public class RandomValidCommandsTest {
+ public static void main(String[] args) {
+ MultiCommand.generateRandomTest(true).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directive json parser
+ * @library /testlibrary /../../test/lib ../share /
+ * @run driver compiler.compilercontrol.parser.DirectiveParser
+ */
+
+package compiler.compilercontrol.parser;
+
+import compiler.compilercontrol.share.JSONFile;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+
+public class DirectiveParser {
+ private static final String ERROR_MSG = "VM should exit with error "
+ + "on incorrect JSON file: ";
+ private static final String EXPECTED_ERROR_STRING = "Parsing of compiler"
+ + " directives failed";
+
+ public static void main(String[] args) {
+ simpleTest();
+ nonMatchingBrackets();
+ arrayTest();
+ emptyObjectTest();
+ emptyFile();
+ noFile();
+ directory();
+ }
+
+ private static void simpleTest() {
+ String fileName = "simple.json";
+ try (JSONFile file = new JSONFile(fileName)) {
+ file.write(JSONFile.Element.ARRAY)
+ .write(JSONFile.Element.OBJECT)
+ .write(JSONFile.Element.PAIR, "match")
+ .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"")
+ .write(JSONFile.Element.PAIR, "c2")
+ .write(JSONFile.Element.OBJECT)
+ .write(JSONFile.Element.PAIR, "inline")
+ .write(JSONFile.Element.ARRAY)
+ .write(JSONFile.Element.VALUE, "\"+*.indexOf\"")
+ .write(JSONFile.Element.VALUE, "\"-a.b\"")
+ .end()
+ .end()
+ .end() // end object
+ .write(JSONFile.Element.OBJECT)
+ .write(JSONFile.Element.PAIR, "match")
+ .write(JSONFile.Element.VALUE, "\"*.indexOf\"")
+ .write(JSONFile.Element.PAIR, "c1")
+ .write(JSONFile.Element.OBJECT)
+ .write(JSONFile.Element.PAIR, "enable")
+ .write(JSONFile.Element.VALUE, "false")
+ .end()
+ .end(); // end object
+ file.end();
+ }
+ OutputAnalyzer output = execute(fileName);
+ output.shouldHaveExitValue(0);
+ output.shouldNotContain(EXPECTED_ERROR_STRING);
+ }
+
+ private static void nonMatchingBrackets() {
+ String fileName = "non-matching.json";
+ try (JSONFile file = new JSONFile(fileName)) {
+ file.write(JSONFile.Element.ARRAY)
+ .write(JSONFile.Element.OBJECT)
+ .write(JSONFile.Element.PAIR, "match")
+ .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"")
+ .end();
+ // don't write matching }
+ }
+ OutputAnalyzer output = execute(fileName);
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non matching "
+ + "brackets");
+ output.shouldContain(EXPECTED_ERROR_STRING);
+ }
+
+ private static void arrayTest() {
+ String fileName = "array.json";
+ try (JSONFile file = new JSONFile(fileName)) {
+ file.write(JSONFile.Element.ARRAY);
+ file.end();
+ }
+ OutputAnalyzer output = execute(fileName);
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty array");
+ }
+
+ private static void emptyObjectTest() {
+ String fileName = "emptyObject.json";
+ try (JSONFile file = new JSONFile(fileName)) {
+ file.write(JSONFile.Element.OBJECT);
+ file.end();
+ }
+ OutputAnalyzer output = execute(fileName);
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty object "
+ + "without any match");
+ output.shouldContain(EXPECTED_ERROR_STRING);
+ }
+
+ private static void emptyFile() {
+ String fileName = "empty.json";
+ try (JSONFile file = new JSONFile(fileName)) {
+ // empty
+ }
+ OutputAnalyzer output = execute(fileName);
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty file");
+ output.shouldContain(EXPECTED_ERROR_STRING);
+ }
+
+ private static void noFile() {
+ OutputAnalyzer output = execute("nonexistent.json");
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non existing "
+ + "file");
+ }
+
+ private static void directory() {
+ OutputAnalyzer output = execute(Utils.TEST_SRC);
+ Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "directory as "
+ + "a name");
+ }
+
+ private static OutputAnalyzer execute(String fileName) {
+ OutputAnalyzer output;
+ try {
+ output = ProcessTools.executeTestJvm(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:CompilerDirectivesFile=" + fileName,
+ "-version");
+ } catch (Throwable thr) {
+ throw new Error("Execution failed", thr);
+ }
+ return output;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public abstract class AbstractTestBase {
+ protected static final MethodGenerator METHOD_GEN = new MethodGenerator();
+ protected static final int ATTEMPTS = 25;
+ protected static final List<Pair<Executable, Callable<?>>> METHODS
+ = new PoolHelper().getAllMethods(PoolHelper.METHOD_FILTER);
+
+ public abstract void test();
+
+ /**
+ * Generate random valid method descriptor
+ *
+ * @param exec method to make descriptor for
+ * @return a valid {@link MethodDescriptor#isValid()} descriptor instance
+ */
+ public static MethodDescriptor getValidMethodDescriptor(Executable exec) {
+ MethodDescriptor md = METHOD_GEN.generateRandomDescriptor(exec);
+ for (int i = 0; !md.isValid() && i < ATTEMPTS; i++) {
+ md = METHOD_GEN.generateRandomDescriptor(exec);
+ }
+ if (!md.isValid()) {
+ System.out.println("WARN: Using predefined pattern");
+ md = MethodGenerator.commandDescriptor(exec);
+ }
+ return md;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/JSONFile.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.Objects;
+import java.util.Stack;
+
+/**
+ * Simple JSON file writer
+ */
+public class JSONFile implements AutoCloseable {
+ private final Stack<Element> stack;
+ private final String fileName;
+ private final PrintStream out;
+ private int spaces;
+
+ /**
+ * JSON element
+ */
+ public enum Element {
+ OBJECT,
+ ARRAY,
+ PAIR,
+ VALUE
+ }
+
+ /**
+ * Constructor. Creates file with default name
+ */
+ public JSONFile() {
+ this("directives_file.json");
+ }
+
+ /**
+ * Constructor
+ *
+ * @param fileName file name
+ */
+ public JSONFile(String fileName) {
+ this.spaces = 0;
+ this.stack = new Stack<>();
+ this.fileName = fileName;
+ try {
+ out = new PrintStream(fileName);
+ } catch (FileNotFoundException e) {
+ throw new Error("TESTBUG: can't open/create file " + fileName, e);
+ }
+ }
+
+ /**
+ * Gets file name
+ *
+ * @return file name string
+ */
+ public String getFileName() {
+ return fileName;
+ }
+
+ /**
+ * Gets current JSON element in the file.
+ * The element is a current {@linkplain Element}
+ * that was written into a file.
+ *
+ * @return the type of the current element,
+ * or null if there are nothing written
+ */
+ public Element getElement() {
+ if (stack.empty()) {
+ return null;
+ }
+ return stack.peek();
+ }
+
+ /**
+ * Writes given type with a value to file.
+ * Note that only PAIR and VALUE types accept a single value parameter.
+ * OBJECT and ARRAY do not have a value
+ *
+ * @param element JSON element type
+ * @param value element's value
+ * @return this file instance
+ */
+ public JSONFile write(Element element, String... value) {
+ if (value.length > 1) {
+ throw new Error("TESTBUG: Unexpected value length: "
+ + value.length);
+ }
+ if (!stack.empty()) {
+ if (stack.peek() == Element.VALUE) {
+ out.print(", ");
+ stack.pop();
+ }
+ }
+ switch (element) {
+ case OBJECT:
+ out.print("{");
+ spaces++;
+ stack.push(Element.VALUE);
+ break;
+ case ARRAY:
+ out.print("[");
+ stack.push(Element.VALUE);
+ break;
+ case PAIR:
+ fillSpaces();
+ Objects.requireNonNull(value, "TESTBUG: " + element
+ + "requires a value to be set");
+ out.print(value[0] + ": ");
+ break;
+ case VALUE:
+ Objects.requireNonNull(value, "TESTBUG: " + element
+ + "requires a value to be set");
+ out.print(value[0]);
+ break;
+ }
+ stack.push(element);
+ return this;
+ }
+
+ private void fillSpaces() {
+ out.println();
+ for (int i = 0; i < spaces; i++) {
+ // Fill with spaces to be more readable
+ out.print(" ");
+ }
+ }
+
+ /**
+ * Ends current object or array of {@linkplain Element}
+ *
+ * @return this file instance
+ */
+ public JSONFile end() {
+ if (!stack.empty()) {
+ Element prev = stack.pop();
+ while (prev != Element.OBJECT && prev != Element.ARRAY
+ && !stack.empty()) {
+ prev = stack.pop();
+ }
+ switch (prev) {
+ case OBJECT:
+ spaces--;
+ fillSpaces();
+ out.print("}");
+ break;
+ case ARRAY:
+ out.print("]");
+ break;
+ default:
+ throw new Error("TESTBUG: Incorrect end. " +
+ "Wrong type found: " + prev);
+ }
+ } else {
+ throw new Error("TESTBUG: Incorrect end. Empty stack");
+ }
+ return this;
+ }
+
+ /**
+ * Closes this file
+ */
+ @Override
+ public void close() {
+ out.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MultiCommand extends AbstractTestBase {
+ private final List<CompileCommand> testCases;
+
+ public MultiCommand(List<CompileCommand> testCases) {
+ this.testCases = testCases;
+ }
+
+ /**
+ * Generates a test containing multiple random commands
+ *
+ * @param validOnly shows that all commands should be valid
+ * @return test instance to run
+ */
+ public static AbstractTestBase generateRandomTest(boolean validOnly) {
+ CommandGenerator cmdGen = new CommandGenerator();
+ List<Command> commands = cmdGen.generateCommands();
+ List<CompileCommand> testCases = new ArrayList<>();
+ for (Command cmd : commands) {
+ if (validOnly && cmd == Command.NONEXISTENT) {
+ // skip invalid command
+ continue;
+ }
+ Executable exec = Utils.getRandomElement(METHODS).first;
+ MethodDescriptor md;
+ if (validOnly) {
+ md = AbstractTestBase.getValidMethodDescriptor(exec);
+ } else {
+ md = AbstractTestBase.METHOD_GEN.generateRandomDescriptor(exec);
+ }
+ CompileCommand cc = cmdGen.generateCompileCommand(cmd, md, null);
+ testCases.add(cc);
+ }
+ return new MultiCommand(testCases);
+ }
+
+ @Override
+ public void test() {
+ Scenario.Builder builder = Scenario.getBuilder();
+ for (CompileCommand cc : testCases) {
+ cc.print();
+ builder.add(cc);
+ }
+ Scenario scenario = builder.build();
+ scenario.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/SingleCommand.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class SingleCommand extends AbstractTestBase {
+ private final Command command;
+ private final Scenario.Type type;
+
+ public SingleCommand(Command command, Scenario.Type type) {
+ this.command = command;
+ this.type = type;
+ }
+
+ @Override
+ public void test() {
+ Scenario.Builder builder = Scenario.getBuilder();
+ Executable exec = Utils.getRandomElement(METHODS).first;
+ MethodDescriptor md = getValidMethodDescriptor(exec);
+ CommandGenerator cmdGen = new CommandGenerator();
+ CompileCommand compileCommand = cmdGen.generateCompileCommand(command,
+ md, type);
+ compileCommand.print();
+ builder.add(compileCommand);
+ Scenario scenario = builder.build();
+ scenario.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.actions;
+
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.Pair;
+import jdk.test.lib.ProcessTools;
+import pool.PoolHelper;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+import java.lang.reflect.Executable;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
+
+public class BaseAction {
+ private static final List<Pair<Executable, Callable<?>>> METHODS;
+ private static final Map<String, Executable> METHODS_NAMES;
+
+ static {
+ METHODS = new PoolHelper().getAllMethods();
+ METHODS_NAMES = METHODS.stream().collect(Collectors.toMap(
+ pair -> pair.first.toGenericString(),
+ pair -> pair.first));
+ }
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ throw new Error("TESTBUG: requires port as parameter: "
+ + Arrays.toString(args));
+ }
+ int pid;
+ try {
+ pid = ProcessTools.getProcessId();
+ } catch (Exception e) {
+ throw new Error("Could not determine own pid", e);
+ }
+ int port = Integer.parseInt(args[0]);
+ System.out.println("INFO: Client connection port = " + port);
+ List<String> lines;
+ try (
+ Socket socket = new Socket(InetAddress.getLocalHost(), port);
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(socket.getInputStream()));
+ PrintWriter out = new PrintWriter(
+ new OutputStreamWriter(socket.getOutputStream()))) {
+ // send own pid to execute jcmd if needed
+ out.println(String.valueOf(pid));
+ out.flush();
+ lines = in.lines().collect(Collectors.toList());
+ } catch (IOException e) {
+ throw new Error("Error on performing network operation", e);
+ }
+ check(decodeMap(lines));
+ }
+
+ private static Map<Executable, State> decodeMap(List<String> lines) {
+ if (lines == null || lines.size() == 0) {
+ throw new Error("TESTBUG: unexpected lines list");
+ }
+ Map<Executable, State> stateMap = new HashMap<>();
+ int startIndex = 0;
+ ListIterator<String> iterator = lines.listIterator();
+ while (iterator.hasNext()) {
+ int index = iterator.nextIndex();
+ String next = iterator.next();
+ switch (next) {
+ case "{" :
+ startIndex = index;
+ break;
+ case "}" :
+ // method name goes after {
+ Executable executable = METHODS_NAMES.get(lines.get(
+ ++startIndex));
+ // state description starts after method
+ State state = State.fromString(lines.subList(++startIndex,
+ index).toArray(new String[index - startIndex]));
+ stateMap.put(executable, state);
+ break;
+ }
+ }
+ return stateMap;
+ }
+
+ protected static void check(Map<Executable, State> methodStates) {
+ // Check each method from the pool
+ METHODS.forEach(pair -> {
+ Executable x = pair.first;
+ CompileAction.checkCompiled(x, methodStates.get(x));
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/actions/CompileAction.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.actions;
+
+import compiler.compilercontrol.share.scenario.State;
+import compiler.testlibrary.CompilerUtils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Pair;
+import jdk.test.lib.Utils;
+import pool.PoolHelper;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class CompileAction {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final int[] COMP_LEVELS;
+ private static final List<Pair<Executable, Callable<?>>> METHODS
+ = new PoolHelper().getAllMethods();
+ private static final int EXEC_AMOUNT = 100;
+
+ static {
+ COMP_LEVELS = CompilerUtils.getAvailableCompilationLevels();
+ if (COMP_LEVELS.length == 0) {
+ throw new Error("TESTBUG: test requires JIT " +
+ "compiler to be available");
+ }
+ }
+
+ /**
+ * Checks executable if it could be compiled
+ *
+ * @param executable given executable to check
+ * @param state method compilation state
+ */
+ public static void checkCompiled(Executable executable,
+ State state) {
+ int first = COMP_LEVELS[0];
+ if (first < 4) {
+ checkCompilation(executable, first, state.isC1Compilable());
+ }
+ int last = COMP_LEVELS[COMP_LEVELS.length - 1];
+ if (last == 4) {
+ checkCompilation(executable, last, state.isC2Compilable());
+ }
+ }
+
+ private static void checkCompilation(Executable executable,
+ int level,
+ boolean expectedCompiled) {
+ execute(executable);
+ WHITE_BOX.enqueueMethodForCompilation(executable, level);
+ Utils.waitForCondition(
+ () -> {
+ execute(executable);
+ return !WHITE_BOX.isMethodQueuedForCompilation(executable);
+ }, 100L);
+ execute(executable);
+ boolean isCompilable = WHITE_BOX.isMethodCompilable(executable, level);
+ Asserts.assertEQ(isCompilable, expectedCompiled,
+ String.format("FAILED: method %s compilable: %b, but should: %b"
+ + " on required level: %d", executable, isCompilable,
+ expectedCompiled, level));
+ }
+
+ private static void execute(Executable executable) {
+ Callable<?> callable = getCallableFor(executable);
+ try {
+ for (int i = 0; i < EXEC_AMOUNT; i++) {
+ callable.call();
+ }
+ } catch (Exception e) {
+ throw new Error("Got exception during execution", e);
+ }
+ }
+
+ private static Callable<?> getCallableFor(Executable executable) {
+ for (Pair<Executable, Callable<?>> pair : METHODS) {
+ if (pair.first == executable) {
+ return pair.second;
+ }
+ }
+ throw new Error("TESTBUG: wrong executable: " + executable);
+ }
+}
--- a/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java Wed Jul 05 20:59:18 2017 +0200
@@ -124,6 +124,23 @@
}
/**
+ * Method descriptor that matches any method. Its full signature is *.*
+ *
+ * @param executable executable used to generate descriptor
+ * @return MethodDescriptor instance
+ */
+ public static MethodDescriptor anyMatchDescriptor(Executable executable) {
+ MethodDescriptor md = new MethodDescriptor(executable);
+ Combination<PatternType> patterns = new Combination<>(PatternType.ANY,
+ PatternType.ANY, PatternType.ANY);
+ md.aClass.setSeparator(Separator.SLASH);
+ md.aMethod.setSeparator(Separator.DOT);
+ md.aSignature.setSeparator(Separator.NONE);
+ md.setPatterns(patterns);
+ return md;
+ }
+
+ /**
* Generates a list of method patterns from the pool of methods
*
* @return a list of test cases
@@ -206,6 +223,8 @@
elements.add(input -> "_" + input);
elements.add(input -> "$" + input);
elements.add(input -> "0" + input);
+
+ /* TODO: uncomment this together with the fix for 8140631
// Unicode characters
elements.add(input -> embed(input, "\u0001"));
elements.add(input -> embed(input, "\u007F"));
@@ -214,6 +233,7 @@
elements.add(input -> embed(input, "\u0306"));
// Supplementary character
elements.add(input -> new String(Character.toChars(0x1F64C)));
+ */
return elements;
}
--- a/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java Wed Jul 05 20:59:18 2017 +0200
@@ -29,6 +29,7 @@
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.Arrays;
+import java.util.regex.Pattern;
/**
* This class represents a signature of the method
@@ -66,7 +67,8 @@
if (element.isEmpty()) {
setPattern(MethodDescriptor.PatternType.ANY);
} else {
- super.setElement(element);
+ this.element = element;
+ this.regexp = element;
}
}
@@ -148,4 +150,12 @@
+ patternType);
}
}
+
+ @Override
+ public String getRegexp() {
+ if ("\\(.*\\).*".equals(regexp)) {
+ return regexp;
+ }
+ return Pattern.quote(regexp);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import jdk.test.lib.OutputAnalyzer;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Checks that output contains a string with commands and full method pattern
+ */
+public class CommandProcessor implements Consumer<OutputAnalyzer> {
+ protected final List<CompileCommand> commands;
+
+ public CommandProcessor(List<CompileCommand> commands) {
+ this.commands = commands;
+ }
+
+ @Override
+ public void accept(OutputAnalyzer outputAnalyzer) {
+ for (CompileCommand command : commands) {
+ if (command.isValid()) {
+ outputAnalyzer.shouldContain("CompileCommand: "
+ + command.command.name + " "
+ + command.methodDescriptor.getCanonicalString());
+ outputAnalyzer.shouldNotContain("CompileCommand: An error "
+ + "occurred during parsing");
+ } else {
+ outputAnalyzer.shouldMatch("(CompileCommand: )"
+ + "(unrecognized command)|(Bad pattern)|"
+ + "(An error occurred during parsing)");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Log compilation file processor
+ */
+public class LogProcessor implements Consumer<OutputAnalyzer> {
+ public static final String LOG_FILE = "compilation.log";
+ private static final String TASK_ELEMENT = "<task [^>]*>";
+ private static final String TASK_DONE_ELEMENT = "<task_done [^>]*>";
+ private static final String TASK_END_ELEMENT = "</task>";
+ private static final String ANY_ELEMENT = "<[^>]*>";
+ private static final Pattern METHOD_PATTERN = Pattern.compile(
+ "method='([^']+)'");
+ private final List<String> loggedMethods;
+ private final List<String> testMethods;
+ private Scanner scanner = null;
+
+ public LogProcessor(Map<Executable, State> states) {
+ loggedMethods = states.keySet().stream()
+ .filter(x -> states.get(x).isLog())
+ .map(MethodGenerator::logDescriptor)
+ .map(MethodDescriptor::getString)
+ .collect(Collectors.toList());
+ testMethods = new PoolHelper().getAllMethods()
+ .stream()
+ .map(pair -> pair.first)
+ .map(MethodGenerator::logDescriptor)
+ .map(MethodDescriptor::getString)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void accept(OutputAnalyzer outputAnalyzer) {
+ if (loggedMethods.isEmpty()) {
+ return;
+ }
+ getScanner();
+ matchTasks();
+ }
+
+ /*
+ * Gets scanner for log file of the test case
+ */
+ private Scanner getScanner() {
+ File logFile = new File(LOG_FILE);
+ try {
+ scanner = new Scanner(logFile);
+ } catch (FileNotFoundException e) {
+ throw new Error("TESTBUG: file not found: " + logFile, e);
+ }
+ return scanner;
+ }
+
+ /*
+ * Parses for <task method='java.lang.String indexOf (I)I' >
+ * and finds if there is a compilation log for this task
+ */
+ private void matchTasks() {
+ String task = scanner.findWithinHorizon(TASK_ELEMENT, 0);
+ while (task != null) {
+ String element = scanner.findWithinHorizon(ANY_ELEMENT, 0);
+ if (Pattern.matches(TASK_DONE_ELEMENT, element)
+ || Pattern.matches(TASK_END_ELEMENT, element)) {
+ /* If there is nothing between <task> and </task>
+ except <task done /> then compilation log is empty */
+ Asserts.assertTrue(matchMethod(task), "Compilation log "
+ + "expected. Met: " + element);
+ }
+ task = scanner.findWithinHorizon(TASK_ELEMENT, 0);
+ }
+ }
+
+ // Matches given string to regular expression
+ private boolean matchMethod(String input) {
+ Matcher matcher = METHOD_PATTERN.matcher(input);
+ Asserts.assertTrue(matcher.find(), "Wrong matcher or input");
+ // Get method and normalize it
+ String method = normalize(matcher.group(1));
+ // Check that this method matches regexp
+ return loggedMethods.contains(method) || !testMethods.contains(method);
+ }
+
+ // Normalize given signature to conform regular expression used in tests
+ private String normalize(String method) {
+ return method.replaceAll("\\.", "/") // replace dots in a class string
+ .replaceFirst(" ", ".") // replace space between class and method
+ .replaceFirst(" ", "") // remove space between method and signature
+ .replace("<", "<")
+ .replace(">", ">");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/PrintProcessor.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Process output to find compiled methods assemblies printed by print command
+ */
+public class PrintProcessor implements Consumer<OutputAnalyzer> {
+ /**
+ * Compiled method string pattern.
+ * Capturing groups are
+ * 1. Compiler used to compile this method
+ * 2. Time stamp
+ * 3. Compile ID
+ * 4. Method attributes
+ * 5. Compilation level
+ * 6. Method name
+ */
+ private static final Pattern COMPILED_METHOD
+ = Pattern.compile("Compiled method (?<compiler>\\(.*\\))[ ]+"
+ + "(?<time>[0-9]+)[ ]+(?<id>[0-9]+) (?<attr>[ !%sbn]{6})"
+ + "(?<level>[0-9]+)[ ]+(?<name>[^ ]+).*");
+ private final List<String> printMethods;
+ private final List<String> testMethods;
+
+ public PrintProcessor(Map<Executable, State> states) {
+ printMethods = states.keySet().stream()
+ .filter(x -> states.get(x).isPrintAssembly())
+ .map(MethodGenerator::logDescriptor)
+ .map(MethodDescriptor::getString)
+ .map(s -> s.replaceFirst("\\(.*", "")) // remove signature
+ .collect(Collectors.toList());
+ testMethods = new PoolHelper().getAllMethods()
+ .stream()
+ .map(pair -> pair.first)
+ .map(MethodGenerator::logDescriptor)
+ .map(MethodDescriptor::getString)
+ .map(s -> s.replaceFirst("\\(.*", "")) // remove signature
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void accept(OutputAnalyzer outputAnalyzer) {
+ boolean wizardMode = false;
+ try {
+ wizardMode = Boolean.parseBoolean(ManagementFactory
+ .getPlatformMXBean(HotSpotDiagnosticMXBean.class)
+ .getVMOption("WizardMode").getValue());
+ } catch (IllegalArgumentException e) {
+ // ignore exception because WizardMode exists in debug only builds
+ }
+ if (wizardMode) {
+ System.out.println("SKIP: WizardMode's output are not supported");
+ return;
+ }
+ for (String line : outputAnalyzer.asLines()) {
+ Matcher matcher = COMPILED_METHOD.matcher(line);
+ if (matcher.matches()) {
+ String method = normalize(matcher.group("name"));
+ if (!printMethods.contains(normalize(method))
+ && testMethods.contains(method)) {
+ System.out.println(outputAnalyzer.getOutput());
+ throw new AssertionError("FAILED: wrong method "
+ + "was printed: " + method + " LINE: " + line);
+ }
+ }
+ }
+ }
+
+ // Normalize given signature to conform regular expression used in tests
+ private String normalize(String method) {
+ return method.replaceAll("\\.", "/") // replace dots in a class string
+ .replaceFirst("::", ".") // replace :: between class and method
+ .replace("<", "<")
+ .replace(">", ">");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/QuietProcessor.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import jdk.test.lib.OutputAnalyzer;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class QuietProcessor implements Consumer<OutputAnalyzer> {
+ private final List<CompileCommand> commands;
+
+ public QuietProcessor(List<CompileCommand> compileCommands) {
+ commands = compileCommands;
+ }
+
+ @Override
+ public void accept(OutputAnalyzer outputAnalyzer) {
+ for (CompileCommand command : commands) {
+ if (command.isValid()) {
+ outputAnalyzer.shouldNotContain("CompileCommand: "
+ + command.command.name + " "
+ + command.methodDescriptor.getCanonicalString());
+ outputAnalyzer.shouldNotContain("CompileCommand: An error "
+ + "occurred during parsing");
+ } else {
+ outputAnalyzer.shouldMatch("(CompileCommand: )"
+ + "(unrecognized command)|(Bad pattern)|"
+ + "(An error occurred during parsing)");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/AbstractCommandBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * An abstract class that builds states by applying
+ * commands one after another
+ */
+public abstract class AbstractCommandBuilder
+ implements StateBuilder<CompileCommand> {
+ protected static final List<Pair<Executable, Callable<?>>> METHODS
+ = new PoolHelper().getAllMethods();
+ protected final List<CompileCommand> compileCommands = new ArrayList<>();
+
+ @Override
+ public void add(CompileCommand command) {
+ compileCommands.add(command);
+ }
+
+ @Override
+ public Map<Executable, State> getStates() {
+ Map<Executable, State> states = new HashMap<>();
+ for (CompileCommand compileCommand : compileCommands) {
+ if (compileCommand.isValid()) {
+ CompileCommand cc = new CompileCommand(compileCommand.command,
+ compileCommand.methodDescriptor,
+ /* CompileCommand option and file doesn't support
+ compiler setting */
+ null,
+ compileCommand.type);
+ MethodDescriptor md = cc.methodDescriptor;
+ for (Pair<Executable, Callable<?>> pair: METHODS) {
+ Executable exec = pair.first;
+ State state = states.getOrDefault(exec, new State());
+ MethodDescriptor execDesc = new MethodDescriptor(exec);
+ // if executable matches regex then apply the state
+ if (execDesc.getCanonicalString().matches(md.getRegexp())) {
+ state.apply(cc);
+ } else {
+ if (cc.command == Command.COMPILEONLY) {
+ state.setC1Compilable(false);
+ state.setC2Compilable(false);
+ }
+ }
+ states.put(exec, state);
+ }
+ }
+ }
+ return states;
+ }
+
+ @Override
+ public List<CompileCommand> getCompileCommands() {
+ return Collections.unmodifiableList(compileCommands);
+ }
+
+ @Override
+ public boolean isValid() {
+ // CompileCommand ignores invalid items
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/Command.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.processors.LogProcessor;
+import java.util.Arrays;
+
+/**
+ * Represents a CompileCommand command set
+ */
+public enum Command {
+ COMPILEONLY("compileonly", ".*", "-Xbatch"),
+ EXCLUDE("exclude", "", "-Xbatch"),
+ INLINE("inline", ".*"),
+ DONTINLINE("dontinline", ""),
+ LOG("log", "", "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+LogCompilation", "-XX:LogFile=" + LogProcessor.LOG_FILE),
+ PRINT("print", ""),
+ QUIET("quiet", ""),
+ NONEXISTENT("nonexistent", ""); // wrong command for a negative case
+
+ /**
+ * Command name
+ */
+ public final String name;
+
+ /**
+ * Base regular expression
+ */
+ public final String regex;
+
+ /**
+ * Additional VM options for this command
+ */
+ public final String[] vmOpts;
+
+ private Command(String name, String regex, String... vmOptions) {
+ this.name = name;
+ this.regex = regex;
+ String[] wbOpts = new String[] { "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI" };
+ int length = (vmOptions != null) ? vmOptions.length : 0;
+ this.vmOpts = Arrays.copyOf(wbOpts, wbOpts.length + length);
+ if (vmOptions != null) {
+ System.arraycopy(vmOptions, 0, vmOpts, wbOpts.length, length);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandFileBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Creates CompileCommandFile from the given array of commands
+ */
+public class CommandFileBuilder extends AbstractCommandBuilder {
+ private final String fileName;
+
+ public CommandFileBuilder(String fileName) {
+ this.fileName = fileName;
+ }
+
+ @Override
+ public List<String> getOptions() {
+ // Create CommandFile
+ try (PrintWriter pw = new PrintWriter(fileName)) {
+ compileCommands.stream()
+ .map(cc -> cc.command.name + " "
+ + cc.methodDescriptor.getString())
+ .forEach(pw::println);
+ if (pw.checkError()) {
+ throw new Error("TESTBUG: write error");
+ }
+ } catch (IOException e) {
+ throw new Error("TESTBUG: can't write a file", e);
+ }
+ List<String> opt = new ArrayList<>();
+ opt.add("-XX:CompileCommandFile=" + fileName);
+ return opt;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandGenerator.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import jdk.test.lib.Utils;
+
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Generates random commands
+ */
+public class CommandGenerator {
+ private static final int MAX_COMMANDS = Integer.getInteger(
+ "compiler.compilercontrol.share.scenario.CommandGenerator.commands",
+ 100);
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ /**
+ * Generates random command
+ *
+ * @return command
+ */
+ public Command generateCommand() {
+ return Utils.getRandomElement(Command.values());
+ }
+
+ /**
+ * Generates random number of random command
+ *
+ * @return a list of random commands
+ */
+ public List<Command> generateCommands() {
+ int amount = 1 + RANDOM.nextInt(MAX_COMMANDS - 1);
+ return generateCommands(amount);
+ }
+
+ /**
+ * Generates specified amount of random command
+ *
+ * @param amount amount of commands to generate
+ * @return a list of random commands
+ */
+ public List<Command> generateCommands(int amount) {
+ return Stream.generate(this::generateCommand)
+ .limit(amount)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Generates random compile command {@link CompileCommand} with specified
+ * command and method descriptor
+ *
+ * @param command a command type
+ * @param md a method descriptor
+ * @param type a type of the command, or null to generate any
+ * @return the generated compile command
+ */
+ public CompileCommand generateCompileCommand(Command command,
+ MethodDescriptor md, Scenario.Type type) {
+ if (type == null) {
+ type = Utils.getRandomElement(Scenario.Type.values());
+ }
+ return type.createCompileCommand(command, md, generateCompiler());
+ }
+
+ /**
+ * Generates type of compiler that should be used for the command, or null
+ * if any or all compilers should be used
+ *
+ * @return Compiler value, or null
+ */
+ public Scenario.Compiler generateCompiler() {
+ Scenario.Compiler[] compilers = Scenario.Compiler.values();
+ int compiler = RANDOM.nextInt(compilers.length + 1) - 1;
+ return (compiler != -1) ? compilers[compiler] : null;
+ }
+
+ /**
+ * Generates random diagnostic command
+ * {@link Scenario.Type}
+ */
+ public Scenario.JcmdType generateJcmdType() {
+ return Utils.getRandomElement(Scenario.JcmdType.values());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandOptionsBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Creates VM options by adding CompileCommand prefix to commands
+ */
+public class CommandOptionsBuilder extends AbstractCommandBuilder {
+ @Override
+ public List<String> getOptions() {
+ return compileCommands.stream()
+ .map(cc -> "-XX:CompileCommand="
+ + cc.command.name
+ + MethodDescriptor.Separator.COMMA.symbol
+ + cc.methodDescriptor.getString())
+ .collect(Collectors.toList());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CompileCommand.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+/**
+ * Compile Command description interface
+ */
+public class CompileCommand {
+ public final Command command;
+ public final MethodDescriptor methodDescriptor;
+ public final Scenario.Compiler compiler;
+ public final Scenario.Type type;
+
+ public CompileCommand(Command command,
+ MethodDescriptor methodDescriptor,
+ Scenario.Compiler compiler,
+ Scenario.Type type) {
+ this.command = command;
+ this.methodDescriptor = methodDescriptor;
+ this.compiler = compiler;
+ this.type = type;
+ }
+
+ /**
+ * Shows that this compile command is valid
+ *
+ * @return true if this is a valid command
+ */
+ public boolean isValid() {
+ if (command == Command.NONEXISTENT) {
+ return false;
+ }
+ return methodDescriptor.isValid();
+ }
+
+ /**
+ * Prints compile command to the system output
+ */
+ public void print() {
+ System.out.printf("%s (type: %s): %s (valid: %b)%n", command.name(),
+ type.name(), methodDescriptor.getString(), isValid());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.JSONFile;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.concurrent.Callable;
+
+/**
+ * Directive file and state builder class
+ */
+public class DirectiveBuilder implements StateBuilder<CompileCommand> {
+ private static final List<Pair<Executable, Callable<?>>> METHODS
+ = new PoolHelper().getAllMethods();
+ private final Map<Executable, State> stateMap = new HashMap<>();
+ private final String fileName;
+ private Map<MethodDescriptor, List<CompileCommand>> matchBlocks
+ = new LinkedHashMap<>();
+ private List<String> inlineMatch = new ArrayList<>();
+ private boolean isFileValid = true;
+
+ public DirectiveBuilder(String fileName) {
+ this.fileName = fileName;
+ }
+
+ @Override
+ public List<String> getOptions() {
+ List<String> options = new ArrayList<>();
+ if (!matchBlocks.isEmpty()) {
+ // add option only if there are any directive available
+ options.add("-XX:CompilerDirectivesFile=" + fileName);
+ }
+ return options;
+ }
+
+ @Override
+ public List<CompileCommand> getCompileCommands() {
+ throw new Error("TESTBUG: isn't applicable for directives");
+ }
+
+ @Override
+ public boolean isValid() {
+ // Invalid directives file makes VM exit with error code
+ return isFileValid;
+ }
+
+ @Override
+ public Map<Executable, State> getStates() {
+ try (DirectiveWriter dirFile = new DirectiveWriter(fileName)) {
+ for (MethodDescriptor matchDescriptor : matchBlocks.keySet()) {
+ // Write match block with all options converted from commands
+ dirFile.match(matchDescriptor);
+ for (CompileCommand compileCommand :
+ matchBlocks.get(matchDescriptor)) {
+ isFileValid &= compileCommand.isValid();
+ handleCommand(dirFile, compileCommand);
+ }
+ if ("Inlinee.caller".matches((matchDescriptor.getRegexp()))) {
+ // Got a *.* match block, where inline would be written
+ dirFile.inline(inlineMatch.toArray(
+ new String[inlineMatch.size()]));
+ inlineMatch.clear();
+ }
+ dirFile.end(); // ends match block
+ }
+
+ /*
+ * Write inline directive in the end to the latest match block
+ * if we didn't do this before
+ * Inlinee caller methods should match this block only
+ */
+ if (!inlineMatch.isEmpty()) {
+ Pair<Executable, Callable<?>> pair = METHODS.get(0);
+ MethodDescriptor md = MethodGenerator.anyMatchDescriptor(
+ pair.first);
+ CompileCommand cc = new CompileCommand(Command.QUIET, md, null,
+ Scenario.Type.DIRECTIVE);
+ List<CompileCommand> commands = new ArrayList<>();
+
+ // Add appropriate "*.*" match block
+ commands.add(cc);
+ matchBlocks.put(md, commands);
+ // Add match block for this descriptor with inlines
+ dirFile.match(md);
+ dirFile.inline(inlineMatch.toArray(
+ new String[inlineMatch.size()]));
+ dirFile.end();
+ }
+ if (!matchBlocks.isEmpty()) {
+ // terminates file
+ dirFile.end();
+ }
+
+ // Build states for each method according to match blocks
+ for (Pair<Executable, Callable<?>> pair : METHODS) {
+ State state = getState(pair);
+ if (state != null) {
+ stateMap.put(pair.first, state);
+ }
+ }
+ }
+ if (isFileValid) {
+ return stateMap;
+ } else {
+ // return empty map because invalid file doesn't change states
+ return new HashMap<>();
+ }
+ }
+
+ private State getState(Pair<Executable, Callable<?>> pair) {
+ State state = null;
+ MethodDescriptor execDesc = MethodGenerator.commandDescriptor(
+ pair.first);
+ boolean isMatchFound = false;
+
+ if (stateMap.containsKey(pair.first)) {
+ state = stateMap.get(pair.first);
+ }
+ for (MethodDescriptor matchDesc : matchBlocks.keySet()) {
+ if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) {
+ /*
+ * if executable matches regex
+ * then apply commands from this match to the state
+ */
+ for (CompileCommand cc : matchBlocks.get(matchDesc)) {
+ state = new State();
+ if (!isMatchFound) {
+ // this is a first found match, apply all commands
+ state.apply(cc);
+ } else {
+ // apply only inline directives
+ switch (cc.command) {
+ case INLINE:
+ case DONTINLINE:
+ state.apply(cc);
+ break;
+ }
+ }
+ }
+ isMatchFound = true;
+ }
+ }
+ return state;
+ }
+
+ private void handleCommand(DirectiveWriter dirFile, CompileCommand cmd) {
+ Command command = cmd.command;
+
+ switch (command) {
+ case COMPILEONLY:
+ dirFile.excludeCompile(cmd.compiler, false);
+ break;
+ case EXCLUDE:
+ dirFile.excludeCompile(cmd.compiler, true);
+ break;
+ case INLINE:
+ case DONTINLINE:
+ // Inline commands will be written later
+ break;
+ case LOG:
+ dirFile.option(DirectiveWriter.Option.LOG, true);
+ break;
+ case QUIET:
+ // there are no appropriate directive for this
+ break;
+ case PRINT:
+ dirFile.option(DirectiveWriter.Option.PRINT_ASSEMBLY, true);
+ break;
+ case NONEXISTENT:
+ dirFile.write(JSONFile.Element.PAIR, command.name);
+ dirFile.write(JSONFile.Element.OBJECT);
+ dirFile.write(JSONFile.Element.PAIR, command.name);
+ dirFile.write(JSONFile.Element.VALUE,
+ cmd.methodDescriptor.getString());
+ dirFile.end(); // ends object
+ break;
+ default:
+ throw new Error("TESTBUG: wrong command: " + command);
+ }
+ }
+
+ @Override
+ public void add(CompileCommand compileCommand) {
+ MethodDescriptor methodDescriptor = compileCommand.methodDescriptor;
+
+ switch (compileCommand.command) {
+ case INLINE:
+ inlineMatch.add("+" + methodDescriptor.getString());
+ break;
+ case DONTINLINE:
+ inlineMatch.add("-" + methodDescriptor.getString());
+ break;
+ }
+ for (MethodDescriptor md: matchBlocks.keySet()) {
+ if (methodDescriptor.getCanonicalString().matches(md.getRegexp())) {
+ matchBlocks.get(md).add(compileCommand);
+ }
+ }
+ if (!matchBlocks.containsKey(compileCommand.methodDescriptor)) {
+ List<CompileCommand> commands = new ArrayList<>();
+ commands.add(compileCommand);
+ matchBlocks.put(compileCommand.methodDescriptor, commands);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveWriter.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.JSONFile;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+/**
+ * Simple directive file writer.
+ */
+public class DirectiveWriter implements AutoCloseable {
+ private final JSONFile jsonFile;
+
+ /**
+ * Builds directive file for the given name
+ *
+ * @param fileName name the file to be created
+ */
+ public DirectiveWriter(String fileName) {
+ jsonFile = new JSONFile(fileName);
+ }
+
+ /**
+ * Emits match block with a given methods
+ *
+ * @param methods methods used for the match
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter match(String... methods) {
+ if (jsonFile.getElement() == null) {
+ write(JSONFile.Element.ARRAY);
+ }
+ write(JSONFile.Element.OBJECT);
+ write(JSONFile.Element.PAIR, "match");
+ writeMethods(methods);
+ return this;
+ }
+
+ /**
+ * Emits match block with a given methods
+ *
+ * @param methodDescriptors method descriptors used for the match
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter match(MethodDescriptor... methodDescriptors) {
+ String[] methods = new String[methodDescriptors.length];
+ for (int i = 0; i < methodDescriptors.length; i++) {
+ methods[i] = methodDescriptors[i].getString();
+ }
+ match(methods);
+ return this;
+ }
+
+ /**
+ * Emits inline block with a given methods to be inlined or not.
+ * Each method should be prepended with + or - to show if it should be
+ * inlined or not.
+ *
+ * @param methods methods used for the inline
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter inline(String... methods) {
+ write(JSONFile.Element.PAIR, "inline");
+ writeMethods(methods);
+ return this;
+ }
+
+ private void writeMethods(String[] methods) {
+ if (methods.length == 0) {
+ throw new IllegalArgumentException("ERROR: empty methods array");
+ }
+ if (methods.length > 1) {
+ write(JSONFile.Element.ARRAY);
+ for (String method : methods) {
+ write(JSONFile.Element.VALUE, "\"" + method + "\"");
+ }
+ end(); // ends array
+ } else {
+ write(JSONFile.Element.VALUE, "\"" + methods[0] + "\"");
+ }
+ }
+
+ /**
+ * Emits compiler blocks that makes current match to be excluded or not
+ * from compilation with specified compiler
+ *
+ * @param compiler compiler to be excluded or null, for all
+ * @param exclude shows if compiler should be disabled for this match
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter excludeCompile(Scenario.Compiler compiler,
+ boolean exclude) {
+ if (compiler != null) {
+ emitCompiler(compiler);
+ option(Option.EXCLUDE, exclude);
+ end();
+ } else {
+ for (Scenario.Compiler comp : Scenario.Compiler.values()) {
+ emitCompiler(comp);
+ option(Option.EXCLUDE, exclude);
+ end(); // end compiler block
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Emits compiler directive block
+ *
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter emitCompiler(Scenario.Compiler compiler) {
+ write(JSONFile.Element.PAIR, compiler.name);
+ write(JSONFile.Element.OBJECT);
+ return this;
+ }
+
+ @Override
+ public void close() {
+ jsonFile.close();
+ }
+
+ /**
+ * Ends current object element. It could be either a
+ * c1 or c2 block, or a whole match block
+ *
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter end() {
+ jsonFile.end();
+ return this;
+ }
+
+ public DirectiveWriter write(JSONFile.Element element, String... value) {
+ jsonFile.write(element, value);
+ return this;
+ }
+
+ /**
+ * Emits directive option with a given value
+ *
+ * @param option directive to be set
+ * @param value value of the directive
+ * @return this DirectiveWriter instance
+ */
+ public DirectiveWriter option(Option option, Object value) {
+ write(JSONFile.Element.PAIR, option.string);
+ write(JSONFile.Element.VALUE, String.valueOf(value));
+ return this;
+ }
+
+ /**
+ * Directive option list
+ */
+ public enum Option {
+ PRINT_ASSEMBLY("PrintAssembly"),
+ LOG("Log"),
+ EXCLUDE("Exclude");
+
+ public final String string;
+
+ private Option(String directive) {
+ this.string = directive;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/JcmdCommand.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+public class JcmdCommand extends CompileCommand {
+ public final Scenario.JcmdType jcmdType;
+
+ public JcmdCommand(Command command,
+ MethodDescriptor methodDescriptor,
+ Scenario.Compiler compiler,
+ Scenario.Type type,
+ Scenario.JcmdType jcmdType) {
+ super(command, methodDescriptor, compiler, type);
+ this.jcmdType = jcmdType;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/JcmdStateBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import pool.PoolHelper;
+import jdk.test.lib.Pair;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
+ private static final List<Pair<Executable, Callable<?>>> METHODS
+ = new PoolHelper().getAllMethods();
+ private final Map<Executable, State> stateMap = new HashMap<>();
+ private final DirectiveBuilder directiveBuilder;
+ private Map<MethodDescriptor, List<CompileCommand>> matchBlocks
+ = new LinkedHashMap<>();
+ private List<JcmdCommand> commands = new ArrayList<>();
+ private boolean isFileValid = true;
+
+ public JcmdStateBuilder(String fileName) {
+ directiveBuilder = new DirectiveBuilder(fileName);
+ }
+
+ @Override
+ public void add(JcmdCommand compileCommand) {
+ commands.add(compileCommand);
+ switch (compileCommand.jcmdType) {
+ case ADD:
+ directiveBuilder.add(compileCommand);
+ addCommand(compileCommand);
+ break;
+ case PRINT:
+ // doesn't change the state
+ break;
+ case CLEAR:
+ matchBlocks.clear();
+ break;
+ case REMOVE:
+ removeDirective();
+ break;
+ }
+ }
+
+ private void addCommand(JcmdCommand compileCommand) {
+ isFileValid &= compileCommand.isValid();
+ for (MethodDescriptor md: matchBlocks.keySet()) {
+ if (compileCommand.methodDescriptor.getCanonicalString()
+ .matches(md.getRegexp())) {
+ matchBlocks.get(md).add(compileCommand);
+ }
+ }
+ List<CompileCommand> commands = new ArrayList<>();
+ commands.add(compileCommand);
+ matchBlocks.put(compileCommand.methodDescriptor, commands);
+ }
+
+ private void removeDirective() {
+ Iterator<MethodDescriptor> iterator = matchBlocks.keySet().iterator();
+ if (iterator.hasNext()) {
+ MethodDescriptor md = iterator.next();
+ matchBlocks.remove(md);
+ }
+ }
+
+ @Override
+ public boolean isValid() {
+ // VM skips invalid directive file added via jcmd command
+ return true;
+ }
+
+ @Override
+ public Map<Executable, State> getStates() {
+ directiveBuilder.getStates();
+ // Build states for each method according to match blocks
+ for (Pair<Executable, Callable<?>> pair : METHODS) {
+ State state = getState(pair);
+ if (state != null) {
+ stateMap.put(pair.first, state);
+ }
+ }
+ if (isFileValid) {
+ return stateMap;
+ } else {
+ // return empty map because invalid file doesn't change states
+ return new HashMap<>();
+ }
+ }
+
+ private State getState(Pair<Executable, Callable<?>> pair) {
+ State state = null;
+ MethodDescriptor execDesc = MethodGenerator.commandDescriptor(
+ pair.first);
+ boolean isMatchFound = false;
+
+ if (stateMap.containsKey(pair.first)) {
+ state = stateMap.get(pair.first);
+ }
+ for (MethodDescriptor matchDesc : matchBlocks.keySet()) {
+ if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) {
+ /*
+ * if executable matches regex
+ * then apply commands from this match to the state
+ */
+ for (CompileCommand cc : matchBlocks.get(matchDesc)) {
+ state = new State();
+ if (!isMatchFound) {
+ // this is a first found match, apply all commands
+ state.apply(cc);
+ } else {
+ // apply only inline directives
+ switch (cc.command) {
+ case INLINE:
+ case DONTINLINE:
+ state.apply(cc);
+ break;
+ }
+ }
+ }
+ isMatchFound = true;
+ }
+ }
+ return state;
+ }
+
+ @Override
+ public List<String> getOptions() {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public List<JcmdCommand> getCompileCommands() {
+ return commands;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.actions.BaseAction;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.processors.CommandProcessor;
+import compiler.compilercontrol.share.processors.LogProcessor;
+import compiler.compilercontrol.share.processors.PrintProcessor;
+import compiler.compilercontrol.share.processors.QuietProcessor;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.dcmd.CommandExecutorException;
+import jdk.test.lib.dcmd.JcmdExecutor;
+import pool.PoolHelper;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.reflect.Executable;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+
+/**
+ * Test scenario
+ */
+public final class Scenario {
+ private final boolean isValid;
+ private final List<String> vmopts;
+ private final Map<Executable, State> states;
+ private final List<Consumer<OutputAnalyzer>> processors;
+ private final List<String> jcmdExecCommands;
+
+ private Scenario(boolean isValid,
+ List<String> vmopts,
+ Map<Executable, State> states,
+ List<CompileCommand> compileCommands,
+ List<JcmdCommand> jcmdCommands) {
+ this.isValid = isValid;
+ this.vmopts = vmopts;
+ this.states = states;
+ processors = new ArrayList<>();
+ processors.add(new LogProcessor(states));
+ processors.add(new PrintProcessor(states));
+ List<CompileCommand> nonQuieted = new ArrayList<>();
+ List<CompileCommand> quieted = new ArrayList<>();
+ boolean metQuiet = false;
+ for (CompileCommand cc : compileCommands) {
+ metQuiet |= cc.command == Command.QUIET;
+ if (metQuiet) {
+ quieted.add(cc);
+ } else {
+ nonQuieted.add(cc);
+ }
+ }
+ processors.add(new CommandProcessor(nonQuieted));
+ processors.add(new QuietProcessor(quieted));
+ jcmdExecCommands = new ArrayList<>();
+ boolean addCommandMet = false;
+ for (JcmdCommand cmd : jcmdCommands) {
+ switch (cmd.jcmdType) {
+ case ADD:
+ if (!addCommandMet) {
+ jcmdExecCommands.add(JcmdType.ADD.command);
+ }
+ addCommandMet = true;
+ break;
+ default:
+ jcmdExecCommands.add(cmd.jcmdType.command);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Executes scenario
+ */
+ public void execute() {
+ // Construct execution command with CompileCommand and class
+ List<String> argsList = new ArrayList<>();
+ // Add VM options
+ argsList.addAll(vmopts);
+ // Add class name that would be executed in a separate VM
+ String classCmd = BaseAction.class.getName();
+ argsList.add(classCmd);
+ OutputAnalyzer output;
+ try (ServerSocket serverSocket = new ServerSocket(0)) {
+ if (isValid) {
+ // Get port test VM will connect to
+ int port = serverSocket.getLocalPort();
+ if (port == -1) {
+ throw new Error("Socket is not bound: " + port);
+ }
+ argsList.add(String.valueOf(port));
+ // Start separate thread to connect with test VM
+ new Thread(() -> connectTestVM(serverSocket)).start();
+ }
+ // Start test VM
+ output = ProcessTools.executeTestJvmAllArgs(
+ argsList.toArray(new String[argsList.size()]));
+ } catch (Throwable thr) {
+ throw new Error("Execution failed", thr);
+ }
+ if (isValid) {
+ output.shouldHaveExitValue(0);
+ for (Consumer<OutputAnalyzer> processor : processors) {
+ processor.accept(output);
+ }
+ } else {
+ Asserts.assertNE(output.getExitValue(), 0, "VM should exit with "
+ + "error for incorrect directives");
+ output.shouldContain("Parsing of compiler directives failed");
+ }
+ }
+
+ /*
+ * Performs connection with a test VM, sends method states and performs
+ * JCMD operations on a test VM.
+ */
+ private void connectTestVM(ServerSocket serverSocket) {
+ /*
+ * There are no way to prove that accept was invoked before we started
+ * test VM that connects to this serverSocket. Connection timeout is
+ * enough
+ */
+ try (
+ Socket socket = serverSocket.accept();
+ PrintWriter pw = new PrintWriter(socket.getOutputStream(),
+ true);
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ socket.getInputStream()))) {
+ // Get pid of the executed process
+ int pid = Integer.parseInt(in.readLine());
+ Asserts.assertNE(pid, 0, "Got incorrect pid");
+ executeJCMD(pid);
+ // serialize and send state map
+ for (Executable x : states.keySet()) {
+ pw.println("{");
+ pw.println(x.toGenericString());
+ pw.println(states.get(x).toString());
+ pw.println("}");
+ }
+ } catch (IOException e) {
+ throw new Error("Failed to write data", e);
+ }
+ }
+
+ // Executes all diagnostic commands
+ private void executeJCMD(int pid) {
+ for (String command : jcmdExecCommands) {
+ new JcmdExecutor() {
+ @Override
+ protected List<String> createCommandLine(String cmd)
+ throws CommandExecutorException {
+ return Arrays.asList(jcmdBinary, Integer.toString(pid),
+ cmd);
+ }
+ }.execute(command);
+ }
+ }
+
+ /**
+ * Gets states of methods for this scenario
+ *
+ * @return pairs of executable and its state
+ */
+ public Map<Executable, State> getStates() {
+ return states;
+ }
+
+ public static enum Compiler {
+ C1("c1"),
+ C2("c2");
+
+ public final String name;
+
+ Compiler(String name) {
+ this.name = name;
+ }
+ }
+
+ /**
+ * Type of diagnostic (jcmd) command
+ */
+ public static enum JcmdType {
+ ADD("Compiler.directives_add " + Type.JCMD.fileName),
+ PRINT("Compiler.directives_print"),
+ CLEAR("Compiler.directives_clear"),
+ REMOVE("Compiler.directives_remove");
+
+ public final String command;
+ private JcmdType(String command) {
+ this.command = command;
+ }
+ }
+
+ /**
+ * Type of the compile command
+ */
+ public static enum Type {
+ OPTION(""),
+ FILE("command_file"),
+ DIRECTIVE("directives.json"),
+ JCMD("jcmd_directives.json") {
+ @Override
+ public CompileCommand createCompileCommand(Command command,
+ MethodDescriptor md, Compiler compiler) {
+ return new JcmdCommand(command, md, compiler, this,
+ JcmdType.ADD);
+ }
+ };
+
+ public final String fileName;
+
+ public CompileCommand createCompileCommand(Command command,
+ MethodDescriptor md, Compiler compiler) {
+ return new CompileCommand(command, md, compiler, this);
+ }
+
+ private Type(String fileName) {
+ this.fileName = fileName;
+ }
+ }
+
+ public static Builder getBuilder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private final Set<String> vmopts = new LinkedHashSet<>();
+ private final Map<Type, StateBuilder<CompileCommand>> builders
+ = new HashMap<>();
+ private final JcmdStateBuilder jcmdStateBuilder;
+
+ public Builder() {
+ builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName));
+ builders.put(Type.OPTION, new CommandOptionsBuilder());
+ builders.put(Type.DIRECTIVE, new DirectiveBuilder(
+ Type.DIRECTIVE.fileName));
+ jcmdStateBuilder = new JcmdStateBuilder(Type.JCMD.fileName);
+ }
+
+ public void add(CompileCommand compileCommand) {
+ String[] vmOptions = compileCommand.command.vmOpts;
+ Collections.addAll(vmopts, vmOptions);
+ if (compileCommand.type == Type.JCMD) {
+ jcmdStateBuilder.add((JcmdCommand) compileCommand);
+ } else {
+ StateBuilder<CompileCommand> builder = builders.get(
+ compileCommand.type);
+ if (builder == null) {
+ throw new Error("TESTBUG: Missing builder for the type: "
+ + compileCommand.type);
+ }
+ builder.add(compileCommand);
+ }
+ }
+
+ public Scenario build() {
+ boolean isValid = true;
+
+ // Get states from each of the state builders
+ Map<Executable, State> commandFileStates
+ = builders.get(Type.FILE).getStates();
+ Map<Executable, State> commandOptionStates
+ = builders.get(Type.OPTION).getStates();
+ Map<Executable, State> directiveFileStates
+ = builders.get(Type.DIRECTIVE).getStates();
+
+ // get all jcmd commands
+ List<JcmdCommand> jcmdCommands = jcmdStateBuilder
+ .getCompileCommands();
+ boolean isClearedState = false;
+ if (jcmdClearedState(jcmdCommands)) {
+ isClearedState = true;
+ }
+
+ // Merge states
+ List<Pair<Executable, Callable<?>>> methods = new PoolHelper()
+ .getAllMethods();
+ Map<Executable, State> finalStates = new HashMap<>();
+ Map<Executable, State> jcmdStates = jcmdStateBuilder.getStates();
+ for (Pair<Executable, Callable<?>> pair : methods) {
+ Executable x = pair.first;
+ State commandOptionState = commandOptionStates.get(x);
+ State commandFileState = commandFileStates.get(x);
+ State st = State.merge(commandOptionState, commandFileState);
+ if (!isClearedState) {
+ State directiveState = directiveFileStates.get(x);
+ if (directiveState != null) {
+ st = directiveState;
+ }
+ }
+ State jcmdState = jcmdStates.get(x);
+ st = State.merge(st, jcmdState);
+
+ finalStates.put(x, st);
+ }
+
+ /*
+ * Create a list of commands from options and file
+ * to handle quiet command
+ */
+ List<CompileCommand> ccList = new ArrayList<>();
+ ccList.addAll(builders.get(Type.OPTION).getCompileCommands());
+ ccList.addAll(builders.get(Type.FILE).getCompileCommands());
+
+ // Get all VM options after we build all states and files
+ List<String> options = new ArrayList<>();
+ options.addAll(vmopts);
+ for (StateBuilder<?> builder : builders.values()) {
+ options.addAll(builder.getOptions());
+ isValid &= builder.isValid();
+ }
+ options.addAll(jcmdStateBuilder.getOptions());
+ return new Scenario(isValid, options, finalStates, ccList,
+ jcmdCommands);
+ }
+
+ // shows if jcmd have passed a clear command
+ private boolean jcmdClearedState(List<JcmdCommand> jcmdCommands) {
+ for (JcmdCommand jcmdCommand : jcmdCommands) {
+ if (jcmdCommand.jcmdType == JcmdType.CLEAR) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/State.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import jdk.test.lib.Asserts;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Represents method compilation state
+ */
+public class State {
+ // Each of the two-elements array contains a state for each compiler
+ private Optional<Boolean>[] compile =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean>[] forceInline =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean>[] dontInline =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean> printAssembly = Optional.empty();
+ private Optional<Boolean> printInline = Optional.empty();
+ private Optional<Boolean> log = Optional.empty();
+
+ public State() {
+ Arrays.fill(compile, Optional.empty());
+ Arrays.fill(forceInline, Optional.empty());
+ Arrays.fill(dontInline, Optional.empty());
+ }
+
+ /**
+ * Creates state from the string
+ *
+ * @param strings array of strings that represent the state
+ * @return State instance
+ * @see #toString()
+ */
+ public static State fromString(String[] strings) {
+ Asserts.assertNotNull(strings, "Non null array is required");
+ Asserts.assertNE(strings.length, 0, "Non empty array is required");
+ State st = new State();
+ for (String string : strings) {
+ int i = string.indexOf(' ');
+ String command = string.substring(0, i);
+ String values = string.substring(i + 1); // skip space symbol
+ switch (command) {
+ case "compile" :
+ parseArray(st.compile, values);
+ break;
+ case "force_inline" :
+ parseArray(st.forceInline, values);
+ break;
+ case "dont_inline" :
+ parseArray(st.dontInline, values);
+ break;
+ case "log" :
+ st.log = parseElement(values);
+ break;
+ case "print_assembly" :
+ st.printAssembly = parseElement(values);
+ break;
+ case "print_inline" :
+ st.printInline = parseElement(values);
+ break;
+ default:
+ throw new Error("TESTBUG: ");
+ }
+ }
+ return st;
+ }
+
+ private static void parseArray(Optional<Boolean>[] array, String str) {
+ Asserts.assertNotNull(str);
+ int beginBrace = 0;
+ int endBrace = str.length() - 1;
+ if (str.charAt(beginBrace) != '[' || str.charAt(endBrace) != ']') {
+ throw new Error("TESTBUG: not an array type: " + str);
+ }
+ // Get all elements divided with comma as an array
+ String[] strValues = str.substring(beginBrace + 1, endBrace)
+ .split(", ");
+ Asserts.assertEQ(strValues.length, array.length, "Different amount of "
+ + "elements in the string");
+ for (int i = 0; i < strValues.length; i++) {
+ array[i] = parseElement(strValues[i]);
+ }
+ }
+
+ private static Optional<Boolean> parseElement(String str) {
+ Asserts.assertNotNull(str);
+ Asserts.assertTrue(str.startsWith(Optional.class.getSimpleName()),
+ "String is not of type Optional: " + str);
+ if ("Optional.empty".equals(str)) {
+ return Optional.empty();
+ }
+ int begin = str.indexOf('[');
+ Asserts.assertNE(begin, -1, "TEST BUG: Wrong Optional string");
+ int end = str.indexOf(']');
+ Asserts.assertEQ(end, str.length() - 1);
+ boolean b = Boolean.parseBoolean(str.substring(begin + 1, end));
+ return Optional.of(b);
+ }
+
+ /**
+ * Gets string representation of this state
+ */
+ @Override
+ public String toString() {
+ return "compile " + Arrays.toString(compile)
+ + "\nforce_inline " + Arrays.toString(forceInline)
+ + "\ndont_inline " + Arrays.toString(dontInline)
+ + "\nlog " + log
+ + "\nprint_assembly " + printAssembly
+ + "\nprint_inline " + printInline;
+ }
+
+ public boolean isC1Compilable() {
+ return compile[Scenario.Compiler.C1.ordinal()].orElse(true);
+ }
+
+ public boolean isC2Compilable() {
+ return compile[Scenario.Compiler.C2.ordinal()].orElse(true);
+ }
+
+ public boolean isCompilable() {
+ return isC1Compilable() && isC2Compilable();
+ }
+
+ public void setC1Compilable(boolean value) {
+ setCompilable(Scenario.Compiler.C1.ordinal(), value);
+ }
+
+ public void setC2Compilable(boolean value) {
+ setCompilable(Scenario.Compiler.C2.ordinal(), value);
+ }
+
+ public void setCompilable(Scenario.Compiler compiler, boolean value) {
+ if (compiler == null) {
+ setC1Compilable(value);
+ setC2Compilable(value);
+ return;
+ }
+ switch (compiler) {
+ case C1:
+ setC1Compilable(value);
+ break;
+ case C2:
+ setC2Compilable(value);
+ break;
+ default:
+ throw new Error("Unknown compiler");
+ }
+ }
+
+ private void setCompilable(int level, boolean value) {
+ check(level);
+ compile[level] = Optional.of(value);
+ if (!value) {
+ setDontInline(level);
+ }
+ }
+
+ public boolean isC1Inlinable() {
+ return ! dontInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+ }
+
+ public boolean isC2Inlinable() {
+ return ! dontInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+ }
+
+ public boolean isInlinable() {
+ return isC1Inlinable() && isC2Inlinable();
+ }
+
+ private void setDontInline(int level) {
+ check(level);
+ dontInline[level] = Optional.of(true);
+ forceInline[level] = Optional.of(false);
+ }
+
+ private void setForceInline(int level) {
+ check(level);
+ dontInline[level] = Optional.of(false);
+ forceInline[level] = Optional.of(true);
+ }
+
+ public boolean isC1ForceInline() {
+ return forceInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+ }
+
+ public boolean isC2ForceInline() {
+ return forceInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+ }
+
+ public boolean isForceInline() {
+ return isC1ForceInline() && isC2ForceInline();
+ }
+
+ public void setC1Inline(boolean value) {
+ if (value && isC1Compilable()) {
+ setForceInline(Scenario.Compiler.C1.ordinal());
+ } else {
+ setDontInline(Scenario.Compiler.C1.ordinal());
+ }
+ }
+
+ public void setC2Inline(boolean value) {
+ if (value && isC2Compilable()) {
+ setForceInline(Scenario.Compiler.C2.ordinal());
+ } else {
+ setDontInline(Scenario.Compiler.C1.ordinal());
+ }
+ }
+
+ public void setInline(Scenario.Compiler compiler, boolean value) {
+ if (compiler == null) {
+ setC1Inline(value);
+ setC2Inline(value);
+ return;
+ }
+ switch (compiler) {
+ case C1:
+ setC1Inline(value);
+ break;
+ case C2:
+ setC2Inline(value);
+ break;
+ default:
+ throw new Error("Unknown compiler");
+ }
+ }
+
+ public boolean isPrintAssembly() {
+ return printAssembly.orElse(false);
+ }
+
+ public void setPrintAssembly(boolean value) {
+ printAssembly = Optional.of(value);
+ }
+
+ public boolean isPrintInline() {
+ return printInline.orElse(false);
+ }
+
+ public void setPrintInline(boolean value) {
+ printInline = Optional.of(value);
+ }
+
+ public boolean isLog() {
+ return log.orElse(false);
+ }
+
+ public void setLog(boolean log) {
+ this.log = Optional.of(log);
+ }
+
+ private void check(int level) {
+ if (level < 0 || level > compile.length) {
+ throw new IllegalArgumentException("TESTBUG: Wrong level " + level);
+ }
+ }
+
+ /**
+ * Applies given command to the state.
+ *
+ * @param compileCommand command to be applied
+ */
+ public void apply(CompileCommand compileCommand) {
+ switch (compileCommand.command) {
+ case COMPILEONLY:
+ setCompilable(compileCommand.compiler, true);
+ break;
+ case EXCLUDE:
+ setCompilable(compileCommand.compiler, false);
+ break;
+ case INLINE:
+ setInline(compileCommand.compiler, true);
+ break;
+ case DONTINLINE:
+ setInline(compileCommand.compiler, false);
+ break;
+ case LOG:
+ setLog(true);
+ break;
+ case PRINT:
+ setPrintAssembly(true);
+ break;
+ case QUIET:
+ case NONEXISTENT:
+ // doesn't apply the state
+ break;
+ default:
+ throw new Error("Wrong command: " + compileCommand.command);
+ }
+ }
+
+ /**
+ * Merges two given states with different priority
+ *
+ * @param low state with lower merge priority
+ * @param high state with higher merge priority
+ */
+ public static State merge(State low, State high) {
+ if (high == null) {
+ if (low == null) {
+ return new State();
+ }
+ return low;
+ }
+ if (low == null) {
+ return high;
+ }
+ State result = new State();
+ // Compilable
+ result.compile[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.compile[Scenario.Compiler.C1.ordinal()],
+ low.compile[Scenario.Compiler.C1.ordinal()]);
+ result.compile[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.compile[Scenario.Compiler.C2.ordinal()],
+ low.compile[Scenario.Compiler.C2.ordinal()]);
+ // Force inline
+ result.forceInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.forceInline[Scenario.Compiler.C1.ordinal()],
+ low.forceInline[Scenario.Compiler.C1.ordinal()]);
+ result.forceInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.forceInline[Scenario.Compiler.C2.ordinal()],
+ low.forceInline[Scenario.Compiler.C2.ordinal()]);
+ // Don't inline
+ result.dontInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.dontInline[Scenario.Compiler.C1.ordinal()],
+ low.dontInline[Scenario.Compiler.C1.ordinal()]);
+ result.dontInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.dontInline[Scenario.Compiler.C2.ordinal()],
+ low.dontInline[Scenario.Compiler.C2.ordinal()]);
+ // set PrintAssembly
+ result.printAssembly = mergeOptional(high.printAssembly,
+ low.printAssembly);
+ // set PrintInline
+ result.printInline = mergeOptional(high.printInline, low.printInline);
+ // set LogCompilation
+ result.log = mergeOptional(high.log, low.log);
+ return result;
+ }
+
+ private static <T> Optional<T> mergeOptional(Optional<T> high,
+ Optional<T> low) {
+ T val = high.orElse(low.orElse(null));
+ return Optional.ofNullable(val);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/StateBuilder.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+
+public interface StateBuilder<T extends CompileCommand> {
+ /**
+ * Adds CompileCommand to builder
+ *
+ * @param command command used to build states
+ */
+ void add(T command);
+
+ /**
+ * Gets final states of methods
+ *
+ * @return a map with pairs of executables and their states
+ */
+ Map<Executable, State> getStates();
+
+ /**
+ * Gets list of VM options that will change states of methods
+ *
+ * @return a list of VM options
+ */
+ List<String> getOptions();
+
+ /**
+ * Gets list of passed commands {@link CompileCommand}
+ *
+ * @return a list of compile commands
+ */
+ List<T> getCompileCommands();
+
+ /**
+ * Shows that this state builder created a valid input for the test vm
+ *
+ * @return true if this is a valid input
+ */
+ boolean isValid();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8138651
+ * @library /testlibrary /../../test/lib
+ * @build IntrinsicDisabledTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * -XX:DisableIntrinsic=_putCharVolatile,_putInt
+ * -XX:DisableIntrinsic=_putIntVolatile
+ * -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
+ * -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
+ * IntrinsicDisabledTest
+ */
+
+import java.lang.reflect.Executable;
+import java.util.Objects;
+
+import sun.hotspot.WhiteBox;
+
+import jdk.test.lib.Platform;
+
+public class IntrinsicDisabledTest {
+
+ private static final WhiteBox wb = WhiteBox.getWhiteBox();
+
+ /* Compilation level corresponding to C1. */
+ private static final int COMP_LEVEL_SIMPLE = 1;
+
+ /* Compilation level corresponding to C2. */
+ private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
+ /* Determine if tiered compilation is enabled. */
+ private static boolean isTieredCompilationEnabled() {
+ return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation")));
+ }
+
+ /* This test uses several methods from sun.misc.Unsafe. The method
+ * getMethod() returns a different Executable for each different
+ * combination of its input parameters. There are eight possible
+ * combinations, getMethod can return an Executable representing
+ * the following methods: putChar, putCharVolatile, getChar,
+ * getCharVolatile, putInt, putIntVolatile, getInt,
+ * getIntVolatile. These methods were selected because they can
+ * be intrinsified by both the C1 and the C2 compiler.
+ */
+ static Executable getMethod(boolean isChar, boolean isPut, boolean isVolatile) throws RuntimeException {
+ Executable aMethod;
+ String methodTypeName = isChar ? "Char" : "Int";
+
+ try {
+ Class aClass = Class.forName("sun.misc.Unsafe");
+ if (isPut) {
+ aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""),
+ Object.class,
+ long.class,
+ isChar ? char.class : int.class);
+ } else {
+ aMethod = aClass.getDeclaredMethod("get" + methodTypeName + (isVolatile ? "Volatile" : ""),
+ Object.class,
+ long.class);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, method is unavailable. " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, class is unavailable. " + e);
+ }
+
+ return aMethod;
+ }
+
+ public static void test(int compLevel) {
+
+ Executable putChar = getMethod(true, /*isPut =*/ true, /*isVolatile = */ false);
+ Executable getChar = getMethod(true, /*isPut =*/ false, /*isVolatile = */ false);
+ Executable putCharVolatile = getMethod(true, /*isPut =*/ true, /*isVolatile = */ true);
+ Executable getCharVolatile = getMethod(true, /*isPut =*/ false, /*isVolatile = */ true);
+ Executable putInt = getMethod(false, /*isPut =*/ true, /*isVolatile = */ false);
+ Executable getInt = getMethod(false, /*isPut =*/ false, /*isVolatile = */ false);
+ Executable putIntVolatile = getMethod(false, /*isPut =*/ true, /*isVolatile = */ true);
+ Executable getIntVolatile = getMethod(false, /*isPut =*/ false, /*isVolatile = */ true);
+
+ /* Test if globally disabling intrinsics works. */
+ if (!wb.isIntrinsicAvailable(putChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
+ "] is not available globally although it should be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putCharVolatile, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
+ "] is available globally although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putInt, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
+ "] is available globally although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putIntVolatile, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
+ "] is available globally although it should not be.");
+ }
+
+ /* Test if disabling intrinsics on a per-method level
+ * works. The method for which intrinsics are
+ * disabled (the compilation context) is putChar. */
+ if (!wb.isIntrinsicAvailable(getChar, putChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getChar.toGenericString() +
+ "] is not available for intrinsification in [" +
+ putChar.toGenericString() + "] although it should be.");
+ }
+
+ if (wb.isIntrinsicAvailable(getCharVolatile, putChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
+ "] is available for intrinsification in [" +
+ putChar.toGenericString() + "] although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(getInt, putChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
+ "] is available for intrinsification in [" +
+ putChar.toGenericString() + "] although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(getIntVolatile, putCharVolatile, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
+ "] is available for intrinsification in [" +
+ putCharVolatile.toGenericString() + "] although it should not be.");
+ }
+
+ /* Test if disabling intrinsics on a per-method level
+ * leaves those intrinsics enabled globally. */
+ if (!wb.isIntrinsicAvailable(getCharVolatile, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
+ "] is not available globally although it should be.");
+ }
+
+ if (!wb.isIntrinsicAvailable(getInt, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
+ "] is not available globally although it should be.");
+ }
+
+
+ if (!wb.isIntrinsicAvailable(getIntVolatile, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
+ "] is not available globally although it should be.");
+ }
+
+ /* Test if disabling an intrinsic globally disables it on a
+ * per-method level as well. */
+ if (!wb.isIntrinsicAvailable(putChar, getChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
+ "] is not available for intrinsification in [" +
+ getChar.toGenericString() + "] although it should be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putCharVolatile, getChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
+ "] is available for intrinsification in [" +
+ getChar.toGenericString() + "] although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putInt, getChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
+ "] is available for intrinsification in [" +
+ getChar.toGenericString() + "] although it should not be.");
+ }
+
+ if (wb.isIntrinsicAvailable(putIntVolatile, getChar, compLevel)) {
+ throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
+ "] is available for intrinsification in [" +
+ getChar.toGenericString() + "] although it should not be.");
+ }
+ }
+
+ public static void main(String args[]) {
+ if (Platform.isServer()) {
+ if (isTieredCompilationEnabled()) {
+ test(COMP_LEVEL_SIMPLE);
+ }
+ test(COMP_LEVEL_FULL_OPTIMIZATION);
+ } else {
+ test(COMP_LEVEL_SIMPLE);
+ }
+ }
+}
--- a/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -27,21 +27,36 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Random;
+import sun.hotspot.WhiteBox;
+
+import jdk.test.lib.Platform;
+
/**
* @test
- * @bug 8130150
+ * @bug 8130150 8131779 8139907
+ * @summary Verify that the Montgomery multiply and square intrinsic works and correctly checks their arguments.
+ * @library /testlibrary /../../test/lib
* @library /testlibrary
- * @summary Verify that the Montgomery multiply intrinsic works and correctly checks its arguments.
+ * @build MontgomeryMultiplyTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MontgomeryMultiplyTest
*/
public class MontgomeryMultiplyTest {
+ private static final WhiteBox wb = WhiteBox.getWhiteBox();
+
+ /* Compilation level corresponding to C2. */
+ private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
static final MethodHandles.Lookup lookup = MethodHandles.lookup();
static final MethodHandle montgomeryMultiplyHandle, montgomerySquareHandle;
@@ -76,6 +91,37 @@
}
}
+ /* Obtain executable for the intrinsics tested. Depending on the
+ * value of 'isMultiply', the executable corresponding to either
+ * implMontgomerMultiply or implMontgomerySqure is returned. */
+ static Executable getExecutable(boolean isMultiply) throws RuntimeException {
+ try {
+ Class aClass = Class.forName("java.math.BigInteger");
+ Method aMethod;
+ if (isMultiply) {
+ aMethod = aClass.getDeclaredMethod("implMontgomeryMultiply",
+ int[].class,
+ int[].class,
+ int[].class,
+ int.class,
+ long.class,
+ int[].class);
+ } else {
+ aMethod = aClass.getDeclaredMethod("implMontgomerySquare",
+ int[].class,
+ int[].class,
+ int.class,
+ long.class,
+ int[].class);
+ }
+ return aMethod;
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, method is unavailable. " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, class is unavailable. " + e);
+ }
+ }
+
// Invoke either BigInteger.montgomeryMultiply or BigInteger.montgomerySquare.
int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv,
int[] product) throws Throwable {
@@ -267,11 +313,15 @@
}
public static void main(String args[]) {
- try {
- new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
- new MontgomeryMultiplyTest().testResultValues();
- } catch (Throwable ex) {
- throw new RuntimeException(ex);
+ if (Platform.isServer() &&
+ wb.isIntrinsicAvailable(getExecutable(true), COMP_LEVEL_FULL_OPTIMIZATION) &&
+ wb.isIntrinsicAvailable(getExecutable(false), COMP_LEVEL_FULL_OPTIMIZATION)) {
+ try {
+ new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
+ new MontgomeryMultiplyTest().testResultValues();
+ } catch (Throwable ex) {
+ throw new RuntimeException(ex);
+ }
}
- }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CompilerDirectivesDCMDTest
+ * @bug 8137167
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @run main ClassFileInstaller jdk.test.lib.Platform
+ * @run testng/othervm CompilerDirectivesDCMDTest
+ * @summary Test of diagnostic command
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+import jdk.test.lib.Platform;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+
+public class CompilerDirectivesDCMDTest {
+
+ public static String filename;
+
+ public void run(CommandExecutor executor) {
+
+ if (Platform.isServer()) {
+ filename = System.getProperty("test.src", ".") + File.separator + "control2.txt";
+ } else {
+ filename = System.getProperty("test.src", ".") + File.separator + "control1.txt";
+ }
+ testPrintCommand(executor);
+ testAddAndRemoveCommand(executor);
+ }
+
+ public static void testPrintCommand(CommandExecutor executor) {
+
+ // Get output from dcmd (diagnostic command)
+ OutputAnalyzer output = executor.execute("Compiler.directives_print");
+ int count = find(output, "Directive:");
+ if (count < 1) {
+ Assert.fail("Expected at least one directive - found " + count);
+ }
+ }
+
+ public static void testAddAndRemoveCommand(CommandExecutor executor) {
+ OutputAnalyzer output;
+ int count = 0;
+
+ // Start with clearing stack - expect only default directive left
+ output = executor.execute("Compiler.directives_clear");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 1) {
+ Assert.fail("Expected one directives - found " + count);
+ }
+
+ // Test that we can not remove the default directive
+ output = executor.execute("Compiler.directives_remove");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 1) {
+ Assert.fail("Expected one directives - found " + count);
+ }
+
+ // Test adding some directives from file
+ output = executor.execute("Compiler.directives_add " + filename);
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 3) {
+ Assert.fail("Expected three directives - found " + count);
+ }
+
+ // Test remove one directive
+ output = executor.execute("Compiler.directives_remove");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 2) {
+ Assert.fail("Expected two directives - found " + count);
+ }
+
+ // Test adding directives again
+ output = executor.execute("Compiler.directives_add " + filename);
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 4) {
+ Assert.fail("Expected four directives - found " + count);
+ }
+
+ // Test clearing
+ output = executor.execute("Compiler.directives_clear");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 1) {
+ Assert.fail("Expected one directives - found " + count);
+ }
+
+ // Test clear when already cleared
+ output = executor.execute("Compiler.directives_clear");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 1) {
+ Assert.fail("Expected one directives - found " + count);
+ }
+
+ // Test remove one directive when empty
+ output = executor.execute("Compiler.directives_remove");
+ output = executor.execute("Compiler.directives_print");
+ count = find(output, "Directive:");
+ if (count != 1) {
+ Assert.fail("Expected one directive - found " + count);
+ }
+ }
+
+ public static int find(OutputAnalyzer output, String find) {
+ int count = 0;
+
+ for (String line : output.asLines()) {
+ if (line.startsWith(find)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ @Test
+ public void jmx() {
+ run(new JMXExecutor());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control1.txt Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,17 @@
+[
+ {
+ match: "foo/bar.*",
+ PrintAssembly: false,
+ c1: {
+ BreakAtExecute: false,
+ },
+ inline : [ "+javax/util.*", "-comx/sun.*"],
+ PrintAssembly: false,
+ },
+ {
+ match: ["baz.*","frob.*"],
+ inline : [ "+java/util.*", "-com/sun.*" ],
+ PrintAssembly: false,
+ BreakAtExecute: false,
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control2.txt Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,22 @@
+[
+ {
+ match: "foo/bar.*",
+ PrintAssembly: false,
+ c1: {
+ BreakAtExecute: false,
+ },
+ c2: {
+ inline : "+java/util.*",
+ BreakAtCompile: true
+ },
+ inline : [ "+javax/util.*", "-comx/sun.*"],
+ PrintAssembly: false,
+ IGVPrintLevel: 2
+ },
+ {
+ match: ["baz.*","frob.*"],
+ inline : [ "+java/util.*", "-com/sun.*" ],
+ PrintAssembly: false,
+ BreakAtExecute: false,
+ }
+]
--- a/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Wed Jul 05 20:59:18 2017 +0200
@@ -39,7 +39,7 @@
/**
* Pumps stdout and stderr from running the process into a String.
*
- * @param processHandler ProcessHandler to run.
+ * @param processBuilder ProcessBuilder to run.
* @return Output from process.
* @throws IOException If an I/O error occurs.
*/
@@ -109,6 +109,17 @@
}
/**
+ * Gets the array of strings containing input arguments passed to the VM
+ *
+ * @return arguments
+ */
+ public static String[] getVmInputArgs() {
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ List<String> args = runtime.getInputArguments();
+ return args.toArray(new String[args.size()]);
+ }
+
+ /**
* Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
*
* @return String[] with platform specific arguments, empty if there are none
@@ -172,6 +183,26 @@
return executeProcess(pb);
}
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from the test's run command, jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.fromRun.opts} {test.vm.opts} {test.java.opts} cmds
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvmAllArgs(String... cmds) throws Throwable {
+ List<String> argsList = new ArrayList<>();
+ String[] testArgs = getVmInputArgs();
+ Collections.addAll(argsList, testArgs);
+ Collections.addAll(argsList, Utils.addTestJavaOpts(cmds));
+ ProcessBuilder pb = createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+ return executeProcess(pb);
+ }
+
/**
* Executes a process, waits for it to finish and returns the process output.
* The process will have exited before this method returns.
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Nov 05 13:43:17 2015 -0800
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Wed Jul 05 20:59:18 2017 +0200
@@ -78,7 +78,7 @@
/**
* Returns the value of 'test.src' system property.
*/
- public static final String TEST_SRC = System.getProperty("test.src", "").trim();
+ public static final String TEST_SRC = System.getProperty("test.src", ".").trim();
private static Unsafe unsafe = null;
@@ -412,6 +412,23 @@
}
/**
+ * Returns random element of non empty array
+ *
+ * @param <T> a type of array element
+ * @param array array of elements
+ * @return random element of array
+ * @throws IllegalArgumentException if array is empty
+ */
+ public static <T> T getRandomElement(T[] array)
+ throws IllegalArgumentException {
+ if (array == null || array.length == 0) {
+ throw new IllegalArgumentException("Empty or null array");
+ }
+ Random random = getRandomInstance();
+ return array[random.nextInt(array.length)];
+ }
+
+ /**
* Wait for condition to be true
*
* @param condition, a condition to wait for
--- a/jaxp/.hgtags Thu Nov 05 13:43:17 2015 -0800
+++ b/jaxp/.hgtags Wed Jul 05 20:59:18 2017 +0200
@@ -333,3 +333,4 @@
4700fd67e942714046df1d0514f2ef4ddcac78bb jdk9-b88
5021da4c949690e5c2578c073c36fb161e4b35e5 jdk9-b89
35f68242b624112cb6ef7e6226059674d6b499f4 jdk9-b90
+ffaff3d0ad0e0ca1e632b80826afa8729ee72a48 jdk9-b91
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+/**
+ * Represents an alternative catalog entry.
+ *
+ * @since 9
+ */
+class AltCatalog extends BaseEntry {
+ URI catalogURI;
+
+ AltCatalog(CatalogEntryType type, String base) {
+ super(type, base);
+ }
+
+ /**
+ * Set the catalog attribute. If the value of the catalog attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ *
+ * @param catalog The catalog attribute value.
+ * @throws CatalogException if converting to catalog URI failed
+ */
+ void setCatalog(String catalog) {
+ URL url = verifyURI("catalog", baseURI, catalog);
+ try {
+ catalogURI = url.toURI();
+ } catch (URISyntaxException ex) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
+ }
+
+ }
+
+ /**
+ * Returns the catalog attribute as an URI String.
+ * @return The value of the catalog attribute
+ */
+ String getCatalogId() {
+ return catalogURI.toASCIIString();
+ }
+
+ /**
+ * Returns the catalog attribute as an URI.
+ * @return The value of the catalog attribute
+ */
+ URI getCatalogURI() {
+ return catalogURI;
+ }
+
+ /**
+ * Matches the specified id with the entry. Returns the match if it
+ * is successful and the length of the start String is longer than the
+ * longest of any previous match.
+ *
+ * @param id The id to be matched.
+ * @param currentMatch The length of start String of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ public URI matchURI(String id, int currentMatch) {
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Objects;
+import jdk.xml.internal.SecuritySupport;
+
+/**
+ * Represents a general Catalog entry.
+ *
+ * @since 9
+ */
+abstract class BaseEntry {
+ final String SLASH = "/";
+
+ CatalogEntryType type;
+
+ //The id attribute
+ String id;
+
+ //The attribute to be matched, e.g. systemId
+ String matchId;
+
+ //The baseURI attribute
+ URL baseURI;
+
+ //Indicates whether the base attribute is specified
+ boolean baseSpecified = false;
+
+ /**
+ * CatalogEntryType represents catalog entry types.
+ */
+ static enum CatalogEntryType {
+
+ CATALOG("catalogfile"),
+ CATALOGENTRY("catalog"),
+ GROUP("group"),
+ PUBLIC("public"),
+ SYSTEM("system"),
+ REWRITESYSTEM("rewriteSystem"),
+ SYSTEMSUFFIX("systemSuffix"),
+ DELEGATEPUBLIC("delegatePublic"),
+ DELEGATESYSTEM("delegateSystem"),
+ URI("uri"),
+ REWRITEURI("rewriteURI"),
+ URISUFFIX("uriSuffix"),
+ DELEGATEURI("delegateURI"),
+ NEXTCATALOG("nextCatalog");
+
+ final String literal;
+
+ CatalogEntryType(String literal) {
+ this.literal = literal;
+ }
+
+ public boolean isType(String type) {
+ return literal.equals(type);
+ }
+
+ static public CatalogEntryType getType(String entryType) {
+ for (CatalogEntryType type : CatalogEntryType.values()) {
+ if (type.isType(entryType)) {
+ return type;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Constructs a CatalogEntry
+ *
+ * @param type The type of the entry
+ */
+ public BaseEntry(CatalogEntryType type) {
+ this.type = Objects.requireNonNull(type);
+ }
+
+ /**
+ * Constructs a CatalogEntry
+ *
+ * @param type The type of the entry
+ * @param base The base URI
+ */
+ public BaseEntry(CatalogEntryType type, String base) {
+ this.type = Objects.requireNonNull(type);
+ setBaseURI(base);
+ }
+
+ /**
+ * Returns the type of the entry
+ *
+ * @return The type of the entry
+ */
+ public CatalogEntryType getType() {
+ return type;
+ }
+
+ /**
+ * Sets the entry type
+ *
+ * @param type The entry type
+ */
+ public void setType(CatalogEntryType type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the id of the entry
+ *
+ * @return The id of the entry
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Set the entry Id
+ *
+ * @param id The Id attribute
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the base URI for the entry
+ *
+ * @param base The base URI
+ */
+ public final void setBaseURI(String base) {
+ baseURI = verifyURI("base", null, base);
+ }
+
+ /**
+ * Gets the base URI for the entry
+ *
+ * @return The base URI as a string.
+ */
+ public URL getBaseURI() {
+ return baseURI;
+ }
+
+ /**
+ * Gets the attribute used for matching
+ *
+ * @return The value of the field
+ */
+ public String getMatchId() {
+ return matchId;
+ }
+
+ /**
+ * Sets the matchId field
+ * @param matchId The value of the Id
+ */
+ public void setMatchId(String matchId) {
+ this.matchId = matchId;
+ }
+
+ /**
+ * Matches the specified string with the identifier attribute of the entry.
+ *
+ * @param match The identifier attribute to be matched
+ * @return The replacement URI if a matching entry is found, null if not.
+ */
+ public String match(String match) {
+ return null;
+ }
+
+ /**
+ * Try to match the specified id with the entry. Return the match if it
+ * is successful and the length of the start String is longer than the
+ * longest of any previous match.
+ *
+ * @param id The id to be matched.
+ * @param currentMatch The length of start String of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ public String match(String id, int currentMatch) {
+ return null;
+ }
+
+ /**
+ * Verifies the specified URI.
+ *
+ * @param arg The name of the argument
+ * @param uri The URI to be verified
+ * @return The URI created from the specified uri
+ * @throws IllegalArgumentException if the specified uri is null,
+ * or an URL can not be created based on the specified base and uri
+ */
+ URL verifyURI(String arg, URL base, String uri) {
+ if (uri == null) {
+ CatalogMessages.reportIAE(new Object[]{uri, arg}, null);
+ }
+
+ URL url = null;
+ uri = Normalizer.normalizeURI(uri);
+
+ try {
+ if (base != null) {
+ url = new URL(base, uri);
+ } else {
+ url = new URL(uri);
+ }
+ } catch (MalformedURLException e) {
+ CatalogMessages.reportIAE(new Object[]{uri, arg}, e);
+ }
+ return url;
+ }
+
+ /**
+ * Replace backslashes with forward slashes. (URLs always use forward
+ * slashes.)
+ *
+ * @param sysid The input system identifier.
+ * @return The same system identifier with backslashes turned into forward
+ * slashes.
+ */
+ protected String fixSlashes(String sysid) {
+ return sysid.replace('\\', '/');
+ }
+
+ /**
+ * Construct an absolute URI from a relative one, using the current base
+ * URI.
+ *
+ * @param sysid The (possibly relative) system identifier
+ * @return The system identifier made absolute with respect to the current
+ * {@link #base}.
+ */
+ protected String makeAbsolute(String sysid) {
+ URL local = null;
+
+ sysid = fixSlashes(sysid);
+ /**
+ * try { local = new URL(base, sysid); } catch (MalformedURLException e)
+ * { catalogManager.debug.message(1, "Malformed URL on system
+ * identifier", sysid); }
+ */
+ if (local != null) {
+ return local.toString();
+ } else {
+ return sysid;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.util.stream.Stream;
+
+/**
+ * The Catalog class represents an entity Catalog as defined by
+ * <a
+ * href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
+ * XML Catalogs, OASIS Standard V1.1, 7 October 2005</a>.
+ * <p>
+ * A catalog is an XML file that contains a root {@code catalog} entry with a list
+ * of catalog entries. The entries can also be grouped with a {@code group} entry.
+ * The catalog and group entries may specify {@code prefer} and {@code xml:base}
+ * attributes that set preference of public or system type of entries and base URI
+ * to resolve relative URIs.
+ *
+ * <p>
+ * A catalog can be used in two situations:
+ * <ul>
+ * <li>Locate the replacement text for an external entity;
+ * </li>
+ * <li>Locate an alternate URI reference for a resource.
+ * </li>
+ * </ul>
+ * <p>
+ * For case 1, the standard defines 6 External Identifier Entries:<br>
+ * {@code public, system, rewriteSystem, systemSuffix, delegatePublic, and
+ * delegateSystem}.
+ * <p>
+ * While for case 2, it defines 4 URI Entries:<br>
+ * {@code uri, rewriteURI, uriSuffix and delegateURI}.
+ * <p>
+ * In addition to the above entry types, a catalog may define nextCatalog
+ * entries to add additional catalog entry files.
+ * <p>
+ *
+ * @since 9
+ */
+public interface Catalog {
+
+ /**
+ * Attempts to find a matching entry in the catalog by systemId.
+ *
+ * <p>
+ * The method searches through the system-type entries, including {@code system,
+ * rewriteSystem, systemSuffix, delegateSystem}, and {@code group} entries in the
+ * current catalog in order to find a match.
+ * <p>
+ * Resolution follows the steps listed below: <br>
+ * <ul>
+ * <li>If a matching {@code system} entry exists, it is returned immediately.</li>
+ * <li>If more than one {@code rewriteSystem} entry matches, the matching entry with
+ * the longest normalized {@code systemIdStartString} value is returned.</li>
+ * <li>If more than one {@code systemSuffix} entry matches, the matching entry
+ * with the longest normalized {@code systemIdSuffix} value is returned.</li>
+ * <li>If more than one {@code delegateSystem} entry matches, the matching entry
+ * with the longest matching {@code systemIdStartString} value is returned.</li>
+ * </ul>
+ *
+ * @param systemId the system identifier of the entity to be matched
+ *
+ * @return an URI string if a mapping is found, or null otherwise
+ */
+ public String matchSystem(String systemId);
+
+ /**
+ * Attempts to find a matching entry in the catalog by publicId. The method
+ * searches through the public-type entries, including {@code public,
+ * delegatePublic}, and {@code group} entries in the current catalog in order to find
+ * a match.
+ * <p>
+ * Refer to the description about <a href="CatalogFeatures.html#PREFER">
+ * Feature PREFER in the table Catalog Features</a> in class
+ * {@link CatalogFeatures}. Public entries are only considered if the
+ * {@code prefer} is {@code public} and {@code system} entries are not found.
+ * <p>
+ * Resolution follows the steps listed below: <br>
+ * <ul>
+ * <li>If a matching {@code public} entry is found, it is returned immediately.</li>
+ * <li>If more than one {@code delegatePublic} entry matches, the matching entry
+ * with the longest matching {@code publicIdStartString} value is returned.</li>
+ * </ul>
+ *
+ * @param publicId the public identifier of the entity to be matched
+ * @see CatalogFeatures.Feature
+ * @return an URI string if a mapping is found, or null otherwise
+ */
+ public String matchPublic(String publicId);
+
+ /**
+ * Attempts to find a matching entry in the catalog by the uri element.
+ *
+ * <p>
+ * The method searches through the uri-type entries, including {@code uri,
+ * rewriteURI, uriSuffix, delegateURI} and {@code group} entries in the current
+ * catalog in order to find a match.
+ *
+ * <p>
+ * Resolution follows the steps listed below: <br>
+ * <ul>
+ * <li>If a matching {@code uri} entry is found, it is returned immediately.</li>
+ * <li>If more than one {@code rewriteURI} entry matches, the matching entry with
+ * the longest normalized {@code uriStartString} value is returned.</li>
+ * <li>If more than one {@code uriSuffix} entry matches, the matching entry with
+ * the longest normalized {@code uriSuffix} value is returned.</li>
+ * <li>If more than one {@code delegatePublic} entry matches, the matching entry
+ * with the longest matching {@code uriStartString} value is returned.</li>
+ * </ul>
+ *
+ * @param uri the URI reference of the entity to be matched
+ *
+ * @return an URI string if a mapping is found, or null otherwise
+ */
+ public String matchURI(String uri);
+
+ /**
+ * Returns a sequential Stream of alternative Catalogs specified using the
+ * {@code nextCatalog} entries in the current catalog, and as the input of
+ * catalog files excluding the current catalog (that is, the first in the
+ * input list) when the Catalog object is created by the {@link CatalogManager}.
+ * <p>
+ * The order of Catalogs in the returned stream is the same as the order
+ * in which the corresponding {@code nextCatalog} entries appear in the
+ * current catalog. The alternative catalogs from the input file list are
+ * appended to the end of the stream in the order they are entered.
+ *
+ * @return a sequential Stream of Catalogs
+ */
+ public Stream<Catalog> catalogs();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+/**
+ * Represents the catalog element or entry of a catalog file
+ *
+ * @since 9
+ */
+class CatalogEntry extends GroupEntry {
+
+ /**
+ * Construct a catalog entry.
+ *
+ * @param base The baseURI attribute
+ * @param attributes The attributes
+ */
+ public CatalogEntry(String base, String... attributes) {
+ super(base, attributes);
+ setType(CatalogEntryType.CATALOGENTRY);
+ }
+
+ @Override
+ public String match(String match) {
+ throw new UnsupportedOperationException("Unsupported operation.");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogException.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+/**
+ * The exception class handles errors that may happen while processing or using
+ * a catalog.
+ *
+ * @since 9
+ */
+public class CatalogException extends RuntimeException {
+
+ private static final long serialVersionUID = 653231525876459057L;
+
+ /**
+ * Constructs a new CatalogException with the specified detail message. The
+ * cause is not initialized, and may subsequently be initialized by a call
+ * to {@link #initCause}.
+ *
+ * @param message the detail message
+ */
+ public CatalogException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new CatalogException with the specified detail message and
+ * cause.
+ *
+ * @param message the detail message (which is saved for later retrieval by
+ * the {@link #getMessage()} method)
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted, and
+ * indicates that the cause is nonexistent or unknown.)
+ */
+ public CatalogException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import jdk.xml.internal.SecuritySupport;
+
+/**
+ * The CatalogFeatures holds a collection of features and properties.
+ * <p>
+ *
+ * <center><h2><a name="CatalogFeatures">Catalog Features</a></h2></center></p>
+ *
+ * <table border="1">
+ * <thead>
+ * <tr>
+ * <th rowspan="2">Feature</th>
+ * <th rowspan="2">Description</th>
+ * <th rowspan="2">Property Name</th>
+ * <th rowspan="2">System Property [1]</th>
+ * <th rowspan="2">jaxp.properties [1]</th>
+ * <th colspan="2" align="center">Value [2]</th>
+ * <th rowspan="2">Action</th>
+ * </tr>
+ * <tr>
+ * <th>Type</th>
+ * <th>Value</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ *
+ * <tr>
+ * <td><a name="FILES">FILES</a></td>
+ * <td>A semicolon-delimited list of catalog files. Relative file paths are
+ * considered relative to ${user.dir}.
+ * </td>
+ * <td>javax.xml.catalog.files</td>
+ * <td>javax.xml.catalog.files</td>
+ * <td>javax.xml.catalog.files</td>
+ * <td>String</td>
+ * <td>File paths</td>
+ * <td>
+ * Reads the first catalog as the current catalog; Loads others if no match
+ * is found in the current catalog including delegate catalogs if any.
+ * </td>
+ * </tr>
+ *
+ * <tr>
+ * <td rowspan="2"><a name="PREFER">PREFER</a></td>
+ * <td rowspan="2">Indicates the preference between the public and system
+ * identifiers. The default value is public [3].</td>
+ * <td rowspan="2">javax.xml.catalog.prefer</td>
+ * <td rowspan="2">N/A</td>
+ * <td rowspan="2">N/A</td>
+ * <td rowspan="2">String</td>
+ * <td>{@code system}</td>
+ * <td>Searches system entries for a match; Searches public entries when
+ * external identifier specifies only a public identifier</td>
+ * </tr>
+ * <tr>
+ * <td>{@code public}</td>
+ * <td>Searches system entries for a match; Searches public entries when
+ * there is no matching system entry.</td>
+ * </tr>
+ *
+ * <tr>
+ * <td rowspan="2"><a name="DEFER">DEFER</a></td>
+ * <td rowspan="2">Indicates that the alternative catalogs including those
+ * specified in delegate entries or nextCatalog are not read until they are
+ * needed. The default value is true.</td>
+ * <td rowspan="2">javax.xml.catalog.defer [4]</td>
+ * <td rowspan="2">javax.xml.catalog.defer</td>
+ * <td rowspan="2">javax.xml.catalog.defer</td>
+ * <td rowspan="2">String</td>
+ * <td>{@code true}</td>
+ * <td>Loads alternative catalogs as needed.
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>{@code false}</td>
+ * <td>Loads all catalogs[5]. </td>
+ * </tr>
+ *
+ * <tr>
+ * <td rowspan="3"><a name="RESOLVE">RESOLVE</a></td>
+ * <td rowspan="3">Determines the action if there is no matching entry found after
+ * all of the specified catalogs are exhausted. The default is strict.</td>
+ * <td rowspan="3">javax.xml.catalog.resolve [4]</td>
+ * <td rowspan="3">javax.xml.catalog.resolve</td>
+ * <td rowspan="3">javax.xml.catalog.resolve</td>
+ * <td rowspan="3">String</td>
+ * <td>{@code strict}</td>
+ * <td>Throws CatalogException if there is no match.
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>{@code continue}</td>
+ * <td>Allows the XML parser to continue as if there is no match.
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>{@code ignore}</td>
+ * <td>Tells the XML parser to skip the external references if there no match.
+ * </td>
+ * </tr>
+ *
+ * </tbody>
+ * </table>
+ * <p>
+ * <b>[1]</b> There is no System property for the features that marked as "N/A".
+ *
+ * <p>
+ * <b>[2]</b> The value shall be exactly as listed in this table, case-sensitive.
+ * Any unspecified value will result in {@link IllegalArgumentException}.
+ * <p>
+ * <b>[3]</b> The Catalog specification defined complex rules on
+ * <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#attrib.prefer">
+ * the prefer attribute</a>. Although the prefer can be public or system, the
+ * specification actually made system the preferred option, that is, no matter
+ * the option, a system entry is always used if found. Public entries are only
+ * considered if the prefer is public and system entries are not found. It is
+ * therefore recommended that the prefer attribute be set as public
+ * (which is the default).
+ * <p>
+ * <b>[4]</b> Although non-standard attributes in the OASIS Catalog specification,
+ * {@code defer} and {@code resolve} are recognized by the Java Catalog API the
+ * same as the {@code prefer} as being an attribute in the catalog entry of the
+ * main catalog. Note that only the attributes specified for the catalog entry
+ * of the main Catalog file will be used.
+ * <p>
+ * <b>[5]</b> If the intention is to share an entire catalog store, it may be desirable to
+ * set the property {@code javax.xml.catalog.defer} to false to allow the entire
+ * catalog to be pre-loaded.
+ * <p>
+ * <h3>Scope and Order</h3>
+ * Features and properties can be set through the catalog file, the Catalog API,
+ * system properties, and {@code jaxp.properties}, with a preference in the same order.
+ * <p>
+ * Properties that are specified as attributes in the catalog file for the
+ * catalog and group entries shall take preference over any of the other settings.
+ * For example, if a {@code prefer} attribute is set in the catalog file as in
+ * {@code <catalog prefer="public">}, any other input for the "prefer" property
+ * is not necessary or will be ignored.
+ * <p>
+ * Properties set through the Catalog API override those that may have been set
+ * by system properties and/or in {@code jaxp.properties}. In case of multiple
+ * interfaces, the latest in a procedure shall take preference. For
+ * {@link Feature#FILES}, this means that the path(s) specified through the methods
+ * of the {@link CatalogManager} will override any that may have been entered
+ * through the {@link Builder}.
+ *
+ * <p>
+ * System properties when set shall override those in {@code jaxp.properties}.
+ * <p>
+ * The {@code jaxp.properties} file is typically in the conf directory of the Java
+ * installation. The file is read only once by the JAXP implementation and
+ * its values are then cached for future use. If the file does not exist
+ * when the first attempt is made to read from it, no further attempts are
+ * made to check for its existence. It is not possible to change the value
+ * of any properties in {@code jaxp.properties} after it has been read.
+ * <p>
+ * A CatalogFeatures instance can be created through its builder as illustrated
+ * in the following sample code:
+ * <pre>{@code
+ CatalogFeatures f = CatalogFeatures.builder()
+ .with(Feature.FILES, "catalog.xml")
+ .with(Feature.PREFER, "public")
+ .with(Feature.DEFER, "true")
+ .with(Feature.RESOLVE, "ignore")
+ .build();
+ * }</pre>
+ *
+ * @since 9
+ */
+public class CatalogFeatures {
+
+ /**
+ * The constant name of the javax.xml.catalog.files property. See the property table for more details.
+ */
+ static final String CATALOG_FILES = "javax.xml.catalog.files";
+
+ /**
+ * The javax.xml.catalog.prefer property. See the property table for more details.
+ */
+ static final String CATALOG_PREFER = "javax.xml.catalog.prefer";
+
+ /**
+ * Determines whether or not delegated catalogs and nextCatalog will be read
+ * when the current catalog is loaded.
+ */
+ static final String CATALOG_DEFER = "javax.xml.catalog.defer";
+
+ /**
+ * Determines the action if there is no matching entry found after
+ * all of the specified catalogs are exhausted.
+ */
+ static final String CATALOG_RESOLVE = "javax.xml.catalog.resolve";
+
+ //values for the prefer property
+ static final String PREFER_SYSTEM = "system";
+ static final String PREFER_PUBLIC = "public";
+
+ //values for the defer property
+ static final String DEFER_TRUE = "true";
+ static final String DEFER_FALSE = "false";
+
+ //values for the Resolve property
+ static final String RESOLVE_STRICT = "strict";
+ static final String RESOLVE_CONTINUE = "continue";
+ static final String RESOLVE_IGNORE = "ignore";
+
+ /**
+ * A Feature type as defined in the
+ * <a href="CatalogFeatures.html#CatalogFeatures">Catalog Features table</a>.
+ */
+ public static enum Feature {
+ /**
+ * The {@code javax.xml.catalog.files} property as described in
+ * item <a href="CatalogFeatures.html#FILES">FILES</a> of the
+ * Catalog Features table.
+ */
+ FILES(CATALOG_FILES, null, true),
+ /**
+ * The {@code javax.xml.catalog.prefer} property as described in
+ * item <a href="CatalogFeatures.html#PREFER">PREFER</a> of the
+ * Catalog Features table.
+ */
+ PREFER(CATALOG_PREFER, PREFER_PUBLIC, false),
+ /**
+ * The {@code javax.xml.catalog.defer} property as described in
+ * item <a href="CatalogFeatures.html#DEFER">DEFER</a> of the
+ * Catalog Features table.
+ */
+ DEFER(CATALOG_DEFER, DEFER_TRUE, true),
+ /**
+ * The {@code javax.xml.catalog.resolve} property as described in
+ * item <a href="CatalogFeatures.html#RESOLVE">RESOLVE</a> of the
+ * Catalog Features table.
+ */
+ RESOLVE(CATALOG_RESOLVE, RESOLVE_STRICT, true);
+
+ private final String name;
+ private final String defaultValue;
+ private String value;
+ private final boolean hasSystem;
+
+ /**
+ * Constructs a CatalogFeature instance.
+ * @param name the name of the feature
+ * @param value the value of the feature
+ * @param hasSystem a flag to indicate whether the feature is supported
+ * with a System property
+ */
+ Feature(String name, String value, boolean hasSystem) {
+ this.name = name;
+ this.defaultValue = value;
+ this.hasSystem = hasSystem;
+ }
+
+ /**
+ * Checks whether the specified property is equal to the current property.
+ * @param propertyName the name of a property
+ * @return true if the specified property is the current property, false
+ * otherwise
+ */
+ boolean equalsPropertyName(String propertyName) {
+ return name.equals(propertyName);
+ }
+
+ /**
+ * Returns the name of the corresponding System Property.
+ *
+ * @return the name of the System Property
+ */
+ public String getPropertyName() {
+ return name;
+ }
+
+ /**
+ * Returns the default value of the property.
+ * @return the default value of the property
+ */
+ String defaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Returns the value of the property.
+ * @return the value of the property
+ */
+ String getValue() {
+ return value;
+ }
+
+ /**
+ * Checks whether System property is supported for the feature.
+ * @return true it is supported, false otherwise
+ */
+ boolean hasSystemProperty() {
+ return hasSystem;
+ }
+ }
+
+ /**
+ * States of the settings of a property, in the order: default value,
+ * jaxp.properties file, jaxp system properties, and jaxp api properties
+ */
+ static enum State {
+ /** represents the default state of a feature. */
+ DEFAULT("default"),
+ /** indicates the value of the feature is read from jaxp.properties. */
+ JAXPDOTPROPERTIES("jaxp.properties"),
+ /** indicates the value of the feature is read from its System property. */
+ SYSTEMPROPERTY("system property"),
+ /** indicates the value of the feature is specified through the API. */
+ APIPROPERTY("property"),
+ /** indicates the value of the feature is specified as a catalog attribute. */
+ CATALOGATTRIBUTE("catalog attribute");
+
+ final String literal;
+
+ State(String literal) {
+ this.literal = literal;
+ }
+
+ String literal() {
+ return literal;
+ }
+ }
+
+ /**
+ * Values of the properties
+ */
+ private String[] values;
+
+ /**
+ * States of the settings for each property
+ */
+ private State[] states;
+
+ /**
+ * Private class constructor
+ */
+ private CatalogFeatures() {
+ }
+
+ /**
+ * Returns a CatalogFeatures instance with default settings.
+ * @return a default CatalogFeatures instance
+ */
+ public static CatalogFeatures defaults() {
+ return CatalogFeatures.builder().build();
+ }
+
+ /**
+ * Constructs a new CatalogFeatures instance with the builder.
+ *
+ * @param builder the builder to build the CatalogFeatures
+ */
+ CatalogFeatures(Builder builder) {
+ init();
+ setProperty(Feature.FILES.ordinal(), State.APIPROPERTY, builder.files);
+ setProperty(Feature.PREFER.ordinal(), State.APIPROPERTY, builder.prefer);
+ setProperty(Feature.DEFER.ordinal(), State.APIPROPERTY, builder.defer);
+ setProperty(Feature.RESOLVE.ordinal(), State.APIPROPERTY, builder.resolve);
+ }
+
+ /**
+ * Returns the value of the specified feature.
+ *
+ * @param cf the type of the Catalog feature
+ * @return the value of the feature
+ */
+ public String get(Feature cf) {
+ return values[cf.ordinal()];
+ }
+
+ /**
+ * Initializes the supported properties
+ */
+ private void init() {
+ values = new String[Feature.values().length];
+ states = new State[Feature.values().length];
+ for (Feature cf : Feature.values()) {
+ setProperty(cf.ordinal(), State.DEFAULT, cf.defaultValue());
+ }
+ //read system properties or jaxp.properties
+ readSystemProperties();
+ }
+
+ /**
+ * Sets the value of a property by its index, updates only if it shall override.
+ *
+ * @param index the index of the property
+ * @param state the state of the property
+ * @param value the value of the property
+ * @throws IllegalArgumentException if the value is invalid
+ */
+ private void setProperty(int index, State state, String value) {
+ if (value != null && value.length() != 0) {
+ if (index == Feature.PREFER.ordinal()) {
+ if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
+ CatalogMessages.reportIAE(new Object[]{value, Feature.PREFER.name()}, null);
+ }
+ } else if (index == Feature.DEFER.ordinal()) {
+ if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
+ CatalogMessages.reportIAE(new Object[]{value, Feature.DEFER.name()}, null);
+ }
+ } else if (index == Feature.RESOLVE.ordinal()) {
+ if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
+ && !value.equals(RESOLVE_IGNORE)) {
+ CatalogMessages.reportIAE(new Object[]{value, Feature.RESOLVE.name()}, null);
+ }
+ }
+ if (states[index] == null || state.compareTo(states[index]) >= 0) {
+ values[index] = value;
+ states[index] = state;
+ }
+ }
+ }
+
+ /**
+ * Reads from system properties, or those in jaxp.properties
+ */
+ private void readSystemProperties() {
+ for (Feature cf : Feature.values()) {
+ getSystemProperty(cf, cf.getPropertyName());
+ }
+ }
+
+ /**
+ * Reads from system properties, or those in jaxp.properties
+ *
+ * @param cf the type of the property
+ * @param sysPropertyName the name of system property
+ */
+ private boolean getSystemProperty(Feature cf, String sysPropertyName) {
+ if (cf.hasSystemProperty()) {
+ String value = SecuritySupport.getSystemProperty(sysPropertyName);
+ if (value != null && !value.equals("")) {
+ setProperty(cf.ordinal(), State.SYSTEMPROPERTY, value);
+ return true;
+ }
+
+ value = SecuritySupport.readJAXPProperty(sysPropertyName);
+ if (value != null && !value.equals("")) {
+ setProperty(cf.ordinal(), State.JAXPDOTPROPERTIES, value);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an instance of the builder for creating the CatalogFeatures object.
+ *
+ * @return an instance of the builder
+ */
+ public static Builder builder() {
+ return new CatalogFeatures.Builder();
+ }
+
+ /**
+ * The Builder class for building the CatalogFeatures object.
+ */
+ public static class Builder {
+ /**
+ * Variables for the features supported by CatalogFeatures.
+ */
+ String files, prefer, defer, resolve;
+
+ /**
+ * Instantiation of Builder is not allowed.
+ */
+ private Builder() {}
+
+ /**
+ * Sets the value to a specified Feature.
+ * @param feature the Feature to be set
+ * @param value the value to be set for the Feature
+ * @return this Builder instance
+ * @throws IllegalArgumentException if the value is not valid for the
+ * Feature or has the wrong syntax for the {@code javax.xml.catalog.files}
+ * property
+ */
+ public Builder with(Feature feature, String value) {
+ switch (feature) {
+ case FILES :
+ files = value;
+ break;
+ case PREFER :
+ prefer = value;
+ break;
+ case DEFER :
+ defer = value;
+ break;
+ case RESOLVE :
+ resolve = value;
+ break;
+ }
+ return this;
+ }
+
+ /**
+ * Returns a CatalogFeatures object built by this builder.
+ *
+ * @return an instance of CatalogFeatures
+ */
+ public CatalogFeatures build() {
+ return new CatalogFeatures(this);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import static javax.xml.catalog.BaseEntry.CatalogEntryType;
+import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * Implementation of the Catalog.
+ *
+ * @since 9
+ */
+class CatalogImpl extends GroupEntry implements Catalog {
+
+ //Catalog level, 0 means the top catalog
+ int level = 0;
+
+ //Value of the defer attribute to determine if alternative catalogs are read
+ boolean isDeferred = true;
+
+ //Value of the resolve attribute
+ ResolveType resolveType = ResolveType.STRICT;
+
+ //indicate whether the Catalog is empty
+ boolean isEmpty;
+
+ //Current parsed Catalog
+ int current = 0;
+
+ //System Id for this catalog
+ String systemId;
+
+ //The parent
+ CatalogImpl parent = null;
+
+ /*
+ A list of catalog entry files from the input, excluding the current catalog.
+ Paths in the List are normalized.
+ */
+ List<String> inputFiles;
+
+ //A list of catalogs specified using the nextCatalog element
+ List<NextCatalog> nextCatalogs;
+
+ //reuse the parser
+ SAXParser parser;
+
+ /**
+ * Construct a Catalog with specified path.
+ *
+ * @param file The path to a catalog file.
+ * @throws CatalogException If an error happens while parsing the specified
+ * catalog file.
+ */
+ public CatalogImpl(CatalogFeatures f, String... file) throws CatalogException {
+ this(null, f, file);
+ }
+
+ /**
+ * Construct a Catalog with specified path.
+ *
+ * @param parent The parent catalog
+ * @param file The path to a catalog file.
+ * @throws CatalogException If an error happens while parsing the specified
+ * catalog file.
+ */
+ public CatalogImpl(CatalogImpl parent, CatalogFeatures f, String... file) throws CatalogException {
+ super(CatalogEntryType.CATALOG);
+ this.parent = parent;
+ if (parent == null) {
+ level = 0;
+ } else {
+ level = parent.level + 1;
+ }
+ if (f == null) {
+ this.features = CatalogFeatures.defaults();
+ } else {
+ this.features = f;
+ }
+ setPrefer(features.get(Feature.PREFER));
+ setDeferred(features.get(Feature.DEFER));
+ setResolve(features.get(Feature.RESOLVE));
+
+ //Path of catalog files
+ String[] catalogFile = file;
+ if (level == 0
+ && (file == null || (file.length == 0 || file[0] == null))) {
+ String files = features.get(Feature.FILES);
+ if (files != null) {
+ catalogFile = files.split(";[ ]*");
+ }
+ }
+
+ /*
+ In accordance with 8. Resource Failures of the Catalog spec, missing
+ Catalog entry files are to be ignored.
+ */
+ if ((catalogFile != null && catalogFile.length > 0)) {
+ int start = 0;
+ URI uri = null;
+ for (String temp : catalogFile) {
+ uri = getSystemId(temp);
+ start++;
+ if (verifyCatalogFile(uri)) {
+ systemId = uri.toASCIIString();
+ break;
+ }
+ }
+
+ //Save the rest of input files as alternative catalogs
+ if (level == 0 && catalogFile.length > start) {
+ inputFiles = new ArrayList<>();
+ for (int i = start; i < catalogFile.length; i++) {
+ if (catalogFile[i] != null) {
+ inputFiles.add(catalogFile[i]);
+ }
+ }
+ }
+
+ if (systemId != null) {
+ parse(systemId);
+ }
+ }
+ }
+
+ /**
+ * Resets the Catalog instance to its initial state.
+ */
+ @Override
+ public void reset() {
+ super.reset();
+ current = 0;
+ if (level == 0) {
+ catalogsSearched.clear();
+ }
+ entries.stream().filter((entry) -> (entry.type == CatalogEntryType.GROUP)).forEach((entry) -> {
+ ((GroupEntry) entry).reset();
+ });
+
+ if (parent != null) {
+ this.loadedCatalogs = parent.loadedCatalogs;
+ this.catalogsSearched = parent.catalogsSearched;
+ }
+ }
+
+ /**
+ * Returns whether this Catalog instance is the top (main) Catalog.
+ *
+ * @return true if the instance is the top Catalog, false otherwise
+ */
+ boolean isTop() {
+ return level == 0;
+ }
+
+ /**
+ * Gets the parent of this catalog.
+ *
+ * @returns The parent catalog
+ */
+ public Catalog getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Sets the defer property. If the value is null or empty, or any String
+ * other than the defined, it will be assumed as the default value.
+ *
+ * @param value The value of the defer attribute
+ */
+ public final void setDeferred(String value) {
+ isDeferred = DEFER_TRUE.equals(value);
+ }
+
+ /**
+ * Queries the defer attribute
+ *
+ * @return true if the prefer attribute is set to system, false if not.
+ */
+ public boolean isDeferred() {
+ return isDeferred;
+ }
+
+ /**
+ * Sets the resolve property. If the value is null or empty, or any String
+ * other than the defined, it will be assumed as the default value.
+ *
+ * @param value The value of the resolve attribute
+ */
+ public final void setResolve(String value) {
+ resolveType = ResolveType.getType(value);
+ }
+
+ /**
+ * Gets the value of the resolve attribute
+ *
+ * @return The value of the resolve attribute
+ */
+ public final ResolveType getResolve() {
+ return resolveType;
+ }
+
+ /**
+ * Marks the Catalog as being searched already.
+ */
+ void markAsSearched() {
+ catalogsSearched.add(systemId);
+ }
+
+ /**
+ * Parses the catalog.
+ *
+ * @param systemId The systemId of the catalog
+ * @throws CatalogException if parsing the catalog failed
+ */
+ private void parse(String systemId) {
+ if (parser == null) {
+ parser = getParser();
+ }
+
+ try {
+ CatalogReader reader = new CatalogReader(this, parser);
+ parser.parse(systemId, reader);
+ } catch (SAXException | IOException ex) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, ex);
+ }
+ }
+
+ /**
+ * Resolves the specified file path to an absolute systemId. If it is
+ * relative, it shall be resolved using the base or user.dir property if
+ * base is not specified.
+ *
+ * @param file The specified file path
+ * @return The systemId of the file
+ * @throws CatalogException if the specified file path can not be converted
+ * to a system id
+ */
+ private URI getSystemId(String file) {
+ URL filepath;
+ if (file != null && file.length() > 0) {
+ try {
+ File f = new File(file);
+ if (baseURI != null && !f.isAbsolute()) {
+ filepath = new URL(baseURI, fixSlashes(file));
+ return filepath.toURI();
+ } else {
+ return resolveURI(file);
+ }
+ } catch (MalformedURLException | URISyntaxException e) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_INVALID_PATH,
+ new Object[]{file}, e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Resolves the specified uri. If the uri is relative, makes it absolute by
+ * the user.dir directory.
+ *
+ * @param uri The specified URI.
+ * @return The resolved URI
+ */
+ private URI resolveURI(String uri) throws MalformedURLException {
+ if (uri == null) {
+ uri = "";
+ }
+
+ URI temp = toURI(uri);
+ String str = temp.toASCIIString();
+ String base = str.substring(0, str.lastIndexOf('/') + 1);
+ baseURI = new URL(str);
+
+ return temp;
+ }
+
+ /**
+ * Converts an URI string or file path to URI.
+ *
+ * @param uri an URI string or file path
+ * @return an URI
+ */
+ private URI toURI(String uri) {
+ URI temp = null;
+ try {
+ URL url = new URL(uri);
+ temp = url.toURI();
+ } catch (MalformedURLException | URISyntaxException mue) {
+ File file = new File(uri);
+ temp = file.toURI();
+ }
+ return temp;
+ }
+
+ /**
+ * Returns a SAXParser instance
+ * @return a SAXParser instance
+ * @throws CatalogException if constructing a SAXParser failed
+ */
+ private SAXParser getParser() {
+ SAXParser p = null;
+ try {
+ SAXParserFactory spf = new SAXParserFactoryImpl();
+ spf.setNamespaceAware(true);
+ spf.setValidating(false);
+ spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ p = spf.newSAXParser();
+ } catch (ParserConfigurationException | SAXException e) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, e);
+ }
+ return p;
+ }
+
+ /**
+ * Indicate that the catalog is empty
+ *
+ * @return True if the catalog is empty; False otherwise.
+ */
+ public boolean isEmpty() {
+ return isEmpty;
+ }
+
+ @Override
+ public Stream<Catalog> catalogs() {
+ Iterator<Catalog> iter = new Iterator<Catalog>() {
+ Catalog nextCatalog = null;
+
+ //Current index of the input files
+ int inputFilesIndex = 0;
+
+ //Next catalog
+ int nextCatalogIndex = 0;
+
+ @Override
+ public boolean hasNext() {
+ if (nextCatalog != null) {
+ return true;
+ } else {
+ nextCatalog = nextCatalog();
+ return (nextCatalog != null);
+ }
+ }
+
+ @Override
+ public Catalog next() {
+ if (nextCatalog != null || hasNext()) {
+ Catalog catalog = nextCatalog;
+ nextCatalog = null;
+ return catalog;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ /**
+ * Returns the next alternative catalog.
+ *
+ * @return the next catalog if any
+ */
+ private Catalog nextCatalog() {
+ Catalog c = null;
+
+ //Check those specified in nextCatalogs
+ if (nextCatalogs != null) {
+ while (c == null && nextCatalogIndex < nextCatalogs.size()) {
+ c = getCatalog(nextCatalogs.get(nextCatalogIndex++).getCatalogURI());
+ }
+ }
+
+ //Check the input list
+ if (c == null && inputFiles != null) {
+ while (c == null && inputFilesIndex < inputFiles.size()) {
+ c = getCatalog(getSystemId(inputFiles.get(inputFilesIndex++)));
+ }
+ }
+
+ return c;
+ }
+ };
+
+ return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
+ iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
+ }
+
+ /**
+ * Adds the catalog to the nextCatalog list
+ *
+ * @param catalog a catalog specified in a nextCatalog entry
+ */
+ void addNextCatalog(NextCatalog catalog) {
+ if (catalog == null) {
+ return;
+ }
+
+ if (nextCatalogs == null) {
+ nextCatalogs = new ArrayList<>();
+ }
+
+ nextCatalogs.add(catalog);
+ }
+
+ /**
+ * Loads all alternative catalogs.
+ */
+ void loadNextCatalogs() {
+ //loads catalogs specified in nextCatalogs
+ if (nextCatalogs != null) {
+ for (NextCatalog next : nextCatalogs) {
+ getCatalog(next.getCatalogURI());
+ }
+ }
+
+ //loads catalogs from the input list
+ if (inputFiles != null) {
+ for (String file : inputFiles) {
+ getCatalog(getSystemId(file));
+ }
+ }
+ }
+
+ /**
+ * Returns a Catalog object by the specified path.
+ *
+ * @param path the path to a catalog
+ * @return a Catalog object
+ */
+ Catalog getCatalog(URI uri) {
+ if (uri == null) {
+ return null;
+ }
+
+ Catalog c = null;
+ String path = uri.toASCIIString();
+
+ if (verifyCatalogFile(uri)) {
+ c = getLoadedCatalog(path);
+ if (c == null) {
+ c = new CatalogImpl(this, features, path);
+ saveLoadedCatalog(path, c);
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Saves a loaded Catalog.
+ *
+ * @param catalogId the catalogId associated with the Catalog object
+ * @param c the Catalog to be saved
+ */
+ void saveLoadedCatalog(String catalogId, Catalog c) {
+ loadedCatalogs.put(catalogId, c);
+ }
+
+ /**
+ * Returns a count of all loaded catalogs, including delegate catalogs.
+ *
+ * @return a count of all loaded catalogs
+ */
+ int loadedCatalogCount() {
+ return loadedCatalogs.size() + delegateCatalogs.size();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+
+/**
+ * The Catalog Manager manages the creation of XML Catalogs and Catalog Resolvers.
+ *
+ * @since 9
+ */
+public final class CatalogManager {
+ /**
+ * Creating CatalogManager instance is not allowed.
+ */
+ private CatalogManager() {
+ }
+
+ /**
+ * Creates a Catalog object using the specified feature settings and path to
+ * a catalog file. If the features is null, the default features will be used.
+ * If the path is empty, System property {@code javax.xml.catalog.files} will
+ * be read to locate the initial list of catalog files.
+ * <p>
+ * If more than one catalog files are specified through the path argument or
+ * {@code javax.xml.catalog.files} property, the first entry is considered
+ * the main catalog, while others are treated as alternative catalogs after
+ * those referenced by the {@code nextCatalog} elements in the main catalog.
+ *
+ * @param features the catalog features
+ * @param path path(s) to one or more catalogs.
+ *
+ * @return a catalog instance
+ * @throws CatalogException If no catalog can be found whether through the
+ * specified path or the System property {@code javax.xml.catalog.files}, or
+ * an error occurs while parsing the catalog
+ */
+ public static Catalog catalog(CatalogFeatures features, String... path) {
+ return new CatalogImpl(features, path);
+ }
+
+ /**
+ * Creates an instance of a CatalogResolver using the specified catalog.
+ *
+ * @param catalog the catalog instance
+ * @return an instance of a CatalogResolver
+ */
+ public static CatalogResolver catalogResolver(Catalog catalog) {
+ if (catalog == null) CatalogMessages.reportNPEOnNull("catalog", null);
+ return new CatalogResolverImpl(catalog);
+ }
+
+ /**
+ * Creates an instance of a CatalogUriResolver using the specified catalog.
+ *
+ * @param catalog the catalog instance
+ * @return an instance of a CatalogResolver
+ */
+ public static CatalogUriResolver catalogUriResolver(Catalog catalog) {
+ if (catalog == null) CatalogMessages.reportNPEOnNull("catalog", null);
+ return new CatalogUriResolverImpl(catalog);
+ }
+
+ /**
+ * Creates an instance of a CatalogResolver using the specified feature settings
+ * and path to a catalog file. If the features is null, the default features will
+ * be used. If the path is empty, System property {@code javax.xml.catalog.files}
+ * will be read to locate the initial list of catalog files.
+ * <p>
+ * If more than one catalog files are specified through the path argument or
+ * {@code javax.xml.catalog.files} property, the first entry is considered
+ * the main catalog, while others are treated as alternative catalogs after
+ * those referenced by the {@code nextCatalog} elements in the main catalog.
+ *
+ * @param features the catalog features
+ * @param path the path(s) to one or more catalogs
+ *
+ * @return an instance of a CatalogResolver
+ * @throws CatalogException If no catalog can be found whether through the
+ * specified path or the System property {@code javax.xml.catalog.files}, or
+ * an error occurs while parsing the catalog
+ */
+ public static CatalogResolver catalogResolver(CatalogFeatures features, String... path) {
+ Catalog catalog = catalog(features, path);
+ return new CatalogResolverImpl(catalog);
+ }
+
+ /**
+ * Creates an instance of a CatalogUriResolver using the specified feature settings
+ * and path to a catalog file. If the features is null, the default features will
+ * be used. If the path is empty, System property {@code javax.xml.catalog.files}
+ * will be read to locate the initial list of catalog files.
+ * <p>
+ * If more than one catalog files are specified through the path argument or
+ * {@code javax.xml.catalog.files} property, the first entry is considered
+ * the main catalog, while others are treated as alternative catalogs after
+ * those referenced by the {@code nextCatalog} elements in the main catalog.
+ *
+ * @param features the catalog features
+ * @param path the path(s) to one or more catalogs
+ *
+ * @return an instance of a CatalogResolver
+ * @throws CatalogException If no catalog can be found whether through the
+ * specified path or the System property {@code javax.xml.catalog.files}, or
+ * an error occurs while parsing the catalog
+ */
+ public static CatalogUriResolver catalogUriResolver(CatalogFeatures features, String... path) {
+ Catalog catalog = catalog(features, path);
+ return new CatalogUriResolverImpl(catalog);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import jdk.xml.internal.SecuritySupport;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Catalog Error messages
+ *
+ * @since 9
+ */
+final class CatalogMessages {
+
+ public static final String ERR_INVALID_CATALOG = "InvalidCatalog";
+ public static final String ERR_INVALID_ENTRY_TYPE = "InvalidEntryType";
+ public static final String ERR_INVALID_ARGUMENT = "InvalidArgument";
+ public static final String ERR_NULL_ARGUMENT = "NullArgument";
+ public static final String ERR_CIRCULAR_REFERENCE = "CircularReference";
+ public static final String ERR_INVALID_PATH = "InvalidPath";
+ public static final String ERR_PARSER_CONF = "ParserConf";
+ public static final String ERR_PARSING_FAILED = "ParsingFailed";
+ public static final String ERR_NO_CATALOG = "NoCatalogFound";
+ public static final String ERR_NO_MATCH = "NoMatchFound";
+ public static final String ERR_NO_URI_MATCH = "NoMatchURIFound";
+ public static final String ERR_CREATING_URI = "FailedCreatingURI";
+ public static final String ERR_OTHER = "OtherError";
+
+ static final String bundleName = CatalogMessages.class.getPackage().getName() + ".CatalogMessages";
+ static ResourceBundle resourceBundle;
+
+ /**
+ * Reports an error.
+ * @param key the message key
+ */
+ static void reportError(String key) {
+ reportError(key, null);
+ }
+
+ /**
+ * Reports an error.
+ * @param key the message key
+ * @param arguments the message replacement text arguments. The order of the
+ * arguments must match that of the placeholders in the actual message.
+ */
+ static void reportError(String key, Object[] arguments) {
+ throw new CatalogException(formatMessage(key, arguments));
+ }
+
+ /**
+ * Reports a CatalogException.
+ * @param key the message key
+ * @param arguments the message replacement text arguments. The order of the
+ * arguments must match that of the placeholders in the actual message.
+ */
+ static void reportRunTimeError(String key, Object[] arguments) {
+ throw new CatalogException(formatMessage(key, arguments));
+ }
+
+ /**
+ * Reports a CatalogException.
+ * @param key the message key
+ * @param cause the cause if any
+ */
+ static void reportRunTimeError(String key, Throwable cause) {
+ throw new CatalogException(formatMessage(key, null), cause);
+ }
+
+ /**
+ * Reports a CatalogException.
+ * @param key the message key
+ * @param arguments the message replacement text arguments. The order of the
+ * arguments must match that of the placeholders in the actual message.
+ * @param cause the cause if any
+ */
+ static void reportRunTimeError(String key, Object[] arguments, Throwable cause) {
+ throw new CatalogException(formatMessage(key, arguments), cause);
+ }
+
+ /**
+ * Reports IllegalArgumentException if the argument is null.
+ *
+ * @param name the name of the argument
+ * @param value the value of the argument
+ */
+ static void reportIAEOnNull(String name, String value) {
+ if (value == null) {
+ throw new IllegalArgumentException(
+ formatMessage(ERR_INVALID_ARGUMENT, new Object[]{null, name}));
+ }
+ }
+
+ /**
+ * Reports NullPointerException if the argument is null.
+ *
+ * @param name the name of the argument
+ * @param value the value of the argument
+ */
+ static void reportNPEOnNull(String name, String value) {
+ if (value == null) {
+ throw new NullPointerException(
+ formatMessage(ERR_NULL_ARGUMENT, new Object[]{name}));
+ }
+ }
+
+ /**
+ * Reports IllegalArgumentException
+ * @param arguments the arguments for formating the error message
+ * @param cause the cause if any
+ */
+ static void reportIAE(Object[] arguments, Throwable cause) {
+ throw new IllegalArgumentException(
+ formatMessage(ERR_INVALID_ARGUMENT, arguments), cause);
+ }
+
+ /**
+ * Format a message with the specified arguments using the default locale
+ * information.
+ *
+ * @param key the message key
+ * @param arguments the message replacement text arguments. The order of the
+ * arguments must match that of the placeholders in the actual message.
+ *
+ * @return the formatted message
+ *
+ * @throws MissingResourceException If the message with the specified key
+ * cannot be found
+ */
+ static String formatMessage(String key, Object[] arguments) {
+ return formatMessage(key, arguments, Locale.getDefault());
+ }
+
+ /**
+ * Format a message with the specified arguments using the given locale
+ * information.
+ *
+ * @param key the message key
+ * @param arguments the message replacement text arguments. The order of the
+ * arguments must match that of the placeholders in the actual message.
+ * @param locale the locale of the message
+ *
+ * @return the formatted message
+ *
+ * @throws MissingResourceException If the message with the specified key
+ * cannot be found
+ */
+ static String formatMessage(String key, Object[] arguments, Locale locale) {
+ return SecuritySupport.getErrorMessage(locale, bundleName, key, arguments);
+ }
+
+ /**
+ * Returns sanitized URI.
+ * @param uri an URI to be sanitized
+ */
+ static String sanitize(String uri) {
+ if (uri == null) {
+ return null;
+ }
+ String temp;
+ int p;
+ p = uri.lastIndexOf("/");
+ if (p > 0 && p < uri.length()) {
+ return uri.substring(p + 1);
+ }
+ return uri;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,43 @@
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. 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.
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+#invalid catalog file
+InvalidCatalog = The document element of a catalog must be catalog.
+InvalidEntryType = The entry type ''{0}'' is not valid.
+CircularReference = Circular reference is not allowed: ''{0}''.
+
+#errors
+InvalidArgument = The specified argument ''{0}'' (case sensitive) for ''{1}'' is not valid.
+NullArgument = The argument ''{0}'' can not be null.
+InvalidPath = The path ''{0}'' is invalid.
+ParserConf = Unexpected error while configuring a SAX parser.
+ParsingFailed = Failed to parse the catalog file.
+NoCatalogFound = No Catalog is specified.
+NoMatchFound = No match found for publicId ''{0}'' and systemId ''{1}''.
+NoMatchURIFound = No match found for href ''{0}'' and base ''{1}''.
+FailedCreatingURI = Can not construct URI using href ''{0}'' and base ''{1}''.
+OtherError = Unexpected error.
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.io.StringReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import javax.xml.catalog.BaseEntry.CatalogEntryType;
+import javax.xml.parsers.SAXParser;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.sax.SAXSource;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * CatalogReader handles SAX events while parsing through a catalog file to
+ * create a catalog object.
+ *
+ * @since 9
+ */
+class CatalogReader extends DefaultHandler implements EntityResolver, URIResolver {
+ /** URI of the W3C XML Schema for OASIS XML Catalog files. */
+ public static final String xmlCatalogXSD = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.xsd";
+
+ /** Public identifier for OASIS XML Catalog files. */
+ public static final String xmlCatalogPubId = "-//OASIS//DTD XML Catalogs V1.0//EN";
+
+ /**
+ * The namespace name defined by the OASIS Standard
+ */
+ public static final String NAMESPACE_OASIS = "urn:oasis:names:tc:entity:xmlns:xml:catalog";
+
+ //Indicate whether the root element has been found
+ boolean seenRoot;
+
+ //Indicate that the parser is in a group entry
+ boolean inGroup;
+
+ //The Catalog instance
+ CatalogImpl catalog;
+
+ //The parser for reading the catalog
+ SAXParser parser;
+
+ //The current catalog entry
+ CatalogEntry catalogEntry;
+
+ //The current group
+ GroupEntry group;
+
+ //The current entry
+ BaseEntry entry;
+
+ //remove this variable once 8136778 is committed
+ boolean ignoreTheCatalog = false;
+
+ /**
+ * Constructs an instance with a Catalog object and parser.
+ *
+ * @param catalog The Catalog object that represents a catalog
+ */
+ @SuppressWarnings("unchecked")
+ public CatalogReader(Catalog catalog, SAXParser parser) {
+ this.catalog = (CatalogImpl) catalog;
+ this.parser = parser;
+ }
+
+ /**
+ * Returns when the specified path is valid.
+ * @param path a path
+ * @return true if the path is valid, false otherwise
+ */
+ boolean isValidPath(String path) {
+ boolean valid = true;
+ try {
+ Path p = Paths.get(new URI(path));
+ if (!p.toFile().exists()) {
+ valid = false;
+ }
+ } catch (URISyntaxException ex) {
+ valid = false;
+ }
+
+ return valid;
+ }
+
+ @Override
+ public void startElement(String namespaceURI,
+ String localName,
+ String qName,
+ Attributes atts)
+ throws SAXException {
+
+ //ignore the catalog if it's not compliant. See section 8, item 3 of the spec.
+ if (ignoreTheCatalog) return;
+ if (!NAMESPACE_OASIS.equals(namespaceURI)) {
+//wait till 8136778 is committed
+// parser.stop();
+ ignoreTheCatalog = true;
+ return;
+ }
+
+
+ CatalogEntryType type = CatalogEntryType.getType(localName);
+ if (type == null) {
+ CatalogMessages.reportError(CatalogMessages.ERR_INVALID_ENTRY_TYPE,
+ new Object[]{localName});
+ }
+ if (type != CatalogEntryType.CATALOGENTRY) {
+ if (!seenRoot) {
+ CatalogMessages.reportError(CatalogMessages.ERR_INVALID_CATALOG);
+ }
+ }
+
+ String base = atts.getValue("xml:base");
+ if (base == null) {
+ if (inGroup) {
+ base = group.getBaseURI().toString();
+ } else {
+ if (type == CatalogEntryType.CATALOGENTRY) {
+ base = catalog.getBaseURI().toString();
+ } else {
+ base = catalogEntry.getBaseURI().toString();
+ }
+ }
+ } else {
+ base = Normalizer.normalizeURI(base);
+ }
+
+ //parse the catalog and group entries
+ if (type == CatalogEntryType.CATALOGENTRY
+ || type == CatalogEntryType.GROUP) {
+ String prefer = atts.getValue("prefer");
+ if (prefer == null) {
+ if (type == CatalogEntryType.CATALOGENTRY) {
+ //use the general setting
+ prefer = catalog.isPreferPublic() ?
+ CatalogFeatures.PREFER_PUBLIC : CatalogFeatures.PREFER_SYSTEM;
+ } else {
+ //Group inherit from the catalog entry
+ prefer = catalogEntry.isPreferPublic() ?
+ CatalogFeatures.PREFER_PUBLIC : CatalogFeatures.PREFER_SYSTEM;
+ }
+ }
+
+ if (type == CatalogEntryType.CATALOGENTRY) {
+ seenRoot = true;
+ if (catalog.isTop()) {
+ String defer = atts.getValue("defer");
+ String resolve = atts.getValue("resolve");
+ if (defer == null) {
+ defer = catalog.isDeferred() ?
+ CatalogFeatures.DEFER_TRUE : CatalogFeatures.DEFER_FALSE;
+ }
+ if (resolve == null) {
+ resolve = catalog.getResolve().literal;
+ }
+ catalog.setResolve(resolve);
+ catalogEntry = new CatalogEntry(base, prefer, defer, resolve);
+ } else {
+ catalogEntry = new CatalogEntry(base, prefer);
+ }
+ return;
+ } else {
+ inGroup = true;
+ group = new GroupEntry(catalog, base, prefer);
+ catalog.addEntry(group);
+ return;
+ }
+ }
+
+ //parse entries other than the catalog and group entries
+ switch (type) {
+ case PUBLIC:
+ entry = new PublicEntry(base, atts.getValue("publicId"), atts.getValue("uri"));
+ break;
+ case SYSTEM:
+ entry = new SystemEntry(base, atts.getValue("systemId"), atts.getValue("uri"));
+ break;
+ case REWRITESYSTEM:
+ entry = new RewriteSystem(base, atts.getValue("systemIdStartString"), atts.getValue("rewritePrefix"));
+ break;
+ case SYSTEMSUFFIX:
+ entry = new SystemSuffix(base, atts.getValue("systemIdSuffix"), atts.getValue("uri"));
+ break;
+ case DELEGATEPUBLIC:
+ entry = new DelegatePublic(base, atts.getValue("publicIdStartString"), atts.getValue("catalog"));
+ break;
+ case DELEGATESYSTEM:
+ entry = new DelegateSystem(base, atts.getValue("systemIdStartString"), atts.getValue("catalog"));
+ break;
+ case URI:
+ entry = new UriEntry(base, atts.getValue("name"), atts.getValue("uri"));
+ break;
+ case REWRITEURI:
+ entry = new RewriteUri(base, atts.getValue("uriStartString"), atts.getValue("rewritePrefix"));
+ break;
+ case URISUFFIX:
+ entry = new UriSuffix(base, atts.getValue("uriSuffix"), atts.getValue("uri"));
+ break;
+ case DELEGATEURI:
+ entry = new DelegateUri(base, atts.getValue("uriStartString"), atts.getValue("catalog"));
+ break;
+ case NEXTCATALOG:
+ entry = new NextCatalog(base, atts.getValue("catalog"));
+ break;
+ }
+
+ if (type == CatalogEntryType.NEXTCATALOG) {
+ catalog.addNextCatalog((NextCatalog) entry);
+ } else if (inGroup) {
+ group.addEntry(entry);
+ } else {
+ catalog.addEntry(entry);
+ }
+
+ }
+
+ /**
+ * Handles endElement event
+ */
+ @Override
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ if (ignoreTheCatalog) return;
+
+ CatalogEntryType type = CatalogEntryType.getType(localName);
+ if (type == CatalogEntryType.GROUP) {
+ inGroup = false;
+ } else if (type == CatalogEntryType.CATALOGENTRY) {
+ /*
+ Done reading the catalog file.
+ Load delegate and alternative catalogs if defer is false.
+ */
+ if (!catalog.isDeferred()) {
+ catalog.loadDelegateCatalogs();
+ catalog.loadNextCatalogs();
+ }
+ }
+ }
+
+
+ /**
+ * Skips external DTD since resolving external DTD is not required
+ * by the specification.
+ */
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) {
+ return new InputSource(new StringReader(""));
+ }
+
+ /**
+ * Skips external references since resolution is not required
+ * by the specification.
+ */
+ @Override
+ public Source resolve(String href, String base)
+ throws TransformerException {
+ return new SAXSource(new InputSource(new StringReader("")));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+/**
+ * A SAX EntityResolver that uses catalogs to resolve references.
+ *
+ * @since 9
+ */
+public interface CatalogResolver extends EntityResolver {
+
+ /**
+ * The method searches through the catalog entries in the main and
+ * alternative catalogs to attempt to find a match with the specified publicId
+ * or systemId.
+ * <p>
+ * For resolving external entities, system entries will be matched before
+ * the public entries.
+ * <p>
+ * <b>The {@code prefer} attribute</b>: if the {@code prefer} is public,
+ * and there is no match found through the system entries, public entries
+ * will be considered. If it is not specified, the {@code prefer} is public
+ * by default (Note that by the OASIS standard, system entries will always
+ * be considered first when the external system identifier is specified.
+ * Prefer public means that public entries will be matched when both system
+ * and public identifiers are specified. In general therefore, prefer
+ * public is recommended.)
+ *
+ * @param publicId the public identifier of the external entity being
+ * referenced, or null if none was supplied
+ *
+ * @param systemId the system identifier of the external entity being
+ * referenced. A system identifier is required on all external entities. XML
+ * requires a system identifier on all external entities, so this value is
+ * always specified.
+ *
+ * @return a {@link org.xml.sax.InputSource} object if a mapping is found. If no mapping is
+ * found, returns a {@link org.xml.sax.InputSource} object containing an empty
+ * {@link java.io.Reader} if the {@code javax.xml.catalog.resolve} property
+ * is set to {@code ignore}; returns null if the
+ * {@code javax.xml.catalog.resolve} property is set to {@code continue}.
+ *
+ * @throws CatalogException if no mapping is found and
+ * {@code javax.xml.catalog.resolve} is specified as strict
+ */
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.io.StringReader;
+import java.util.Iterator;
+import org.xml.sax.InputSource;
+
+/**
+ * A SAX EntityResolver/JAXP URIResolver that uses catalogs.
+ *
+ * <p>
+ * This class implements both a SAX EntityResolver and a JAXP URIResolver.
+ *
+ *
+ * @since 9
+ */
+final class CatalogResolverImpl implements CatalogResolver {
+ Catalog catalog;
+
+ /**
+ * Construct an instance of the CatalogResolver from a Catalog.
+ *
+ * @param catalog A Catalog.
+ */
+ public CatalogResolverImpl(Catalog catalog) {
+ this.catalog = catalog;
+ }
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) {
+ //Normalize publicId and systemId
+ systemId = Normalizer.normalizeURI(systemId);
+ publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(publicId));
+
+ //check whether systemId is an urn
+ if (systemId != null && systemId.startsWith("urn:publicid:")) {
+ systemId = Normalizer.decodeURN(systemId);
+ if (publicId != null && !publicId.equals(systemId)) {
+ systemId = null;
+ } else {
+ publicId = systemId;
+ systemId = null;
+ }
+ }
+
+ CatalogImpl c = (CatalogImpl)catalog;
+ String resolvedSystemId = resolve(c, publicId, systemId);
+
+ if (resolvedSystemId != null) {
+ return new InputSource(resolvedSystemId);
+ }
+
+ GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
+ switch (resolveType) {
+ case IGNORE:
+ return new InputSource(new StringReader(""));
+ case STRICT:
+ CatalogMessages.reportError(CatalogMessages.ERR_NO_MATCH,
+ new Object[]{publicId, systemId});
+ }
+
+ //no action, allow the parser to continue
+ return null;
+ }
+
+ /**
+ * Resolves the publicId or systemId to one specified in the catalog.
+ * @param catalog the catalog
+ * @param publicId the publicId
+ * @param systemId the systemId
+ * @return the resolved systemId if a match is found, null otherwise
+ */
+ String resolve(CatalogImpl catalog, String publicId, String systemId) {
+ String resolvedSystemId = null;
+
+ //search the current catalog
+ catalog.reset();
+ if (systemId != null) {
+ resolvedSystemId = catalog.matchSystem(systemId);
+ }
+ if (resolvedSystemId == null) {
+ resolvedSystemId = catalog.matchPublic(publicId);
+ }
+
+ //mark the catalog as having been searched before trying alternatives
+ catalog.markAsSearched();
+
+ //search alternative catalogs
+ if (resolvedSystemId == null) {
+ Iterator<Catalog> iter = catalog.catalogs().iterator();
+ while (iter.hasNext()) {
+ resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
+ if (resolvedSystemId != null) {
+ break;
+ }
+
+ }
+ }
+
+ return resolvedSystemId;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolver.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.URIResolver;
+
+/**
+ * A JAXP URIResolver that uses catalogs to resolve references.
+ *
+ * @since 9
+ */
+public interface CatalogUriResolver extends URIResolver {
+
+ /**
+ * The method searches through the catalog entries in the main and
+ * alternative catalogs to attempt to find a match with the specified URI.
+ *
+ * @param href an href attribute, which may be relative or absolute
+ * @param base The base URI against which the href attribute will be made
+ * absolute if the absolute URI is required
+ *
+ * @return a {@link javax.xml.transform.Source} object if a mapping is found.
+ * If no mapping is found, returns a {@link javax.xml.transform.Source} object
+ * containing an empty {@link java.io.Reader} if the
+ * {@code javax.xml.catalog.resolve} property is set to {@code ignore};
+ * returns a {@link javax.xml.transform.Source} object with the original URI
+ * (href, or href resolved with base if base is not null) if the
+ * {@code javax.xml.catalog.resolve} property is set to {@code continue}.
+ *
+ * @throws CatalogException if no mapping is found and
+ * {@code javax.xml.catalog.resolve} is specified as strict
+ */
+ @Override
+ public Source resolve(String href, String base);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolverImpl.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.Iterator;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * A SAX EntityResolver/JAXP URIResolver that uses catalogs.
+ * <p>
+ * This class implements both a SAX EntityResolver and a JAXP URIResolver.
+ *
+ *
+ * @since 9
+ */
+final class CatalogUriResolverImpl implements CatalogUriResolver {
+
+ Catalog catalog;
+ CatalogResolverImpl entityResolver;
+
+ /**
+ * Construct an instance of the CatalogResolver from a Catalog.
+ *
+ * @param catalog A Catalog.
+ */
+ public CatalogUriResolverImpl(Catalog catalog) {
+ this.catalog = catalog;
+ }
+
+ @Override
+ public Source resolve(String href, String base) {
+ if (href == null) return null;
+
+ CatalogImpl c = (CatalogImpl)catalog;
+ String uri = Normalizer.normalizeURI(href);
+ String result;
+
+ //remove fragment if any.
+ int hashPos = uri.indexOf("#");
+ if (hashPos >= 0) {
+ uri = uri.substring(0, hashPos);
+ }
+
+ //search the current catalog
+ result = resolve(c, uri);
+ if (result == null) {
+ GroupEntry.ResolveType resolveType = c.getResolve();
+ switch (resolveType) {
+ case IGNORE:
+ return new SAXSource(new InputSource(new StringReader("")));
+ case STRICT:
+ CatalogMessages.reportError(CatalogMessages.ERR_NO_URI_MATCH,
+ new Object[]{href, base});
+ }
+ try {
+ URL url = null;
+
+ if (base == null) {
+ url = new URL(uri);
+ result = url.toString();
+ } else {
+ URL baseURL = new URL(base);
+ url = (href.length() == 0 ? baseURL : new URL(baseURL, uri));
+ result = url.toString();
+ }
+ } catch (java.net.MalformedURLException mue) {
+ CatalogMessages.reportError(CatalogMessages.ERR_CREATING_URI,
+ new Object[]{href, base});
+ }
+ }
+
+ SAXSource source = new SAXSource();
+ source.setInputSource(new InputSource(result));
+ setEntityResolver(source);
+ return source;
+ }
+
+ /**
+ * Resolves the publicId or systemId to one specified in the catalog.
+ * @param catalog the catalog
+ * @param href an href attribute, which may be relative or absolute
+ * @return the resolved systemId if a match is found, null otherwise
+ */
+ String resolve(CatalogImpl catalog, String href) {
+ String result = null;
+
+ //search the current catalog
+ catalog.reset();
+ if (href != null) {
+ result = catalog.matchURI(href);
+ }
+
+ //mark the catalog as having been searched before trying alternatives
+ catalog.markAsSearched();
+
+ //search alternative catalogs
+ if (result == null) {
+ Iterator<Catalog> iter = catalog.catalogs().iterator();
+ while (iter.hasNext()) {
+ result = resolve((CatalogImpl)iter.next(), href);
+ if (result != null) {
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Establish an entityResolver for newly resolved URIs.
+ * <p>
+ * This is called from the URIResolver to set an EntityResolver on the SAX
+ * parser to be used for new XML documents that are encountered as a result
+ * of the document() function, xsl:import, or xsl:include. This is done
+ * because the XSLT processor calls out to the SAXParserFactory itself to
+ * create a new SAXParser to parse the new document. The new parser does not
+ * automatically inherit the EntityResolver of the original (although
+ * arguably it should). Quote from JAXP specification on Class
+ * SAXTransformerFactory:
+ * <p>
+ * {@code If an application wants to set the ErrorHandler or EntityResolver
+ * for an XMLReader used during a transformation, it should use a URIResolver
+ * to return the SAXSource which provides (with getXMLReader) a reference to
+ * the XMLReader}
+ *
+ */
+ private void setEntityResolver(SAXSource source) {
+ XMLReader reader = source.getXMLReader();
+ if (reader == null) {
+ SAXParserFactory spFactory = new SAXParserFactoryImpl();
+ spFactory.setNamespaceAware(true);
+ try {
+ reader = spFactory.newSAXParser().getXMLReader();
+ } catch (ParserConfigurationException | SAXException ex) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSER_CONF, ex);
+ }
+ }
+ if (entityResolver != null) {
+ entityResolver = new CatalogResolverImpl(catalog);
+ }
+ reader.setEntityResolver(entityResolver);
+ source.setXMLReader(reader);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/DelegatePublic.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URI;
+
+/**
+ * Represents a delegatePublic entry.
+ *
+ * @since 9
+ */
+final class DelegatePublic extends AltCatalog {
+ String publicIdStartString;
+
+ /**
+ * Construct a delegatePublic entry.
+ * @param startString The publicIdStartString attribute.
+ * @param catalog The catalog attribute.
+ */
+ public DelegatePublic(String base, String startString, String catalog) {
+ super(CatalogEntryType.DELEGATEPUBLIC, base);
+ setPublicIdStartString(startString);
+ setCatalog(catalog);
+ }
+
+ /**
+ * Set the publicIdStartString attribute.
+ * @param startString The publicIdStartString attribute value.
+ */
+ public void setPublicIdStartString (String startString) {
+ CatalogMessages.reportNPEOnNull("publicIdStartString", startString);
+ this.publicIdStartString = Normalizer.normalizePublicId(startString);
+ setMatchId(publicIdStartString);
+ }
+
+ /**
+ * Get the publicIdStartString attribute.
+ * @return The publicIdStartString
+ */
+ public String getPublicIdStartString () {
+ return publicIdStartString;
+ }
+
+ /**
+ * Try to match the specified publicId with the entry.
+ *
+ * @param publicId The publicId to be matched.
+ * @return The URI of the catalog.
+ */
+ @Override
+ public String match(String publicId) {
+ return match(publicId, 0);
+ }
+
+ /**
+ * Try to match the specified publicId with the entry. Return the match if it
+ * is successful and the length of the publicIdStartString is longer than the
+ * longest of any previous match.
+ *
+ * @param publicId The publicId to be matched.
+ * @param currentMatch The length of publicIdStartString of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public URI matchURI(String publicId, int currentMatch) {
+ if (publicIdStartString.length() <= publicId.length() &&
+ publicIdStartString.equals(publicId.substring(0, publicIdStartString.length()))) {
+ if (currentMatch < publicIdStartString.length()) {
+ return catalogURI;
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/DelegateSystem.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URI;
+
+/**
+ * Represents a delegateSystem entry.
+ *
+ * @since 9
+ */
+final class DelegateSystem extends AltCatalog {
+ String systemIdStartString;
+
+ /**
+ * Construct a delegateSystem entry.
+ * @param systemIdStartString The systemIdStartString attribute.
+ * @param catalog The catalog attribute.
+ */
+ public DelegateSystem(String base, String systemIdStartString, String catalog) {
+ super(CatalogEntryType.DELEGATESYSTEM, base);
+ setSystemIdStartString(systemIdStartString);
+ setCatalog(catalog);
+ }
+
+ /**
+ * Set the systemIdStartString attribute.
+ * @param systemIdStartString The systemIdStartString attribute value.
+ */
+ public void setSystemIdStartString (String systemIdStartString) {
+ CatalogMessages.reportNPEOnNull("systemIdStartString", systemIdStartString);
+ this.systemIdStartString = Normalizer.normalizeURI(systemIdStartString);
+ setMatchId(this.systemIdStartString);
+ }
+
+ /**
+ * Get the systemIdStartString attribute.
+ * @return The systemIdStartString
+ */
+ public String getSystemIdStartString () {
+ return systemIdStartString;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry.
+ *
+ * @param systemId The systemId to be matched.
+ * @return The URI of the catalog.
+ */
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+
+ /**
+ * Matches the specified publicId with the entry. Return the match if it
+ * is successful and the length of the systemIdStartString is longer than the
+ * longest of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of systemIdStartString of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public URI matchURI(String systemId, int currentMatch) {
+ if (systemIdStartString.length() <= systemId.length() &&
+ systemIdStartString.equals(systemId.substring(0, systemIdStartString.length()))) {
+ if (currentMatch < systemIdStartString.length()) {
+ return catalogURI;
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/DelegateUri.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URI;
+
+/**
+ * Represents a delegateURI entry.
+ *
+ * @since 9
+ */
+final class DelegateUri extends AltCatalog {
+ String uriStartString;
+
+ /**
+ * Construct a delegateURI entry.
+ * @param uriStartString The uriStartString attribute.
+ * @param catalog The catalog attribute.
+ */
+ public DelegateUri(String base, String uriStartString, String catalog) {
+ super(CatalogEntryType.DELEGATEURI, base);
+ setURIStartString (uriStartString);
+ setCatalog(catalog);
+ }
+
+ /**
+ * Set the uriStartString attribute.
+ *
+ * @param uriStartString The uriStartString attribute value.
+ */
+ public void setURIStartString (String uriStartString) {
+ CatalogMessages.reportNPEOnNull("uriStartString", uriStartString);
+ this.uriStartString = Normalizer.normalizeURI(uriStartString);
+ setMatchId(this.uriStartString);
+ }
+
+ /**
+ * Get the uriStartString attribute.
+ * @return The uriStartString
+ */
+ public String getURIStartString () {
+ return uriStartString;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry.
+ *
+ * @param systemId The systemId to be matched.
+ * @return The URI of the catalog.
+ */
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+
+ /**
+ * Matches the specified systemId with the entry. Return the match if it
+ * is successful and the length of the uriStartString is longer than the
+ * longest of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of uriStartString of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public URI matchURI(String systemId, int currentMatch) {
+ if (uriStartString.length() <= systemId.length() &&
+ uriStartString.equals(systemId.substring(0, uriStartString.length()))) {
+ if (currentMatch < uriStartString.length()) {
+ return catalogURI;
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents a group entry.
+ *
+ * @since 9
+ */
+class GroupEntry extends BaseEntry {
+ static final int ATTRIBUTE_PREFER = 0;
+ static final int ATTRIBUTE_DEFFER = 1;
+ static final int ATTRIBUTE_RESOLUTION = 2;
+
+ //Unmodifiable features when the Catalog is created
+ CatalogFeatures features;
+
+ //Value of the prefer attribute
+ boolean isPreferPublic = true;
+
+ //The catalog instance this group belongs to
+ CatalogImpl catalog;
+
+ //A list of all entries in a catalog or group
+ List<BaseEntry> entries = new ArrayList<>();
+
+ //loaded delegated catalog by system id
+ Map<String, Catalog> delegateCatalogs = new HashMap<>();
+
+ //A list of all loaded Catalogs, including this, and next catalogs
+ Map<String, Catalog> loadedCatalogs = new HashMap<>();
+
+ /*
+ A list of Catalog Ids that have already been searched in a matching
+ operation. Check this list before constructing new Catalog to avoid circular
+ reference.
+ */
+ List<String> catalogsSearched = new ArrayList<>();
+
+ //A flag to indicate whether the current match is a system or uri
+ boolean isInstantMatch = false;
+
+ //A match of a rewrite type
+ String rewriteMatch = null;
+
+ //The length of the longest match of a rewrite type
+ int longestRewriteMatch = 0;
+
+ //A match of a suffix type
+ String suffixMatch = null;
+
+ //The length of the longest match of a suffix type
+ int longestSuffixMatch = 0;
+
+ /**
+ * PreferType represents possible values of the prefer property
+ */
+ public static enum PreferType {
+ PUBLIC("public"),
+ SYSTEM("system");
+
+ final String literal;
+
+ PreferType(String literal) {
+ this.literal = literal;
+ }
+
+ public boolean prefer(String prefer) {
+ return literal.equals(prefer);
+ }
+ }
+
+ /**
+ * PreferType represents possible values of the resolve property
+ */
+ public static enum ResolveType {
+ STRICT(CatalogFeatures.RESOLVE_STRICT),
+ CONTINUE(CatalogFeatures.RESOLVE_CONTINUE),
+ IGNORE(CatalogFeatures.RESOLVE_IGNORE);
+
+ final String literal;
+
+ ResolveType(String literal) {
+ this.literal = literal;
+ }
+
+ static public ResolveType getType(String resolveType) {
+ for (ResolveType type : ResolveType.values()) {
+ if (type.isType(resolveType)) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ public boolean isType(String type) {
+ return literal.equals(type);
+ }
+ }
+
+ /**
+ * Constructs a GroupEntry
+ *
+ * @param type The type of the entry
+ */
+ public GroupEntry(CatalogEntryType type) {
+ super(type);
+ }
+
+ /**
+ * Constructs a group entry.
+ *
+ * @param base The baseURI attribute
+ * @param attributes The attributes
+ */
+ public GroupEntry(String base, String... attributes) {
+ this(null, base, attributes);
+ }
+
+ /**
+ * Resets the group entry to its initial state.
+ */
+ public void reset() {
+ isInstantMatch = false;
+ rewriteMatch = null;
+ longestRewriteMatch = 0;
+ suffixMatch = null;
+ longestSuffixMatch = 0;
+ }
+ /**
+ * Constructs a group entry.
+ * @param catalog The parent catalog
+ * @param base The baseURI attribute
+ * @param attributes The attributes
+ */
+ public GroupEntry(CatalogImpl catalog, String base, String... attributes) {
+ super(CatalogEntryType.GROUP, base);
+ setPrefer(attributes[ATTRIBUTE_PREFER]);
+ this.catalog = catalog;
+ }
+
+ /**
+ * Adds an entry.
+ *
+ * @param entry The entry to be added.
+ */
+ public void addEntry(BaseEntry entry) {
+ entries.add(entry);
+ }
+
+ /**
+ * Sets the prefer property. If the value is null or empty, or any String
+ * other than the defined, it will be assumed as the default value.
+ *
+ * @param value The value of the prefer attribute
+ */
+ public final void setPrefer(String value) {
+ isPreferPublic = PreferType.PUBLIC.prefer(value);
+ }
+
+ /**
+ * Queries the prefer attribute
+ *
+ * @return true if the prefer attribute is set to system, false if not.
+ */
+ public boolean isPreferPublic() {
+ return isPreferPublic;
+ }
+
+ /**
+ * Attempt to find a matching entry in the catalog by systemId.
+ *
+ * <p>
+ * The method searches through the system-type entries, including system,
+ * rewriteSystem, systemSuffix, delegateSystem, and group entries in the
+ * current catalog in order to find a match.
+ *
+ *
+ * @param systemId The system identifier of the external entity being
+ * referenced.
+ *
+ * @return An URI string if a mapping is found, or null otherwise.
+ */
+ public String matchSystem(String systemId) {
+ String match = null;
+ for (BaseEntry entry : entries) {
+ switch (entry.type) {
+ case SYSTEM:
+ match = ((SystemEntry) entry).match(systemId);
+ //if there's a matching system entry, use it
+ if (match != null) {
+ isInstantMatch = true;
+ return match;
+ }
+ break;
+ case REWRITESYSTEM:
+ match = ((RewriteSystem) entry).match(systemId, longestRewriteMatch);
+ if (match != null) {
+ rewriteMatch = match;
+ longestRewriteMatch = ((RewriteSystem) entry).getSystemIdStartString().length();
+ }
+ break;
+ case SYSTEMSUFFIX:
+ match = ((SystemSuffix) entry).match(systemId, longestSuffixMatch);
+ if (match != null) {
+ suffixMatch = match;
+ longestSuffixMatch = ((SystemSuffix) entry).getSystemIdSuffix().length();
+ }
+ break;
+ case GROUP:
+ GroupEntry grpEntry = (GroupEntry) entry;
+ match = grpEntry.matchSystem(systemId);
+ if (grpEntry.isInstantMatch) {
+ //use it if there is a match of the system type
+ return match;
+ } else if (grpEntry.longestRewriteMatch > longestRewriteMatch) {
+ rewriteMatch = match;
+ } else if (grpEntry.longestSuffixMatch > longestSuffixMatch) {
+ suffixMatch = match;
+ }
+ break;
+ }
+ }
+
+ if (longestRewriteMatch > 0) {
+ return rewriteMatch;
+ } else if (longestSuffixMatch > 0) {
+ return suffixMatch;
+ }
+
+ //if no single match is found, try delegates
+ return matchDelegate(CatalogEntryType.DELEGATESYSTEM, systemId);
+ }
+
+ /**
+ * Attempt to find a matching entry in the catalog by publicId.
+ *
+ * <p>
+ * The method searches through the public-type entries, including public,
+ * delegatePublic, and group entries in the current catalog in order to find
+ * a match.
+ *
+ *
+ * @param publicId The public identifier of the external entity being
+ * referenced.
+ *
+ * @return An URI string if a mapping is found, or null otherwise.
+ */
+ public String matchPublic(String publicId) {
+ //as the specification required
+ if (!isPreferPublic) {
+ return null;
+ }
+
+ //match public entries
+ String match = null;
+ for (BaseEntry entry : entries) {
+ switch (entry.type) {
+ case PUBLIC:
+ match = ((PublicEntry) entry).match(publicId);
+ break;
+ case GROUP:
+ match = ((GroupEntry) entry).matchPublic(publicId);
+ break;
+ }
+ if (match != null) {
+ return match;
+ }
+ }
+
+ //if no single match is found, try delegates
+ return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId);
+ }
+
+ /**
+ * Attempt to find a matching entry in the catalog by the uri element.
+ *
+ * <p>
+ * The method searches through the uri-type entries, including uri,
+ * rewriteURI, uriSuffix, delegateURI and group entries in the current
+ * catalog in order to find a match.
+ *
+ *
+ * @param uri The URI reference of a resource.
+ *
+ * @return An URI string if a mapping is found, or null otherwise.
+ */
+ public String matchURI(String uri) {
+ String match = null;
+ for (BaseEntry entry : entries) {
+ switch (entry.type) {
+ case URI:
+ match = ((UriEntry) entry).match(uri);
+ if (match != null) {
+ isInstantMatch = true;
+ return match;
+ }
+ break;
+ case REWRITEURI:
+ match = ((RewriteUri) entry).match(uri, longestRewriteMatch);
+ if (match != null) {
+ rewriteMatch = match;
+ longestRewriteMatch = ((RewriteUri) entry).getURIStartString().length();
+ }
+ break;
+ case URISUFFIX:
+ match = ((UriSuffix) entry).match(uri, longestSuffixMatch);
+ if (match != null) {
+ suffixMatch = match;
+ longestSuffixMatch = ((UriSuffix) entry).getURISuffix().length();
+ }
+ break;
+ case GROUP:
+ GroupEntry grpEntry = (GroupEntry) entry;
+ match = grpEntry.matchURI(uri);
+ if (grpEntry.isInstantMatch) {
+ //use it if there is a match of the uri type
+ return match;
+ } else if (grpEntry.longestRewriteMatch > longestRewriteMatch) {
+ rewriteMatch = match;
+ } else if (grpEntry.longestSuffixMatch > longestSuffixMatch) {
+ suffixMatch = match;
+ }
+ break;
+ }
+ }
+
+ if (longestRewriteMatch > 0) {
+ return rewriteMatch;
+ } else if (longestSuffixMatch > 0) {
+ return suffixMatch;
+ }
+
+ //if no single match is found, try delegates
+ return matchDelegate(CatalogEntryType.DELEGATEURI, uri);
+ }
+
+ /**
+ * Matches delegatePublic or delegateSystem against the specified id
+ *
+ * @param isSystem The flag to indicate whether the delegate is system or
+ * public
+ * @param id The system or public id to be matched
+ * @return The URI string if a mapping is found, or null otherwise.
+ */
+ private String matchDelegate(CatalogEntryType type, String id) {
+ String match = null;
+ int longestMatch = 0;
+ URI catalogId = null;
+ URI temp;
+
+ //Check delegate types in the current catalog
+ for (BaseEntry entry : entries) {
+ if (entry.type == type) {
+ if (type == CatalogEntryType.DELEGATESYSTEM) {
+ temp = ((DelegateSystem)entry).matchURI(id, longestMatch);
+ } else if (type == CatalogEntryType.DELEGATEPUBLIC) {
+ temp = ((DelegatePublic)entry).matchURI(id, longestMatch);
+ } else {
+ temp = ((DelegateUri)entry).matchURI(id, longestMatch);
+ }
+ if (temp != null) {
+ longestMatch = entry.getMatchId().length();
+ catalogId = temp;
+ }
+ }
+ }
+
+ //Check delegate Catalogs
+ if (catalogId != null) {
+ Catalog delegateCatalog = loadCatalog(catalogId);
+
+ if (delegateCatalog != null) {
+ if (type == CatalogEntryType.DELEGATESYSTEM) {
+ match = delegateCatalog.matchSystem(id);
+ } else if (type == CatalogEntryType.DELEGATEPUBLIC) {
+ match = delegateCatalog.matchPublic(id);
+ } else {
+ match = delegateCatalog.matchURI(id);
+ }
+ }
+ }
+
+ return match;
+ }
+
+ /**
+ * Loads all delegate catalogs.
+ */
+ void loadDelegateCatalogs() {
+ entries.stream()
+ .filter((entry) -> (entry.type == CatalogEntryType.DELEGATESYSTEM ||
+ entry.type == CatalogEntryType.DELEGATEPUBLIC ||
+ entry.type == CatalogEntryType.DELEGATEURI))
+ .map((entry) -> (AltCatalog)entry)
+ .forEach((altCatalog) -> {
+ loadCatalog(altCatalog.getCatalogURI());
+ });
+ }
+
+ /**
+ * Loads a delegate catalog by the catalogId specified.
+ * @param catalogId the catalog Id
+ */
+ Catalog loadCatalog(URI catalogURI) {
+ Catalog delegateCatalog = null;
+ if (catalogURI != null) {
+ String catalogId = catalogURI.toASCIIString();
+ delegateCatalog = getLoadedCatalog(catalogId);
+ if (delegateCatalog == null) {
+ if (verifyCatalogFile(catalogURI)) {
+ delegateCatalog = new CatalogImpl(catalog, features, catalogId);
+ delegateCatalogs.put(catalogId, delegateCatalog);
+ }
+ }
+ }
+
+ return delegateCatalog;
+ }
+
+ /**
+ * Returns a previously loaded Catalog object if found.
+ *
+ * @param catalogId The systemId of a catalog
+ * @return a Catalog object previously loaded, or null if none in the saved
+ * list
+ */
+ Catalog getLoadedCatalog(String catalogId) {
+ Catalog c = null;
+
+ //checl delegate Catalogs
+ c = delegateCatalogs.get(catalogId);
+ if (c == null) {
+ //check other loaded Catalogs
+ c = loadedCatalogs.get(catalogId);
+ }
+
+ return c;
+ }
+
+
+ /**
+ * Verifies that the catalog file represented by the catalogId exists. If it
+ * doesn't, returns false to ignore it as specified in the Catalog
+ * specification, section 8. Resource Failures.
+ * <p>
+ * Verifies that the catalog represented by the catalogId has not been
+ * searched or is not circularly referenced.
+ *
+ * @param catalogId The URI to a catalog
+ * @throws CatalogException if circular reference is found.
+ * @return true if the catalogId passed verification, false otherwise
+ */
+ final boolean verifyCatalogFile(URI catalogURI) {
+ if (catalogURI == null) {
+ return false;
+ }
+
+ //Ignore it if it doesn't exist
+ if (!Files.exists(Paths.get(catalogURI))) {
+ return false;
+ }
+
+ String catalogId = catalogURI.toASCIIString();
+ if (catalogsSearched.contains(catalogId)) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_CIRCULAR_REFERENCE,
+ new Object[]{CatalogMessages.sanitize(catalogId)});
+ }
+
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/NextCatalog.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+/**
+ * Represents a nextCatalog entry.
+ *
+ * @since 9
+ */
+final class NextCatalog extends AltCatalog {
+
+ /**
+ * Construct a nextCatalog entry.
+ * @param catalog The catalog attribute.
+ */
+ public NextCatalog(String base, String catalog) {
+ super(CatalogEntryType.NEXTCATALOG, base);
+ setCatalog(catalog);
+ }
+
+ @Override
+ public String match(String match) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * The Normalizer is responsible for normalizing Public and System Identifiers
+ * as specified in section 6.2, 6.3 and 6.4 of the specification
+ * * <a
+ * href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
+ * XML Catalogs, OASIS Standard V1.1, 7 October 2005</a>.
+ *
+ * @since 9
+ */
+class Normalizer {
+
+ /**
+ * Normalize a public identifier in accordance with section 6.2 of the
+ * Catalog specification.
+ *
+ * <p>
+ * All strings of white space in public identifiers must be normalized to
+ * single space characters (#x20), and leading and trailing white space must
+ * be removed.
+ *
+ * @param publicId The unnormalized public identifier
+ *
+ * @return The normalized identifier
+ */
+ static String normalizePublicId(String publicId) {
+ if (publicId == null) return null;
+
+ StringBuilder sb = new StringBuilder(publicId.length());
+ char last = 'a';
+ for (char c : publicId.toCharArray()) {
+ //skip beginning and duplicate space
+ if ((c == ' ') && (sb.length() == 0 || last == ' ')) {
+ continue;
+ }
+
+ //replace whitespace with space
+ if (c == '\t' || c == '\r' || c == '\n') {
+ if (last != ' ') {
+ sb.append(' ');
+ last = ' ';
+ }
+ } else {
+ sb.append(c);
+ last = c;
+ }
+ }
+ //remove the last space
+ if (last == ' ') {
+ sb.deleteCharAt(sb.length() - 1);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Encode a public identifier as a "publicid" URN.
+ *
+ * @param publicId The unnormalized public identifier
+ *
+ * @return The normalized identifier
+ * @throws CatalogException if encoding failed
+ */
+ static String encodeURN(String publicId) {
+ String urn = normalizePublicId(publicId);
+
+ try {
+ urn = URLEncoder.encode(urn, "UTF-8");
+ urn = urn.replace("::", ";");
+ urn = urn.replace("//", ":");
+ } catch (UnsupportedEncodingException ex) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
+ }
+ return "urn:publicid:" + urn;
+ }
+
+ /**
+ * Decode a "publicid" URN into a public identifier.
+ *
+ * @param urn The urn:publicid: URN
+ *
+ * @return The normalized identifier
+ * @throws CatalogException if decoding failed
+ */
+ static String decodeURN(String urn) {
+ String publicId;
+
+ if (urn != null && urn.startsWith("urn:publicid:")) {
+ publicId = urn.substring(13);
+ } else {
+ return urn;
+ }
+ try {
+ publicId = publicId.replace(":", "//");
+ publicId = publicId.replace(";", "::");
+ publicId = URLDecoder.decode(publicId, "UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
+ }
+
+ return publicId;
+ }
+
+ /**
+ * Perform character normalization on a URI reference.
+ *
+ * @param uriref The URI reference
+ * @return The normalized URI reference
+ */
+ static String normalizeURI(String uriref) {
+ if (uriref == null) {
+ return null;
+ }
+
+ byte[] bytes;
+ uriref = uriref.trim();
+ try {
+ bytes = uriref.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException uee) {
+ // this can't happen
+ return uriref;
+ }
+
+ StringBuilder newRef = new StringBuilder(bytes.length);
+ for (int count = 0; count < bytes.length; count++) {
+ int ch = bytes[count] & 0xFF;
+
+ if ((ch <= 0x20) // ctrl
+ || (ch > 0x7F) // high ascii
+ || (ch == 0x22) // "
+ || (ch == 0x3C) // <
+ || (ch == 0x3E) // >
+ || (ch == 0x5C) // \
+ || (ch == 0x5E) // ^
+ || (ch == 0x60) // `
+ || (ch == 0x7B) // {
+ || (ch == 0x7C) // |
+ || (ch == 0x7D) // }
+ || (ch == 0x7F)) {
+ newRef.append("%").append(String.format("%02X", ch));
+ } else {
+ newRef.append((char) bytes[count]);
+ }
+ }
+
+ return newRef.toString().trim();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/PublicEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a public entry.
+ *
+ * @since 9
+ */
+final class PublicEntry extends BaseEntry {
+ String publicId;
+ URL uri;
+
+ /**
+ * Construct a public entry.
+ * @param publicId The publicId attribute.
+ * @param uri The uri attribute.
+ */
+ public PublicEntry(String base, String publicId, String uri) {
+ super(CatalogEntryType.PUBLIC, base);
+ setPublicId(publicId);
+ setURI(uri);
+ }
+
+ /**
+ * Set the publicId attribute.
+ * @param publicId The publicId attribute value.
+ */
+ public void setPublicId(String publicId) {
+ CatalogMessages.reportNPEOnNull("publicId", publicId);
+ this.publicId = Normalizer.normalizePublicId(publicId);
+ }
+
+ /**
+ * Set the uri attribute. If the value of the uri attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ * The URI reference should not include a fragment identifier.
+ * @param uri The uri attribute value.
+ */
+ public void setURI(String uri) {
+ this.uri = verifyURI("uri", baseURI, uri);
+ }
+
+ /**
+ * Get the publicId attribute.
+ * @return The publicId
+ */
+ public String getPublicId() {
+ return publicId;
+ }
+ /**
+ * Get the uri attribute.
+ * @return The uri attribute value.
+ */
+ public URL getURI() {
+ return uri;
+ }
+
+ @Override
+ public String match(String publicId) {
+ if (this.publicId.equals(publicId)) {
+ return uri.toString();
+ }
+ return null;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/RewriteSystem.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a rewriteSystem entry.
+ *
+ * @since 9
+ */
+final class RewriteSystem extends BaseEntry {
+ String systemIdStartString;
+ URL rewritePrefix;
+
+ /**
+ * Construct a rewriteSystem entry.
+ *
+ * @param systemIdStartString The systemIdStartString attribute.
+ * @param rewritePrefix The rewritePrefix attribute.
+ */
+ public RewriteSystem(String base, String systemIdStartString, String rewritePrefix) {
+ super(CatalogEntryType.REWRITESYSTEM, base);
+ setSystemIdStartString (systemIdStartString);
+ setRewritePrefix(rewritePrefix);
+ }
+
+ /**
+ * Set the systemIdStartString attribute.
+ * @param systemIdStartString The systemIdStartString attribute value.
+ */
+ public void setSystemIdStartString (String systemIdStartString) {
+ CatalogMessages.reportNPEOnNull("systemIdStartString", systemIdStartString);
+ this.systemIdStartString = Normalizer.normalizeURI(systemIdStartString);
+ }
+
+ /**
+ * Set the rewritePrefix attribute. If the value of the rewritePrefix attribute
+ * is relative, it must be made absolute with respect to the base URI currently in effect.
+ * @param rewritePrefix The rewritePrefix attribute value.
+ */
+ public void setRewritePrefix(String rewritePrefix) {
+ this.rewritePrefix = verifyURI("setRewritePrefix", baseURI, rewritePrefix);
+ }
+
+ /**
+ * Get the systemIdStartString attribute.
+ * @return The systemIdStartString
+ */
+ public String getSystemIdStartString () {
+ return systemIdStartString;
+ }
+ /**
+ * Get the rewritePrefix attribute.
+ * @return The rewritePrefix attribute value.
+ */
+ public URL getRewritePrefix() {
+ return rewritePrefix;
+ }
+
+
+ /**
+ * Try to match the specified systemId with the entry. Return the match if it
+ * is successful and the length of the systemIdStartString is longer than the
+ * longest of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of systemIdStartString of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ public String match(String systemId, int currentMatch) {
+ if (systemIdStartString.length() <= systemId.length() &&
+ systemIdStartString.equals(systemId.substring(0, systemIdStartString.length()))) {
+ if (currentMatch < systemIdStartString.length()) {
+ String prefix = rewritePrefix.toExternalForm();
+ if (!prefix.endsWith(SLASH) && !systemId.startsWith(SLASH)) {
+ return prefix + SLASH + systemId.substring(systemIdStartString.length());
+ } else {
+ return prefix + systemId.substring(systemIdStartString.length());
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry.
+ *
+ * @param systemId The systemId to be matched.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/RewriteUri.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a rewriteURI entry.
+ *
+ * @since 9
+ */
+final class RewriteUri extends BaseEntry {
+ String uriStartString;
+ URL rewritePrefix;
+
+ /**
+ * Construct a rewriteURI entry.
+ * @param uriStartString The uriStartString attribute.
+ * @param rewritePrefix The rewritePrefix attribute.
+ */
+ public RewriteUri(String base, String uriStartString, String rewritePrefix) {
+ super(CatalogEntryType.REWRITEURI, base);
+ setURIStartString (uriStartString);
+ setRewritePrefix(rewritePrefix);
+ }
+
+ /**
+ * Set the uriStartString attribute.
+ * @param uriStartString The uriStartString attribute value.
+ */
+ public void setURIStartString (String uriStartString) {
+ CatalogMessages.reportNPEOnNull("uriStartString", uriStartString);
+ this.uriStartString = Normalizer.normalizeURI(uriStartString);
+ }
+
+ /**
+ * Set the rewritePrefix attribute. If the value of the rewritePrefix attribute
+ * is relative, it must be made absolute with respect to the base URI currently in effect.
+ *
+ * @param rewritePrefix The rewritePrefix attribute value.
+ */
+ public void setRewritePrefix(String rewritePrefix) {
+ this.rewritePrefix = verifyURI("setRewritePrefix", baseURI, rewritePrefix);
+ }
+
+ /**
+ * Get the uriStartString attribute.
+ * @return The uriStartString
+ */
+ public String getURIStartString () {
+ return uriStartString;
+ }
+ /**
+ * Get the rewritePrefix attribute.
+ * @return The rewritePrefix attribute value.
+ */
+ public URL getRewritePrefix() {
+ return rewritePrefix;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry. Return the match if it
+ * is successful and the length of the systemIdStartString is longer than the
+ * longest of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of uriStartString of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId, int currentMatch) {
+ if (uriStartString.length() <= systemId.length() &&
+ uriStartString.equals(systemId.substring(0, uriStartString.length()))) {
+ if (currentMatch < uriStartString.length()) {
+ String prefix = rewritePrefix.toExternalForm();
+ if (!prefix.endsWith(SLASH) && !systemId.startsWith(SLASH)) {
+ return prefix + SLASH + systemId.substring(uriStartString.length());
+ } else {
+ return prefix + systemId.substring(uriStartString.length());
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/SystemEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a system entry.
+ *
+ * @since 9
+ */
+final class SystemEntry extends BaseEntry {
+ String systemId;
+ URL uri;
+
+ /**
+ * Construct a system entry.
+ *
+ * @param systemId The systemId attribute.
+ * @param uri The uri attribute.
+ */
+ public SystemEntry(String base, String systemId, String uri) {
+ super(CatalogEntryType.SYSTEM, base);
+ setSystemId(systemId);
+ setURI(uri);
+ }
+
+ /**
+ * Set the systemId attribute.
+ * @param systemId The systemId attribute value.
+ */
+ public void setSystemId(String systemId) {
+ CatalogMessages.reportNPEOnNull("systemId", systemId);
+ this.systemId = Normalizer.normalizeURI(systemId);
+ }
+
+ /**
+ * Set the uri attribute. If the value of the uri attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ * The URI reference should not include a fragment identifier.
+ * @param uri The uri attribute value.
+ */
+ public void setURI(String uri) {
+ this.uri = verifyURI("setURI", baseURI, uri);
+ }
+
+ /**
+ * Get the systemId attribute.
+ * @return The systemId
+ */
+ public String getSystemId() {
+ return systemId;
+ }
+ /**
+ * Get the uri attribute.
+ * @return The uri attribute value.
+ */
+ public URL getURI() {
+ return uri;
+ }
+
+ /**
+ * Try to match the specified string with the entry
+ *
+ * @param systemId The systemId to be matched
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId) {
+ if (this.systemId.equals(systemId)) {
+ return uri.toString();
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/SystemSuffix.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a systemSuffix entry.
+ *
+ * @since 9
+ */
+final class SystemSuffix extends BaseEntry {
+ String systemIdSuffix;
+ URL uri;
+
+ /**
+ * Construct a systemSuffix entry.
+ * @param systemIdSuffix The systemIdSuffix attribute.
+ * @param uri The uri attribute.
+ */
+ public SystemSuffix(String base, String systemIdSuffix, String uri) {
+ super(CatalogEntryType.SYSTEMSUFFIX, base);
+ setSystemIdSuffix(systemIdSuffix);
+ setURI(uri);
+ }
+
+ /**
+ * Set the systemIdSuffix attribute.
+ * @param systemIdSuffix The systemIdSuffix attribute value.
+ */
+ public void setSystemIdSuffix(String systemIdSuffix) {
+ CatalogMessages.reportNPEOnNull("systemIdSuffix", systemIdSuffix);
+ this.systemIdSuffix = Normalizer.normalizeURI(systemIdSuffix);
+ }
+
+ /**
+ * Set the uri attribute. If the value of the uri attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ * The URI reference should not include a fragment identifier.
+ * @param uri The uri attribute value.
+ */
+ public void setURI(String uri) {
+ this.uri = verifyURI("setURI", baseURI, uri);
+ }
+
+ /**
+ * Get the systemIdSuffix attribute.
+ * @return The systemIdSuffix
+ */
+ public String getSystemIdSuffix () {
+ return systemIdSuffix;
+ }
+ /**
+ * Get the uri attribute.
+ * @return The uri attribute value.
+ */
+ public URL getURI() {
+ return uri;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry. Return the match if it
+ * is successful and the length of the systemIdSuffix is longer than the longest
+ * of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of systemIdSuffix of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId, int currentMatch) {
+ if (systemId.endsWith(systemIdSuffix)) {
+ if (currentMatch < systemIdSuffix.length()) {
+ return uri.toString();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Try to match the specified systemId with the entry.
+ *
+ * @param systemId The systemId to be matched.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents an uriEntry entry.
+ *
+ * @since 9
+ */
+final class UriEntry extends BaseEntry {
+ String name;
+ URL uri;
+
+ /**
+ * Construct a group entry.
+ * @param name The name attribute.
+ * @param uri The uri attribute.
+ */
+ public UriEntry(String base, String name, String uri) {
+ super(CatalogEntryType.URI, base);
+ setName(name);
+ setURI(uri);
+ }
+
+ /**
+ * Set the name attribute.
+ * @param name The name attribute value.
+ */
+ public void setName(String name) {
+ CatalogMessages.reportNPEOnNull("name", name);
+ this.name = Normalizer.normalizeURI(name);
+ }
+
+ /**
+ * Set the uri attribute. If the value of the uri attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ *
+ * @param uri The uri attribute value.
+ */
+ public void setURI(String uri) {
+ this.uri = verifyURI("setURI", baseURI, uri);
+ }
+
+ /**
+ * Get the name attribute.
+ * @return The name
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * Get the uri attribute.
+ * @return The uri attribute value.
+ */
+ public URL getURI() {
+ return uri;
+ }
+
+ @Override
+ public String match(String name) {
+ if (this.name.equals(name)) {
+ return uri.toString();
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriSuffix.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import java.net.URL;
+
+/**
+ * Represents a uriSuffix entry.
+ *
+ * @since 9
+ */
+final class UriSuffix extends BaseEntry {
+ String uriSuffix;
+ URL uri;
+
+ /**
+ * Construct a group entry.
+ * @param uriSuffix The uriSuffix attribute.
+ * @param uri The uri attribute.
+ */
+ public UriSuffix(String base, String uriSuffix, String uri) {
+ super(CatalogEntryType.URISUFFIX, base);
+ setURISuffix (uriSuffix);
+ setURI(uri);
+ }
+
+ /**
+ * Set the uriSuffix attribute.
+ * @param uriSuffix The uriSuffix attribute value.
+ */
+ public void setURISuffix(String uriSuffix) {
+ CatalogMessages.reportNPEOnNull("uriSuffix", uriSuffix);
+ this.uriSuffix = Normalizer.normalizeURI(uriSuffix);
+ }
+
+ /**
+ * Set the uri attribute. If the value of the uri attribute is relative, it
+ * must be made absolute with respect to the base URI currently in effect.
+ * The URI reference should not include a fragment identifier.
+ * @param uri The uri attribute value.
+ */
+ public void setURI(String uri) {
+ this.uri = verifyURI("setURI", baseURI, uri);
+ }
+
+ /**
+ * Get the uriSuffix attribute.
+ * @return The uriSuffix
+ */
+ public String getURISuffix () {
+ return uriSuffix;
+ }
+ /**
+ * Get the uri attribute.
+ * @return The uri attribute value.
+ */
+ public String getURI() {
+ return uri.toString();
+ }
+
+ /**
+ * Try to match the specified systemId with the entry. Return the match if it
+ * is successful and the length of the uriSuffix is longer than the longest
+ * of any previous match.
+ *
+ * @param systemId The systemId to be matched.
+ * @param currentMatch The length of uriSuffix of previous match if any.
+ * @return The replacement URI if the match is successful, null if not.
+ */
+ @Override
+ public String match(String systemId, int currentMatch) {
+ if (systemId.endsWith(uriSuffix)) {
+ if (currentMatch < uriSuffix.length()) {
+ return uri.toString();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String match(String systemId) {
+ return match(systemId, 0);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.catalog;
+
+import jdk.xml.internal.SecuritySupport;
+
+/**
+ *
+ * @since 9
+ */
+class Util {
+ /**
+ * Find catalog file paths by reading the system property, and then
+ * jaxp.properties if the system property is not specified.
+ *
+ * @param sysPropertyName the name of system property
+ * @return the catalog file paths, or null if not found.
+ */
+ static public String[] getCatalogFiles(String sysPropertyName) {
+ String value = SecuritySupport.getJAXPSystemProperty(sysPropertyName);
+ if (value != null && !value.equals("")) {
+ return value.split(";");
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/package.html Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation. 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.
+-->
+</head>
+<body bgcolor="white">
+
+ Provides the classes for implementing
+ <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
+ XML Catalogs OASIS Standard V1.1, 7 October 2005</a>.
+
+ <p>
+ Unless otherwise noted, passing a null argument to
+ a constructor or method in any class or interface in this package will
+ cause a <tt>NullPointerException</tt> to be thrown.
+ </p>
+
+@since 9
+
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.xml.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+/**
+ * This class contains utility methods for reading resources in the JAXP packages
+ */
+public class SecuritySupport {
+ /**
+ * Cache for properties in java.home/conf/jaxp.properties
+ */
+ static final Properties cacheProps = new Properties();
+
+ /**
+ * Flag indicating whether java.home/conf/jaxp.properties has been read
+ */
+ static volatile boolean firstTime = true;
+
+ private SecuritySupport() {}
+
+ public static String getErrorMessage(Locale locale, String bundle, String key,
+ Object[] arguments) {
+ ResourceBundle rb;
+ if (locale != null) {
+ rb = ResourceBundle.getBundle(bundle,locale);
+ } else {
+ rb = ResourceBundle.getBundle(bundle);
+ }
+
+ String msg = rb.getString(key);
+ if (arguments != null) {
+ msg = MessageFormat.format(msg, arguments);
+ }
+ return msg;
+ }
+
+ /**
+ * Reads JAXP system property with privilege
+ *
+ * @param propName the name of the property
+ * @return the value of the property
+ */
+ public static String getSystemProperty(final String propName) {
+ return
+ AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> (String)System.getProperty(propName));
+ }
+
+ /**
+ * Reads JAXP system property in this order: system property,
+ * $java.home/conf/jaxp.properties if the system property is not specified
+ *
+ * @param propName the name of the property
+ * @return the value of the property
+ */
+ public static String getJAXPSystemProperty(String propName) {
+ String value = getSystemProperty(propName);
+ if (value == null) {
+ value = readJAXPProperty(propName);
+ }
+ return value;
+ }
+
+ /**
+ * Reads the specified property from $java.home/conf/jaxp.properties
+ *
+ * @param propName the name of the property
+ * @return the value of the property
+ */
+ public static String readJAXPProperty(String propName) {
+ String value = null;
+ InputStream is = null;
+ try {
+ if (firstTime) {
+ synchronized (cacheProps) {
+ if (firstTime) {
+ String configFile = getSystemProperty("java.home") + File.separator
+ + "conf" + File.separator + "jaxp.properties";
+ File f = new File(configFile);
+ if (getFileExists(f)) {
+ is = getFileInputStream(f);
+ cacheProps.load(is);
+ }
+ firstTime = false;
+ }
+ }
+ }
+ value = cacheProps.getProperty(propName);
+
+ } catch (IOException ex) {
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ex) {}
+ }
+ }
+
+ return value;
+ }
+
+//------------------- private methods ---------------------------
+ static boolean getFileExists(final File f) {
+ return (AccessController.doPrivileged((PrivilegedAction<Boolean>) ()
+ -> f.exists() ? Boolean.TRUE : Boolean.FALSE));
+ }
+
+ static FileInputStream getFileInputStream(final File file)
+ throws FileNotFoundException {
+ try {
+ return AccessController.doPrivileged((PrivilegedExceptionAction<FileInputStream>) ()
+ -> new FileInputStream(file));
+ } catch (PrivilegedActionException e) {
+ throw (FileNotFoundException) e.getException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/CatalogReferCircularityTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+
+import javax.xml.catalog.CatalogException;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Via nextCatalog entry, the catalog reference chain may be
+ * a (partial) closed circuit. For instance, a catalog may use itself
+ * as an additional catalog specified in its own nextCatalog entry.
+ * This case tests if the implementation handles this issue.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ */
+public class CatalogReferCircularityTest {
+
+ @Test(dataProvider = "catalogName",
+ expectedExceptions = CatalogException.class)
+ public void testReferCircularity(String catalogFile) {
+ catalogResolver(catalogFile).resolveEntity(null,
+ "http://remote/dtd/ghost/docGhost.dtd");
+ }
+
+ @DataProvider(name = "catalogName")
+ private Object[][] catalogName() {
+ return new Object[][] {
+ // This catalog defines itself as next catalog.
+ { "catalogReferCircle-itself.xml" },
+
+ // This catalog defines catalogReferCircle-right.xml as its next
+ // catalog. And catalogReferCircle-right.xml also defines
+ // catalogReferCircle-left.xml as its next catalog, too.
+ { "catalogReferCircle-left.xml" } };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DefaultFeaturesTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogFeatures.Feature;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary This case tests if the default feature values are expected.
+ */
+public class DefaultFeaturesTest {
+
+ private CatalogFeatures defaultFeature;
+
+ @BeforeClass
+ public void init() {
+ defaultFeature = CatalogFeatures.defaults();
+ }
+
+ @Test(dataProvider="feature-value")
+ public void testDefaultFeatures(Feature feature, String expected) {
+ String featureValue = defaultFeature.get(feature);
+ if (expected != null) {
+ Assert.assertEquals(featureValue, expected);
+ } else {
+ Assert.assertNull(featureValue);
+ }
+ }
+
+ @DataProvider(name = "feature-value")
+ private Object[][] data() {
+ return new Object[][] {
+ { Feature.FILES, null },
+ { Feature.PREFER, CatalogTestUtils.PREFER_PUBLIC },
+ { Feature.DEFER, CatalogTestUtils.DEFER_TRUE },
+ { Feature.RESOLVE, CatalogTestUtils.RESOLVE_STRICT } };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.DEFER_FALSE;
+import static catalog.CatalogTestUtils.DEFER_TRUE;
+import static catalog.CatalogTestUtils.getCatalogPath;
+import static javax.xml.catalog.CatalogFeatures.Feature.DEFER;
+import static javax.xml.catalog.CatalogManager.catalog;
+
+import java.lang.reflect.Method;
+
+import javax.xml.catalog.Catalog;
+import javax.xml.catalog.CatalogFeatures;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary This case tests whether the catalogs specified in delegateSystem,
+ * delegatePublic, delegateURI and nextCatalog entries are used lazily
+ * in resolution via defer feature.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ */
+public class DeferFeatureTest {
+
+ @Test(dataProvider = "catalog-countOfLoadedCatalogFile")
+ public void testDeferFeature(Catalog catalog, int catalogCount)
+ throws Exception {
+ Assert.assertEquals(loadedCatalogCount(catalog), catalogCount);
+ }
+
+ @DataProvider(name = "catalog-countOfLoadedCatalogFile")
+ private Object[][] data() {
+ return new Object[][] {
+ // This catalog specifies null catalog explicitly,
+ // and the count of loaded catalogs should be 0.
+ { createCatalog(null), 0 },
+
+ // This catalog specifies null catalog implicitly,
+ // and the count of loaded catalogs should be 0.
+ { createCatalog(CatalogFeatures.defaults()), 0 },
+
+ // This catalog loads null catalog with true DEFER,
+ // and the count of loaded catalogs should be 0.
+ { createCatalog(createDeferFeature(DEFER_TRUE)), 0 },
+
+ // This catalog loads null catalog with false DEFER.
+ // It should load all of none-current catalogs and the
+ // count of loaded catalogs should be 3.
+ { createCatalog(createDeferFeature(DEFER_FALSE)), 3 } };
+ }
+
+ private CatalogFeatures createDeferFeature(String defer) {
+ return CatalogFeatures.builder().with(DEFER, defer).build();
+ }
+
+ private Catalog createCatalog(CatalogFeatures feature) {
+ return catalog(feature, getCatalogPath("deferFeature.xml"));
+ }
+
+ private int loadedCatalogCount(Catalog catalog) throws Exception {
+ Method method = catalog.getClass().getDeclaredMethod(
+ "loadedCatalogCount");
+ method.setAccessible(true);
+ return (int) method.invoke(catalog);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DelegatePublicTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+import static catalog.ResolutionChecker.expectExceptionOnPubId;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from DelegatePublic entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class DelegatePublicTest {
+
+ @Test(dataProvider = "publicId-matchedUri")
+ public void testMatch(String publicId, String matchedUri) {
+ checkPubIdResolution(createResolver(), publicId, matchedUri);
+ }
+
+ @DataProvider(name = "publicId-matchedUri")
+ private Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified public id is defined in
+ // a delegate catalog file of the current catalog file.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/dtd/docAlicePub.dtd" },
+
+ // The current catalog file defines two delegatePublic entries
+ // with the same publicIdStartString, and both of them match the
+ // specified public id. But the matched URI should be in the
+ // delegate catalog file, which is defined in the upper
+ // delegatePublic entry.
+ { "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://local/base/dtd/bob/docBobPub.dtd" },
+
+ // The current catalog file defines two delegatePublic entries,
+ // and both of them match the specified public id. But the
+ // matched URI should be in the delegate catalog file, which is
+ // defined in the longest matched delegatePublic entry.
+ { "-//REMOTE//DTD CARL DOCCARL XML//EN",
+ "http://local/base/dtd/carl/docCarlPub.dtd" } };
+ }
+
+ @Test(dataProvider = "publicId-expectedExceptionClass")
+ public void testException(String publicId,
+ Class<? extends Throwable> expectedExceptionClass) {
+ expectExceptionOnPubId(createResolver(), publicId,
+ expectedExceptionClass);
+ }
+
+ @DataProvider(name = "publicId-expectedExceptionClass")
+ private Object[][] dataOnException() {
+ return new Object[][] {
+ // The matched delegatePublic entry of the specified public id
+ // defines a non-existing delegate catalog file. That should
+ // raise a RuntimeException.
+ { "-//REMOTE//DTD DAVID DOCDAVID XML//EN",
+ RuntimeException.class },
+
+ // There's no match of the specified public id in the catalog
+ // structure. That should raise a CatalogException.
+ { "-//REMOTE//DTD GHOST DOCGHOST XML//EN",
+ CatalogException.class } };
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("delegatePublic.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DelegateSystemTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.expectExceptionOnSysId;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from delegateSystem entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class DelegateSystemTest {
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkSysIdResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ private Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified system id is defined in
+ // a delegate catalog file of the current catalog file.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/alice/docAliceDS.dtd" },
+
+ // The current catalog file defines two delegateSystem entries
+ // with the same systemIdStartString, and both of them match the
+ // specified system id. But the matched URI should be in the
+ // delegate catalog file, which is defined in the upper
+ // delegateSystem entry.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/bob/docBobDS.dtd" },
+
+ // The current catalog file defines two delegateSystem entries,
+ // and both of them match the specified system id. But the
+ // matched URI should be in the delegate catalog file, which is
+ // defined in the longest matched delegateSystem entry.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/base/dtd/carl/docCarlDS.dtd"} };
+ }
+
+ @Test(dataProvider = "systemId-expectedExceptionClass")
+ public void testException(String systemId,
+ Class<? extends Throwable> expectedExceptionClass) {
+ expectExceptionOnSysId(createResolver(), systemId,
+ expectedExceptionClass);
+ }
+
+ @DataProvider(name = "systemId-expectedExceptionClass")
+ private Object[][] dataOnException() {
+ return new Object[][] {
+ // The matched delegateSystem entry of the specified system id
+ // defines a non-existing delegate catalog file. That should
+ // raise a RuntimeException.
+ { "http://remote/dtd/david/docDavidDS.dtd",
+ RuntimeException.class },
+
+ // There's no match of the specified system id in the catalog
+ // structure. That should raise a CatalogException.
+ { "http://ghost/xml/dtd/ghost/docGhostDS.dtd",
+ CatalogException.class } };
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("delegateSystem.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DelegateUriTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkUriResolution;
+import static catalog.ResolutionChecker.expectExceptionOnUri;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from delegateURI entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class DelegateUriTest {
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatch(String uri, String matchedUri) {
+ checkUriResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ private Object[][] data() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is defined in
+ // a delegate catalog file of the current catalog file.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/alice/docAliceDU.dtd" },
+
+ // The current catalog file defines two delegateURI entries
+ // with the same uriStartString, and both of them match the
+ // specified URI reference. But the matched URI should be in
+ // the delegate catalog file, which is defined in the upper
+ // delegateURI entry.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/bob/docBobDU.dtd" },
+
+ // The current catalog file defines two delegateURI entries,
+ // and both of them match the specified URI reference. But the
+ // matched URI should be in the delegate catalog file, which is
+ // defined in the longest matched delegateURI entry.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/base/dtd/carl/docCarlDU.dtd"} };
+ }
+
+ @Test(dataProvider = "uri-expectedExceptionClass")
+ public void testException(String uri,
+ Class<? extends Throwable> expectedExceptionClass) {
+ expectExceptionOnUri(createResolver(), uri, expectedExceptionClass);
+ }
+
+ @DataProvider(name = "uri-expectedExceptionClass")
+ private Object[][] dataOnException() {
+ return new Object[][] {
+ // The matched delegateURI entry of the specified URI reference
+ // defines a non-existing delegate catalog file. That should
+ // raise a RuntimeException.
+ { "http://remote/dtd/david/docDavidDU.dtd",
+ RuntimeException.class },
+
+ // There's no match of the specified URI reference in the
+ // catalog structure. That should raise a CatalogException.
+ { "http://ghost/xml/dtd/ghost/docGhostDS.dtd",
+ CatalogException.class } };
+ }
+
+ private CatalogUriResolver createResolver() {
+ return catalogUriResolver("delegateUri.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/GroupTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from system, public and uri entries respectively,
+ * and some of the entries are enclosed by group entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class GroupTest {
+
+ private static final String CATALOG_GROUP = "group.xml";
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatchOnSysId(String uri, String matchedUri) {
+ checkSysIdResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ private Object[][] dataOnSysId() {
+ return new Object[][] {
+ // The matched URI of the specified system id is enclosed by a
+ // group entry.
+ { "http://remote/dtd/sys/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceSys.dtd" },
+
+ // The matched URI of the specified system id is enclosed by a
+ // group entry, which defines another base.
+ { "http://remote/dtd/sys/bob/docBob.dtd",
+ "http://local/bobBase/dtd/docBobSys.dtd" },
+
+ // The catalog file defines a set of system entries. Some of
+ // them are enclosed by a group entry, and others are out of the
+ // group entry. All of them can match the specified system id.
+ // But the returned matched URI should be in the first one.
+ { "http://remote/dtd/sys/carl/docCarl.dtd",
+ "http://local/base/dtd/docCarlSys1.dtd" } };
+ }
+
+ @Test(dataProvider = "publicId-matchedUri")
+ public void testMatchOnPubId(String uri, String matchedUri) {
+ checkPubIdResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "publicId-matchedUri")
+ private Object[][] dataOnPubId() {
+ return new Object[][] {
+ // The matched URI of the specified public id is enclosed by a
+ // group entry.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/base/dtd/docAlicePub.dtd" },
+
+ // The matched URI of the specified public id is enclosed by a
+ // group entry, which defines another base.
+ { "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://local/bobBase/dtd/docBobPub.dtd" },
+
+ // The catalog file defines a set of public entries. Some of
+ // them are enclosed by a group entry, and others are out of the
+ // group entry. All of them can match the specified public id.
+ // But the returned matched URI should be in the first one.
+ { "-//REMOTE//DTD CARL DOCCARL XML//EN",
+ "http://local/base/dtd/docCarlPub1.dtd" } };
+ }
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatchOnUri(String uri, String matchedUri) {
+ checkUriResolution(catalogUriResolver(CATALOG_GROUP), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ private Object[][] dataOnUri() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is enclosed by
+ // a group entry.
+ { "http://remote/dtd/uri/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceURI.dtd" },
+
+ // The matched URI of the specified URI reference is enclosed by
+ // a group entry, which defines another base.
+ { "http://remote/dtd/uri/bob/docBob.dtd",
+ "http://local/bobBase/dtd/docBobURI.dtd" },
+
+ // The catalog file defines a set of uri entries. Some of
+ // them are enclosed by a group entry, and others are out of the
+ // group entry. All of them can match the specified URI reference.
+ // But the returned matched URI should be in the first one.
+ { "http://remote/dtd/uri/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceURI.dtd" } };
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver(CATALOG_GROUP);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/LoadCatalogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_PUBLIC;
+import static catalog.CatalogTestUtils.CATALOG_SYSTEM;
+import static catalog.CatalogTestUtils.CATALOG_URI;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary When catalog resolver loads catalog files, the current catalog file
+ * and the catalog files specified by the nextCatalog entries may not
+ * accessible. This case tests how does the resolver handle this issue.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class LoadCatalogTest {
+
+ private static final String CATALOG_LOADCATALOGFILES = "loadCatalogFiles.xml";
+ private static final String CATALOG_DUMMY = "dummy.xml";
+
+ private static final String ID_ALICE = "http://remote/dtd/alice/docAlice.dtd";
+ private static final String ID_DUMMY = "http://remote/dtd/doc.dtd";
+
+ @Test(dataProvider = "entityResolver")
+ public void testMatchOnEntityResolver(CatalogResolver resolver) {
+ checkSysIdResolution(resolver, ID_ALICE,
+ "http://local/dtd/docAliceSys.dtd");
+ }
+
+ @DataProvider(name = "entityResolver")
+ private Object[][] entityResolver() {
+ return new Object[][] {
+ // This EntityResolver loads multiple catalog files one by one.
+ // All of the files are available.
+ { catalogResolver(CATALOG_PUBLIC, CATALOG_URI,
+ CATALOG_SYSTEM) },
+
+ // This EntityResolver loads multiple catalog files one by one,
+ // but the middle one isn't existing.
+ { catalogResolver(CATALOG_PUBLIC, CATALOG_DUMMY,
+ CATALOG_SYSTEM) } };
+ }
+
+ @Test(dataProvider = "uriResolver")
+ public void testMatchOnUriResolver(CatalogUriResolver resolver) {
+ checkUriResolution(resolver, ID_ALICE,
+ "http://local/dtd/docAliceURI.dtd");
+ }
+
+ @DataProvider(name = "uriResolver")
+ private Object[][] uriResolver() {
+ return new Object[][] {
+ // This URIResolver loads multiple catalog files one by one.
+ // All of the files are available.
+ { catalogUriResolver(CATALOG_PUBLIC, CATALOG_SYSTEM,
+ CATALOG_URI) },
+
+ // This URIResolver loads multiple catalog files one by one,
+ // but the middle one isn't existing.
+ { catalogUriResolver(CATALOG_PUBLIC, CATALOG_DUMMY,
+ CATALOG_URI) } };
+ }
+
+ @Test(dataProvider = "catalogName",
+ expectedExceptions = CatalogException.class)
+ public void testExceptionOnEntityResolver(String[] catalogName) {
+ catalogResolver(catalogName).resolveEntity(null, ID_DUMMY);
+ }
+
+ @Test(dataProvider = "catalogName",
+ expectedExceptions = CatalogException.class)
+ public void testExceptionOnUriResolver(String[] catalogName) {
+ catalogUriResolver(catalogName).resolve(ID_DUMMY, null);
+ }
+
+ @DataProvider(name = "catalogName")
+ private Object[][] catalogName() {
+ return new Object[][] {
+ // This catalog file set includes null catalog files.
+ { (String[]) null },
+
+ // This catalog file set includes one catalog file, but this
+ // catalog defines a non-existing next catalog.
+ { new String[] { CATALOG_LOADCATALOGFILES } } };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/NextCatalogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from system, public and uri entries respectively,
+ * but some of the entries are defined in none-current catalog files.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class NextCatalogTest {
+
+ private static final String CATALOG_NEXTCATALOGLEFT
+ = "nextCatalog-left.xml";
+ private static final String CATALOG_NEXTCATALOGRIGHT
+ = "nextCatalog-right.xml";
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testNextCatalogOnSysId(String sytemId, String matchedUri) {
+ checkSysIdResolution(createEntityResolver(), sytemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ private Object[][] dataOnSysId() {
+ return new Object[][] {
+ // This matched URI of the specified system id is defined in a
+ // next catalog file.
+ { "http://remote/dtd/sys/docAlice.dtd",
+ "http://local/base/dtd/docAliceNextLeftSys.dtd" },
+
+ // There are two matches of the specified system id. One is in
+ // the current catalog file, and the other is in a next catalog
+ // file. But finally, the returned matched URI is the one in the
+ // current catalog file.
+ { "http://remote/dtd/sys/docBob.dtd",
+ "http://local/base/dtd/docBobLeftSys.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // two-level next catalog file.
+ { "http://remote/dtd/sys/docCarl.dtd",
+ "http://local/base/dtd/docCarlSys.dtd" },
+
+ // Multiple catalog files, which are defined as next catalog,
+ // have the matched system entries of the specified system id.
+ // But finally, the returned matched URI is the first found.
+ { "http://remote/dtd/sys/docDuplicate.dtd",
+ "http://local/base/dtd/docDuplicateLeftSys.dtd" } };
+ }
+
+ @Test(dataProvider = "publicId-matchedUri")
+ public void testNextCatalogOnPubId(String publicId, String matchedUri) {
+ checkPubIdResolution(createEntityResolver(), publicId, matchedUri);
+ }
+
+ @DataProvider(name = "publicId-matchedUri")
+ private Object[][] dataOnPubId() {
+ return new Object[][] {
+ // This matched URI of the specified public id is defined in a
+ // next catalog file.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/base/dtd/docAliceNextLeftPub.dtd" },
+
+ // There are two matches of the specified public id. One is in
+ // the current catalog file, and the other is in a next catalog
+ // file. But finally, the returned matched URI is the one in the
+ // current catalog file.
+ { "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://local/base/dtd/docBobLeftPub.dtd" },
+
+ // The matched URI of the specified public id is defined in a
+ // two-level next catalog file.
+ { "-//REMOTE//DTD CARL DOCCARL XML//EN",
+ "http://local/base/dtd/docCarlPub.dtd" },
+
+ // Multiple catalog files, which are defined as next catalog,
+ // have the matched public entries of the specified public id.
+ // But finally, the returned matched URI is the first found.
+ { "-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN",
+ "http://local/base/dtd/docDuplicateLeftPub.dtd" } };
+ }
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testNextCatalogOnUri(String uri, String matchedUri) {
+ checkUriResolution(createUriResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ private Object[][] dataOnUri() {
+ return new Object[][] {
+ // This matched URI of the specified URI reference is defined in
+ // a next catalog file.
+ { "http://remote/dtd/uri/docAlice.dtd",
+ "http://local/base/dtd/docAliceNextLeftURI.dtd" },
+
+ // There are two matches of the specified URI reference. One is
+ // in the current catalog file, and the other is in a next
+ // catalog file. But finally, the returned matched URI is the
+ // one in the current catalog file.
+ { "http://remote/dtd/uri/docBob.dtd",
+ "http://local/base/dtd/docBobLeftURI.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a two-level next catalog file.
+ { "http://remote/dtd/uri/docCarl.dtd",
+ "http://local/base/dtd/docCarlURI.dtd" },
+
+ // Multiple catalog files, which are defined as next catalog,
+ // have the matched uri entries of the specified URI reference.
+ // But finally, the returned matched URI is the first found.
+ { "http://remote/dtd/uri/docDuplicate.dtd",
+ "http://local/base/dtd/docDuplicateLeftURI.dtd" } };
+ }
+
+ private CatalogResolver createEntityResolver() {
+ return catalogResolver(CATALOG_NEXTCATALOGLEFT,
+ CATALOG_NEXTCATALOGRIGHT);
+ }
+
+ private CatalogUriResolver createUriResolver() {
+ return catalogUriResolver(CATALOG_NEXTCATALOGLEFT,
+ CATALOG_NEXTCATALOGRIGHT);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/NormalizationTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Before matching identifiers and URI references, it has to normalize
+ * the passed identifiers and URI references. And then the catalog
+ * resolver uses the normalized stuff to search the counterparts in
+ * catalog files.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class NormalizationTest {
+
+ private static final String CATALOG_NORMALIZATION = "normalization.xml";
+
+ @Test(dataProvider = "systemId_uri-matchedUri")
+ public void testNormalizationOnSysId(String sytemId, String matchedUri) {
+ checkSysIdResolution(createEntityResolver(), sytemId, matchedUri);
+ }
+
+ @Test(dataProvider = "publicId-matchedUri")
+ public void testNormalizationOnPubId(String publicId, String matchedUri) {
+ checkPubIdResolution(createEntityResolver(), publicId, matchedUri);
+ }
+
+ @Test(dataProvider = "systemId_uri-matchedUri")
+ public void testNormalizationOnUri(String uri, String matchedUri) {
+ checkUriResolution(createUriResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "systemId_uri-matchedUri")
+ private Object[][] dataOnSysIdAndUri() {
+ return new Object[][] {
+ // The specified system id/URI reference contains spaces. And
+ // the counterparts in system/uri entries also contain spaces.
+ { " http://remote/dtd/alice/docAlice.dtd ",
+ "http://local/base/dtd/docAliceSys.dtd" },
+
+ // The specified system id/URI reference doesn't contain space.
+ // But the counterparts in system/uri entries contain spaces.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceSys.dtd" },
+
+ // The specified system id/URI reference contains special chars.
+ { "http://remote/dtd/bob/docBob<>\\^`{|}.dtd",
+ "http://local/base/dtd/docBobSys.dtd" },
+
+ // The specified system identifier/uri contains normalized chars.
+ { "http://remote/dtd/bob/docBob%3C%3E%5C%5E%60%7B%7C%7D.dtd",
+ "http://local/base/dtd/docBobSys.dtd" } };
+ }
+
+ @DataProvider(name = "publicId-matchedUri")
+ private Object[][] dataOnPubId() {
+ return new Object[][] {
+ // The specified public id contains spaces. And the counterparts
+ // in public entry also contains spaces.
+ { " -//REMOTE//DTD ALICE DOCALICE XML//EN ",
+ "http://local/base/dtd/docAlicePub.dtd" },
+
+ // The specified public id doesn't contain space. But the
+ // counterpart in public entry contains spaces.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/base/dtd/docAlicePub.dtd" },
+
+ // The specified public id contains spaces.
+ { " -//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://local/base/dtd/docBobPub.dtd" } };
+ }
+
+ private CatalogResolver createEntityResolver() {
+ return catalogResolver(CATALOG_NORMALIZATION);
+ }
+
+ private CatalogUriResolver createUriResolver() {
+ return catalogUriResolver(CATALOG_NORMALIZATION);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/PreferFeatureTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.PREFER_PUBLIC;
+import static catalog.CatalogTestUtils.PREFER_SYSTEM;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static javax.xml.catalog.CatalogFeatures.Feature.PREFER;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary This case tests how does the feature affect the catalog resolution,
+ * and tests the priority between this feature and attribute prefer
+ * in catalog file.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ */
+public class PreferFeatureTest {
+
+ @Test(dataProvider = "prefer-publicId-systemId",
+ expectedExceptions = CatalogException.class)
+ public void testPreferFeature(String prefer, String systemId,
+ String publicId) {
+ createResolver(prefer).resolveEntity(systemId, publicId);
+ }
+
+ @DataProvider(name = "prefer-publicId-systemId")
+ private Object[][] data() {
+ return new Object[][] {
+ // The feature prefer is system. There's a match for the
+ // specified public id, and no match for the specified system id.
+ // But the resolver cannot find the expected match, and raises a
+ // CatalogException.
+ { PREFER_SYSTEM, "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://remote/dtd/alice/docAliceDummy.dtd" },
+
+ // The feature prefer is public, and the prefer attribute of a
+ // group entry is system. There's a match for the specified
+ // public id, and no match for the specified system id. But the
+ // resolver still cannot find the expected match, and raises a
+ // CatalogException.
+ { PREFER_PUBLIC, "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://remote/dtd/bob/docBobDummy.dtd"} };
+ }
+
+ private CatalogResolver createResolver(String prefer) {
+ return catalogResolver(
+ CatalogFeatures.builder().with(PREFER, prefer).build(),
+ "preferFeature.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/PreferTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkExtIdResolution;
+
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from system and public family entries, which
+ * specify the prefer attribute. It tests how does the prefer attribute
+ * affect the resolution procedure. The test rule is based on OASIS
+ * Standard V1.1 section 4.1.1. "The prefer attribute".
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class PreferTest {
+
+ @Test(dataProvider = "publicId-systemId-matchedUri")
+ public void testPrefer(String publicId, String systemId,
+ String expected) {
+ checkExtIdResolution(createResolver(), publicId, systemId, expected);
+ }
+
+ @DataProvider(name = "publicId-systemId-matchedUri")
+ private Object[][] data() {
+ return new Object[][] {
+ // The prefer attribute is public. Both of the specified public
+ // id and system id have matches in the catalog file. But
+ // finally, the returned URI is the system match.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceSys.dtd" },
+
+ // The prefer attribute is public, and only the specified system
+ // id has match. The returned URI is the system match.
+ { "-//REMOTE//DTD ALICE DOCALICEDUMMY XML//EN",
+ "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceSys.dtd"},
+
+ // The prefer attribute is public, and only the specified public
+ // id has match. The returned URI is the system match.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://remote/dtd/alice/docAliceDummy.dtd",
+ "http://local/base/dtd/docAlicePub.dtd" },
+
+ // The prefer attribute is system, and both of the specified
+ // system id and public id have matches. But the returned URI is
+ // the system match.
+ { "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobSys.dtd" },
+
+ // The prefer attribute is system, and only system id has match.
+ // The returned URI is the system match.
+ { "-//REMOTE//DTD BOB DOCBOBDUMMY XML//EN",
+ "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobSys.dtd" } };
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("prefer.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/PublicFamilyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from public and delegatePublic entries.
+ * It tests the resolution priorities among the public family entries.
+ * The test rule is based on OASIS Standard V1.1 section 7.1.2.
+ * "Resolution of External Identifiers".
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class PublicFamilyTest {
+
+ /*
+ * Gets the best match from public and delegatePublic entries.
+ * The match in public entry is prior to the match in delegatePublic entry.
+ */
+ @Test
+ public void testMatch() {
+ checkPubIdResolution(createResolver(),
+ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/base/dtd/docAlicePub.dtd");
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatched() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("publicFamily.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/PublicTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_PUBLIC;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from public entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class PublicTest {
+
+ @Test(dataProvider = "publicId-matchedUri")
+ public void testPublic(String publicId, String matchedUri) {
+ checkPubIdResolution(createResolver(), publicId, matchedUri);
+ }
+
+ @DataProvider(name = "publicId-matchedUri")
+ public Object[][] data() {
+ return new Object[][] {
+ // The matched URI of the specified public id is defined in a
+ // public entry. The match is an absolute path.
+ { "-//REMOTE//DTD ALICE DOCALICE XML//EN",
+ "http://local/dtd/docAlicePub.dtd" },
+
+ // The matched URI of the specified public id is defined in a
+ // public entry. But the match isn't an absolute path, so the
+ // returned URI should include the base, which is defined by the
+ // catalog file, as the prefix.
+ { "-//REMOTE//DTD BOB DOCBOB XML//EN",
+ "http://local/base/dtd/docBobPub.dtd" },
+
+ // The matched URI of the specified public id is defined in a
+ // public entry. The match isn't an absolute path, and the
+ // public entry defines alternative base. So the returned URI
+ // should include the alternative base.
+ { "-//REMOTE//DTD CARL DOCCARL XML//EN",
+ "http://local/carlBase/dtd/docCarlPub.dtd" },
+
+ // The catalog file defines two public entries, and both of them
+ // match the specified public id. But the first matched URI
+ // should be returned.
+ { "-//REMOTE//DTD DAVID DOCDAVID XML//EN",
+ "http://local/base/dtd/docDavidPub1.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver(CATALOG_PUBLIC);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/ResolveFeatureTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_SYSTEM;
+import static catalog.CatalogTestUtils.CATALOG_URI;
+import static catalog.CatalogTestUtils.RESOLVE_CONTINUE;
+import static catalog.CatalogTestUtils.RESOLVE_IGNORE;
+import static catalog.CatalogTestUtils.RESOLVE_STRICT;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+import static javax.xml.catalog.CatalogFeatures.builder;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary This case tests how does resolve feature affect the catalog
+ * resolution.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class ResolveFeatureTest {
+
+ /*
+ * For strict external identifier resolution, if no match is found,
+ * it should throw CatalogException.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testStrictResolutionOnEntityResolver() {
+ createEntityResolver(RESOLVE_STRICT).resolveEntity(null,
+ "http://remote/dtd/alice/docAliceDummy.dtd");
+ }
+
+ /*
+ * For strict URI reference resolution, if no match is found,
+ * it should throw CatalogException.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testStrictResolutionOnUriResolver() {
+ createUriResolver(RESOLVE_STRICT).resolve(
+ "http://remote/dtd/alice/docAliceDummy.dtd", null);
+ }
+
+ /*
+ * For continue external identifier resolution, if no match is found,
+ * it should continue the process.
+ */
+ @Test
+ public void testContinueResolutionOnEntityResolver() {
+ CatalogResolver resolver = createEntityResolver(RESOLVE_CONTINUE);
+ resolver.resolveEntity(null, "http://remote/dtd/bob/docBobDummy.dtd");
+ checkSysIdResolution(resolver, "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobSys.dtd");
+ }
+
+ /*
+ * For continue URI reference resolution, if no match is found,
+ * it should continue the process.
+ */
+ @Test
+ public void testContinueResolutionOnUriResolver() {
+ CatalogUriResolver resolver = createUriResolver(RESOLVE_CONTINUE);
+ resolver.resolve("http://remote/dtd/bob/docBobDummy.dtd", null);
+ checkUriResolution(resolver, "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobURI.dtd");
+ }
+
+ /*
+ * For ignore external identifier resolution, if no match is found,
+ * it should break the process and return null.
+ */
+ @Test
+ public void testIgnoreResolutionOnEntityResolver() {
+ checkSysIdResolution(createEntityResolver(RESOLVE_IGNORE),
+ "http://remote/dtd/carl/docCarlDummy.dtd", null);
+ }
+
+ /*
+ * For ignore URI reference resolution, if no match is found,
+ * it should break the process and return null.
+ */
+ @Test
+ public void testIgnoreResolutionOnUriResolver() {
+ checkUriResolution(createUriResolver(RESOLVE_IGNORE),
+ "http://remote/dtd/carl/docCarlDummy.dtd", null);
+ }
+
+ private CatalogResolver createEntityResolver(String resolve) {
+ return catalogResolver(createFeature(resolve), CATALOG_SYSTEM);
+ }
+
+ private CatalogUriResolver createUriResolver(String resolve) {
+ return catalogUriResolver(createFeature(resolve), CATALOG_URI);
+ }
+
+ private CatalogFeatures createFeature(String resolve) {
+ return builder().with(Feature.RESOLVE, resolve).build();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/RewriteSystemTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from rewriteSystem entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class RewriteSystemTest {
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkSysIdResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified system id is defined in a
+ // rewriteSystem entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/alice/rs/docAlice.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // rewriteSystem entry. The match isn't an absolute path.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/bob/rs/docBob.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // rewriteSystem entry. The match isn't an absolute path, and
+ // the rewriteSystem entry defines alternative base. So the
+ // returned URI should include the alternative base.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/carlBase/dtd/carl/rs/docCarl.dtd" },
+
+ // The catalog file defines two rewriteSystem entries, and both
+ // of them match the specified system id. But the first matched
+ // URI should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/david1/rs/docDavid.dtd" },
+
+ // The catalog file defines two rewriteSystem entries, and both
+ // of them match the specified system id. But the longest match
+ // should be used.
+ { "http://remote/dtd/ella/docElla.dtd",
+ "http://local/base/dtd/ella/rs/docElla.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("rewriteSystem.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/RewriteUriTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from rewriteURI entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class RewriteUriTest {
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatch(String uri, String matchedUri) {
+ checkUriResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is defined in
+ // a rewriteURI entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/alice/ru/docAlice.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a rewriteURI entry. The match isn't an absolute path.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/bob/ru/docBob.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a rewriteURI entry. The match isn't an absolute path, and the
+ // rewriteURI entry defines alternative base. So the returned
+ // URI should include the alternative base.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/carlBase/dtd/carl/ru/docCarl.dtd" },
+
+ // The catalog file defines two rewriteURI entries, and both of
+ // them match the specified URI reference. But the first matched
+ // URI should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/david1/ru/docDavid.dtd" },
+
+ // The catalog file defines two rewriteURI entries, and both
+ // of them match the specified URI reference. But the longest
+ // match should be used.
+ { "http://remote/dtd/ella/docElla.dtd",
+ "http://local/base/dtd/ella/ru/docElla.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogUriResolver createResolver() {
+ return catalogUriResolver("rewriteUri.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.FEATURE_FILES;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.CatalogTestUtils.getCatalogPath;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+import static javax.xml.catalog.CatalogFeatures.builder;
+import static javax.xml.catalog.CatalogFeatures.Feature.FILES;
+
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary This case tests how to specify the catalog files.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class SpecifyCatalogTest {
+
+ private static final String ID_URI = "http://remote/dtd/uri/doc.dtd";
+ private static final String ID_SYS = "http://remote/dtd/sys/doc.dtd";
+
+ private static final CatalogFeatures FILES_FEATURE = createFeature(
+ "specifyCatalog-feature.xml");
+
+ /*
+ * CatalogResolver specifies catalog via feature javax.xml.catalog.files.
+ */
+ @Test
+ public void specifyCatalogOnEntityResolver() {
+ checkSysIdResolution(catalogResolver(FILES_FEATURE, (String[]) null),
+ ID_SYS, "http://local/base/dtd/docFeatureSys.dtd");
+ }
+
+ /*
+ * CatalogUriResolver specifies catalog via feature javax.xml.catalog.files.
+ */
+ @Test
+ public void specifyCatalogOnUriResolver() {
+ checkUriResolution(catalogUriResolver(FILES_FEATURE, (String[]) null),
+ ID_URI, "http://local/base/dtd/docFeatureURI.dtd");
+ }
+
+ /*
+ * Resolver specifies catalog via system property javax.xml.catalog.files.
+ */
+ @Test
+ public void specifyCatalogViaSysProps() {
+ System.setProperty(FEATURE_FILES,
+ getCatalogPath("specifyCatalog-sysProps.xml"));
+
+ checkResolutionOnEntityResolver(catalogResolver((String[]) null),
+ "http://local/base/dtd/docSysPropsSys.dtd");
+ checkResolutionOnEntityResolver(
+ catalogResolver(FILES_FEATURE, "specifyCatalog-api.xml"),
+ "http://local/base/dtd/docAPISys.dtd");
+
+ checkResolutionOnUriResolver(catalogUriResolver((String[]) null),
+ "http://local/base/dtd/docSysPropsURI.dtd");
+ checkResolutionOnUriResolver(
+ catalogUriResolver(FILES_FEATURE, "specifyCatalog-api.xml"),
+ "http://local/base/dtd/docAPIURI.dtd");
+ }
+
+ private void checkResolutionOnEntityResolver(CatalogResolver resolver,
+ String matchedUri) {
+ checkSysIdResolution(resolver, ID_SYS, matchedUri);
+ }
+
+ private void checkResolutionOnUriResolver(CatalogUriResolver resolver,
+ String matchedUri) {
+ checkUriResolution(resolver, ID_URI, matchedUri);
+ }
+
+ private static CatalogFeatures createFeature(String catalogName) {
+ return builder().with(FILES, getCatalogPath(catalogName)).build();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SystemFamilyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from system, rewriteSystem, systemSuffix and
+ * delegateSystem entries. It tests the resolution priorities among
+ * the system family entries. The test rule is based on OASIS
+ * Standard V1.1 section 7.1.2. "Resolution of External Identifiers".
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class SystemFamilyTest {
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkSysIdResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified system id is defined in a
+ // system entry.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceSys.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // rewriteSystem entry.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/rs/docBob.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // systemSuffix entry.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/base/dtd/docCarlSS.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("systemFamily.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SystemSuffixTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from systemSuffix entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class SystemSuffixTest {
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkSysIdResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified system id is defined in a
+ // systemIdSuffix entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceSS.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // systemIdSuffix entry. The match isn't an absolute path.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobSS.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // systemIdSuffix entry. The match isn't an absolute path, and
+ // the systemIdSuffix entry defines alternative base. So the
+ // returned URI should include the alternative base.
+ { "http://remote/dtd/carl/cdocCarl.dtd",
+ "http://local/carlBase/dtd/docCarlSS.dtd" },
+
+ // The catalog file defines two systemIdSuffix entries, and both
+ // of them match the specified system id. But the first matched
+ // URI should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/docDavidSS1.dtd" },
+
+ // The catalog file defines two systemIdSuffix entries, and both
+ // of them match the specified system id. But the longest match
+ // should be used.
+ { "http://remote/dtd/ella/docElla.dtd",
+ "http://local/base/dtd/docEllaSS.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("systemSuffix.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SystemTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_SYSTEM;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from system entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class SystemTest {
+
+ @Test(dataProvider = "systemId-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkSysIdResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "systemId-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified system id is defined in a
+ // system entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceSys.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // public entry. But the match isn't an absolute path, so the
+ // returned URI should include the base, which is defined by the
+ // catalog file, as the prefix.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobSys.dtd" },
+
+ // The matched URI of the specified system id is defined in a
+ // system entry. The match isn't an absolute path, and the
+ // system entry defines alternative base. So the returned URI
+ // should include the alternative base.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/carlBase/dtd/docCarlSys.dtd" },
+
+ // The catalog file defines two system entries, and both of them
+ // match the specified system id. But the first matched URI
+ // should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/docDavidSys1.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver(CATALOG_SYSTEM);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/UriFamilyTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from uri, rewriteURI, uriSuffix and delegateURI
+ * entries. It tests the resolution priorities among the uri family
+ * entries. The test rule is based on OASIS Standard V1.1 section
+ * 7.2.2. "Resolution of External Identifiers".
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class UriFamilyTest {
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatch(String systemId, String matchedUri) {
+ checkUriResolution(createResolver(), systemId, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is defined in
+ // a uri entry.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/base/dtd/docAliceURI.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a rewriteURI entry.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/ru/docBob.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a uriSuffix entry.
+ { "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/base/dtd/docCarlUS.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogUriResolver createResolver() {
+ return catalogUriResolver("uriFamily.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/UriSuffixTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from rewriteURI entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class UriSuffixTest {
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatch(String uri, String matchedUri) {
+ checkUriResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is defined in
+ // a uriSuffix entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceUS.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a uriSuffix entry. The match isn't an absolute path.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobUS.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a uriSuffix entry. The match isn't an absolute path, and the
+ // uriSuffix entry defines alternative base. So the returned
+ // URI should include the alternative base.
+ { "http://remote/dtd/carl/cdocCarl.dtd",
+ "http://local/carlBase/dtd/docCarlUS.dtd" },
+
+ // The catalog file defines two uriSuffix entries, and both of
+ // them match the specified URI reference. But the first matched
+ // URI should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/docDavidUS1.dtd" },
+
+ // The catalog file defines two uriSuffix entries, and both
+ // of them match the specified URI reference. But the longest
+ // match should be used.
+ { "http://remote/dtd/ella/docElla.dtd",
+ "http://local/base/dtd/docEllaUS.dtd" } };
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogUriResolver createResolver() {
+ return catalogUriResolver("uriSuffix.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/UriTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_URI;
+import static catalog.CatalogTestUtils.RESOLVE_CONTINUE;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkNoMatch;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary Get matched URIs from uri entries.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class UriTest {
+
+ @Test(dataProvider = "uri-matchedUri")
+ public void testMatch(String uri, String matchedUri) {
+ checkUriResolution(createResolver(), uri, matchedUri);
+ }
+
+ @DataProvider(name = "uri-matchedUri")
+ public Object[][] dataOnMatch() {
+ return new Object[][] {
+ // The matched URI of the specified URI reference is defined in
+ // a uri entry. The match is an absolute path.
+ { "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceURI.dtd" },
+
+ // The matched URI of the specified URI reference is defined in
+ // a uri entry. But the match isn't an absolute path, so the
+ // returned URI should include the base, which is defined by the
+ // catalog file, as the prefix.
+ { "http://remote/dtd/bob/docBob.dtd",
+ "http://local/base/dtd/docBobURI.dtd" },
+
+ // The catalog file defines two uri entries, and both of them
+ // match the specified URI reference. But the first matched URI
+ // should be returned.
+ { "http://remote/dtd/david/docDavid.dtd",
+ "http://local/base/dtd/docDavidURI1.dtd" } };
+ }
+
+ /*
+ * Specify base location via method CatalogUriResolver.resolve(href, base).
+ */
+ @Test
+ public void testSpecifyBaseByAPI() {
+ checkUriResolution(createResolver(),
+ "http://remote/dtd/carl/docCarl.dtd",
+ "http://local/carlBase/dtd/docCarlURI.dtd");
+
+ CatalogUriResolver continueResolver = catalogUriResolver(
+ CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE,
+ RESOLVE_CONTINUE).build(), CATALOG_URI);
+ checkUriResolution(continueResolver, "docCarl.dtd",
+ "http://local/alternativeBase/dtd/",
+ "http://local/alternativeBase/dtd/docCarl.dtd");
+ }
+
+ /*
+ * If no match is found, a CatalogException should be thrown.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void testNoMatch() {
+ checkNoMatch(createResolver());
+ }
+
+ private CatalogUriResolver createResolver() {
+ return catalogUriResolver(CATALOG_URI);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/UrnUnwrappingTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.ResolutionChecker.checkPubIdResolution;
+
+import javax.xml.catalog.CatalogResolver;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary If the passed public identifier is started with "urn:publicid:",
+ * it has to be regarded as URN and normalized. And then the catalog
+ * resolver uses the normalized stuff to do matching.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class UrnUnwrappingTest {
+
+ @Test(dataProvider = "urn-matchedUri")
+ public void testUnwrapping(String urn, String matchedUri) {
+ checkPubIdResolution(createResolver(), urn, matchedUri);
+ }
+
+ @DataProvider(name = "urn-matchedUri")
+ private Object[][] data() {
+ return new Object[][] {
+ // The specified public id is URN format.
+ { "urn:publicid:-:REMOTE:DTD+ALICE+DOCALICE+XML:EN",
+ "http://local/base/dtd/docAlicePub.dtd" },
+
+ // The specified public id includes some special URN chars.
+ { "urn:publicid:-:REMOTE:DTD+BOB+DOCBOB+;+%2B+%3A+%2F+%3B+%27"
+ + "+%3F+%23+%25:EN",
+ "http://local/base/dtd/docBobPub.dtd" } };
+ }
+
+ private CatalogResolver createResolver() {
+ return catalogResolver("urnUnwrapping.xml");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/ValidateCatalogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.CATALOG_SYSTEM;
+import static catalog.CatalogTestUtils.CATALOG_URI;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.ResolutionChecker.checkSysIdResolution;
+import static catalog.ResolutionChecker.checkUriResolution;
+
+import javax.xml.catalog.CatalogException;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8077931
+ * @summary A legal catalog file must be well-formed XML, the root element
+ * must be catalog, and the naming space of the root element must be
+ * urn:oasis:names:tc:entity:xmlns:xml:catalog.
+ * @compile ../../libs/catalog/CatalogTestUtils.java
+ * @compile ../../libs/catalog/ResolutionChecker.java
+ */
+public class ValidateCatalogTest {
+
+ private static final String CATALOG_WRONGROOT = "validateCatalog-wrongRoot.xml";
+ private static final String CATALOG_MALFORMED = "validateCatalog-malformed.xml";
+
+ /*
+ * EntityResolver tries to load catalog with wrong root,
+ * it should throw CatalogException.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void validateWrongRootCatalogOnEntityResolver() {
+ catalogResolver(CATALOG_WRONGROOT);
+ }
+
+ /*
+ * URIResolver tries to load catalog with wrong root,
+ * it should throw CatalogException.
+ */
+ @Test(expectedExceptions = CatalogException.class)
+ public void validateWrongRootCatalogOnUriResolver() {
+ catalogUriResolver(CATALOG_WRONGROOT);
+ }
+
+ /*
+ * EntityResolver tries to load malformed catalog,
+ * it should throw RuntimeException.
+ */
+ @Test(expectedExceptions = RuntimeException.class)
+ public void validateMalformedCatalogOnEntityResolver() {
+ catalogResolver(CATALOG_MALFORMED);
+ }
+
+ /*
+ * UriResolver tries to load malformed catalog,
+ * it should throw RuntimeException.
+ */
+ @Test(expectedExceptions = RuntimeException.class)
+ public void validateMalformedCatalogOnUriResolver() {
+ catalogUriResolver(CATALOG_MALFORMED);
+ }
+
+ /*
+ * Resolver should ignore the catalog which doesn't declare the correct
+ * naming space.
+ */
+ @Test
+ public void validateWrongNamingSpaceCatalog() {
+ String catalogName = "validateCatalog-noNamingSpace.xml";
+ checkSysIdResolution(catalogResolver(catalogName, CATALOG_SYSTEM),
+ "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceSys.dtd");
+ checkUriResolution(catalogUriResolver(catalogName, CATALOG_URI),
+ "http://remote/dtd/alice/docAlice.dtd",
+ "http://local/dtd/docAliceURI.dtd");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/catalogReferCircle-itself.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="catalogReferCircle-itself.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/catalogReferCircle-left.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="catalogReferCircle-right.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/catalogReferCircle-right.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="catalogReferCircle-left.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/deferFeature.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSys.dtd" />
+ <uri name="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceURI.dtd" />
+
+ <delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
+ <delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
+ <nextCatalog catalog="nextCatalog-rightAlice.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegatePublic-alice.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="http://local/dtd/docAlicePub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegatePublic-bob.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegatePublic-carl.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegatePublic.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
+
+ <!-- delegateSystem-bobDummy.xml is not existing -->
+ <delegatePublic publicIdStartString="-//REMOTE//DTD BOB DOCBOB" catalog="delegatePublic-bob.xml" />
+ <delegatePublic publicIdStartString="-//REMOTE//DTD BOB DOCBOB" catalog="delegatePublic-bobDummy.xml" />
+
+ <!-- delegateSystem-carlDummy.xml is not existing -->
+ <delegatePublic publicIdStartString="-//REMOTE//DTD CARL DOCCARL" catalog="delegatePublic-carlDummy.xml" />
+ <delegatePublic publicIdStartString="-//REMOTE//DTD CARL DOCCARL XML" catalog="delegatePublic-carl.xml" />
+
+ <!-- delegateSystem-david.xml is not existing -->
+ <delegatePublic publicIdStartString="-//REMOTE//DTD DAVID DOCDAVID" catalog="delegatePublic-david.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateSystem-alice.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/alice/">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceDS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateSystem-bob.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
+ <system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobDS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateSystem-carl.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
+ <system systemId="http://remote/dtd/carl/docCarl.dtd" uri="docCarlDS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateSystem.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
+
+ <!-- delegateSystem-bobDummy.xml is not existing -->
+ <delegateSystem systemIdStartString="http://remote/dtd/" catalog="delegateSystem-bobDummy.xml" />
+ <delegateSystem systemIdStartString="http://remote/dtd/bob/" catalog="delegateSystem-bob.xml" />
+
+ <!-- delegateSystem-carlDummy.xml is not existing -->
+ <delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carl.xml" />
+ <delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carlDummy.xml" />
+
+ <!-- delegateSystem-carlDummy.xml is not existing -->
+ <delegateSystem systemIdStartString="http://remote/dtd/david/" catalog="delegateSystem-davidDummy.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateUri-alice.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/alice/">
+ <uri name="http://remote/dtd/alice/docAlice.dtd" uri="docAliceDU.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateUri-bob.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
+ <uri name="http://remote/dtd/bob/docBob.dtd" uri="docBobDU.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateUri-carl.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
+ <uri name="http://remote/dtd/carl/docCarl.dtd" uri="docCarlDU.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/delegateUri.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <delegateURI uriStartString="http://remote/dtd/alice/" catalog="delegateUri-alice.xml" />
+
+ <delegateURI uriStartString="http://remote/dtd/" catalog="delegateUri-bobDummy.xml" />
+ <delegateURI uriStartString="http://remote/dtd/bob/" catalog="delegateUri-bob.xml" />
+
+ <delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateUri-carl.xml" />
+ <delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateUri-carlDummy.xml" />
+
+ <delegateURI uriStartString="http://remote/dtd/david/" catalog="delegateUri-davidDummy.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/group.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <group>
+ <system systemId="http://remote/dtd/sys/alice/docAlice.dtd" uri="docAliceSys.dtd" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
+ <uri name="http://remote/dtd/uri/alice/docAlice.dtd" uri="docAliceURI.dtd" />
+ </group>
+
+ <group xml:base="http://local/bobBase/dtd/">
+ <system systemId="http://remote/dtd/sys/bob/docBob.dtd" uri="docBobSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+ <uri name="http://remote/dtd/uri/bob/docBob.dtd" uri="docBobURI.dtd" />
+ </group>
+
+ <system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys1.dtd" />
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub1.dtd" />
+ <uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI1.dtd" />
+ <group>
+ <system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys2.dtd" />
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub2.dtd" />
+ <uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI2.dtd" />
+ </group>
+ <system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys3.dtd" />
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub3.dtd" />
+ <uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI3.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/loadCatalogFiles.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE catalog
+ PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="nextCatalog-dummy.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-left.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="nextCatalog-leftAlice.xml" />
+
+ <nextCatalog catalog="nextCatalog-leftBob.xml" />
+ <group xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobLeftSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobLeftPub.dtd" />
+ <uri name="http://remote/dtd/uri/docBob.dtd" uri="docBobLeftURI.dtd" />
+ </group>
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-leftAlice.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docAlice.dtd" uri="docAliceNextLeftSys.dtd" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAliceNextLeftPub.dtd" />
+ <uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextLeftURI.dtd" />
+
+ <system systemId="http://remote/dtd/sys/docDuplicate.dtd" uri="docDuplicateLeftSys.dtd" />
+ <public publicId="-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN" uri="docDuplicateLeftPub.dtd" />
+ <uri name="http://remote/dtd/uri/docDuplicate.dtd" uri="docDuplicateLeftURI.dtd" />
+
+ <systemSuffix systemIdSuffix="ss/doc.dtd" uri="docSSShorter.dtd" />
+ <rewriteSystem systemIdStartString="http://remote/dtd/rs/" rewritePrefix="http://local/base/dtd/rsShorter/" />
+ <uriSuffix uriSuffix="us/doc.dtd" uri="docUSShorter.dtd" />
+ <rewriteURI uriStartString="http://remote/dtd/ru/" rewritePrefix="http://local/base/dtd/ruShorter/" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-leftBob.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <group xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobNextLeftSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobNextLeftPub.dtd" />
+ <uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextLeftURI.dtd" />
+ </group>
+
+ <nextCatalog catalog="nextCatalog-leftCarl.xml" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-leftCarl.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docCarl.dtd" uri="docCarlSys.dtd" />
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" />
+ <uri name="http://remote/dtd/uri/docCarl.dtd" uri="docCarlURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-right.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="nextCatalog-rightAlice.xml" />
+
+ <nextCatalog catalog="nextCatalog-rightAlice.xml" />
+ <group xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobLeftSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobLeftPub.dtd" />
+ <uri name="http://remote/dtd/uri/docBob.dtd" uri="docBobLeftURI.dtd" />
+ </group>
+
+ <system systemId="http://remote/dtd/sys/docDuplicate.dtd" uri="docDuplicateRightSys.dtd" />
+ <public publicId="-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN" uri="docDuplicateRightPub.dtd" />
+ <uri name="http://remote/dtd/uri/docDuplicate.dtd" uri="docDuplicateRightURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-rightAlice.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docAlice.dtd" uri="docAliceNextRightSys.dtd" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAliceNextRightPub.dtd" />
+ <uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextRightURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/nextCatalog-rightBob.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobNextRightSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobNextRightPub.dtd" />
+ <uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextRightURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/normalization.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId=" http://remote/dtd/alice/docAlice.dtd " uri="docAliceSys.dtd" />
+ <system systemId="http://remote/dtd/bob/docBob<>\^`{|}.dtd" uri="docBobSys.dtd" />
+
+ <uri name=" http://remote/dtd/alice/docAlice.dtd " uri="docAliceSys.dtd" />
+ <uri name="http://remote/dtd/bob/docBob<>\^`{|}.dtd" uri="docBobSys.dtd" />
+
+ <public publicId=" -//REMOTE//DTD ALICE DOCALICE XML//EN " uri="docAlicePub.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/prefer.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <group prefer="public">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
+ </group>
+
+ <group prefer="system">
+ <system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+ </group>
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/preferFeature.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
+
+ <group prefer="system">
+ <system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+ </group>
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/public.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="http://local/dtd/docAlicePub.dtd" />
+
+ <public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
+
+ <public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" xml:base="http://local/carlBase/dtd/" />
+
+ <public publicId="-//REMOTE//DTD DAVID DOCDAVID XML//EN" uri="docDavidPub1.dtd" />
+ <public publicId="-//REMOTE//DTD DAVID DOCDAVID XML//EN" uri="docDavidPub2.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/publicFamily.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/rewriteSystem.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <rewriteSystem systemIdStartString="http://remote/dtd/alice/" rewritePrefix="http://local/dtd/alice/rs/" />
+
+ <rewriteSystem systemIdStartString="http://remote/dtd/bob/" rewritePrefix="bob/rs/" />
+
+ <rewriteSystem systemIdStartString="http://remote/dtd/carl/" rewritePrefix="carl/rs/"
+ xml:base="http://local/carlBase/dtd/" />
+
+ <rewriteSystem systemIdStartString="http://remote/dtd/david/" rewritePrefix="david1/rs/" />
+ <rewriteSystem systemIdStartString="http://remote/dtd/david/" rewritePrefix="david2/rs/" />
+
+ <rewriteSystem systemIdStartString="http://remote/dtd/" rewritePrefix="ella/" />
+ <rewriteSystem systemIdStartString="http://remote/dtd/ella/" rewritePrefix="ella/rs/" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/rewriteUri.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <rewriteURI uriStartString="http://remote/dtd/alice/" rewritePrefix="http://local/dtd/alice/ru/" />
+
+ <rewriteURI uriStartString="http://remote/dtd/bob/" rewritePrefix="bob/ru/" />
+
+ <rewriteURI uriStartString="http://remote/dtd/carl/" rewritePrefix="carl/ru/"
+ xml:base="http://local/carlBase/dtd/" />
+
+ <rewriteURI uriStartString="http://remote/dtd/david/" rewritePrefix="david1/ru/" />
+ <rewriteURI uriStartString="http://remote/dtd/david/" rewritePrefix="david2/ru/" />
+
+ <rewriteURI uriStartString="http://remote/dtd/" rewritePrefix="ella/" />
+ <rewriteURI uriStartString="http://remote/dtd/ella/" rewritePrefix="ella/ru/" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/specifyCatalog-api.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/doc.dtd" uri="docAPISys.dtd" />
+ <uri name="http://remote/dtd/uri/doc.dtd" uri="docAPIURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/specifyCatalog-feature.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/doc.dtd" uri="docFeatureSys.dtd" />
+ <uri name="http://remote/dtd/uri/doc.dtd" uri="docFeatureURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/specifyCatalog-sysProps.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/sys/doc.dtd" uri="docSysPropsSys.dtd" />
+ <uri name="http://remote/dtd/uri/doc.dtd" uri="docSysPropsURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/system.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSys.dtd" />
+
+ <system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
+
+ <system systemId="http://remote/dtd/carl/docCarl.dtd" uri="docCarlSys.dtd" xml:base="http://local/carlBase/dtd/" />
+
+ <system systemId="http://remote/dtd/david/docDavid.dtd" uri="docDavidSys1.dtd" />
+ <system systemId="http://remote/dtd/david/docDavid.dtd" uri="docDavidSys2.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/systemFamily.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
+ <systemSuffix systemIdSuffix="docAlice.dtd" uri="docAliceSS.dtd" />
+ <rewriteSystem systemIdStartString="http://remote/dtd/alice/" rewritePrefix="http://local/base/rs/" />
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
+
+ <delegateSystem systemIdStartString="http://remote/dtd/bob/" catalog="delegateSystem-bob.xml" />
+ <systemSuffix systemIdSuffix="docBob.dtd" uri="docBobSS.dtd" />
+ <rewriteSystem systemIdStartString="http://remote/dtd/bob/" rewritePrefix="http://local/base/dtd/rs/" />
+
+ <delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carl.xml" />
+ <systemSuffix systemIdSuffix="docCarl.dtd" uri="docCarlSS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/systemSuffix.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <systemSuffix systemIdSuffix="docAlice.dtd" uri="http://local/dtd/docAliceSS.dtd" />
+
+ <systemSuffix systemIdSuffix="docBob.dtd" uri="docBobSS.dtd" />
+
+ <systemSuffix systemIdSuffix="docCarl.dtd" uri="docCarlSS.dtd" xml:base="http://local/carlBase/dtd/" />
+
+ <systemSuffix systemIdSuffix="docDavid.dtd" uri="docDavidSS1.dtd" />
+ <systemSuffix systemIdSuffix="docDavid.dtd" uri="docDavidSS2.dtd" />
+
+ <systemSuffix systemIdSuffix="docElla.dtd" uri="/" />
+ <systemSuffix systemIdSuffix="ella/docElla.dtd" uri="docEllaSS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/uri.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <uri name="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceURI.dtd" />
+
+ <uri name="http://remote/dtd/bob/docBob.dtd" uri="docBobURI.dtd" />
+
+ <uri name="http://remote/dtd/carl/docCarl.dtd" uri="docCarlURI.dtd" xml:base="http://local/carlBase/dtd/" />
+
+ <uri name="http://remote/dtd/david/docDavid.dtd" uri="docDavidURI1.dtd" />
+ <uri name="http://remote/dtd/david/docDavid.dtd" uri="docDavidURI2.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/uriFamily.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <delegateURI uriStartString="http://remote/dtd/alice/" catalog="delegateURI-alice.xml" />
+ <uriSuffix uriSuffix="docAlice.dtd" uri="docAliceUS.dtd" />
+ <rewriteURI uriStartString="http://remote/dtd/alice/" rewritePrefix="http://local/base/ru/" />
+ <uri name="http://remote/dtd/alice/docAlice.dtd" uri="docAliceURI.dtd" />
+
+ <delegateURI uriStartString="http://remote/dtd/bob/" catalog="delegateURI-bob.xml" />
+ <uriSuffix uriSuffix="docBob.dtd" uri="docBobUS.dtd" />
+ <rewriteURI uriStartString="http://remote/dtd/bob/" rewritePrefix="http://local/base/dtd/ru/" />
+
+ <delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateURI-carl.xml" />
+ <uriSuffix uriSuffix="docCarl.dtd" uri="docCarlUS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/uriSuffix.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <uriSuffix uriSuffix="docAlice.dtd" uri="http://local/dtd/docAliceUS.dtd" />
+
+ <uriSuffix uriSuffix="docBob.dtd" uri="docBobUS.dtd" />
+
+ <uriSuffix uriSuffix="docCarl.dtd" uri="docCarlUS.dtd" xml:base="http://local/carlBase/dtd/" />
+
+ <uriSuffix uriSuffix="docDavid.dtd" uri="docDavidUS1.dtd" />
+ <uriSuffix uriSuffix="docDavid.dtd" uri="docDavidUS2.dtd" />
+
+ <uriSuffix uriSuffix="docElla.dtd" uri="/" />
+ <uriSuffix uriSuffix="ella/docElla.dtd" uri="docEllaUS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/urnUnwrapping.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
+ <public publicId="-//REMOTE//DTD BOB DOCBOB :: + : / ; ' ? # %//EN" uri="docBobPub.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/validateCatalog-malformed.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This catalog is malformed XML -->
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <system systemId="http://remote/dtd/doc.dtd" uri="docSys.dtd" />
+</cat>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/validateCatalog-noNamingSpace.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This catalog doesn't define the correct naming space -->
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog1">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSysWrongNS.dtd" />
+ <uri name="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceURIWrongNS.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/validateCatalog-wrongRoot.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- The root of this catalog isn't named "catalog" -->
+<cat xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <system systemId="http://remote/dtd/doc.dtd" uri="docSys.dtd" />
+</cat>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/IsolatedJDK.sh Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+if [ $# = 0 ]; then
+ echo "The suffix of ISOLATED_JDK is mandatory"
+ exit 1
+fi
+
+checkVariable() {
+ variable='$'$1
+
+ if [ "${variable}" = "" ]; then
+ echo "Failed due to $1 is not set."
+ exit 1
+ fi
+}
+
+checkVariables() {
+ for variable in $*
+ do
+ checkVariable ${variable}
+ done
+}
+
+# Check essential variables
+checkVariables TESTJAVA TESTSRC TESTCLASSES TESTCLASSPATH
+
+echo "TESTJAVA=${TESTJAVA}"
+echo "TESTSRC=${TESTSRC}"
+echo "TESTCLASSES=${TESTCLASSES}"
+echo "TESTCLASSPATH=${TESTCLASSPATH}"
+
+# Make an isolated copy of the testing JDK
+ISOLATED_JDK="./ISOLATED_JDK_$1"
+echo "ISOLATED_JDK=${ISOLATED_JDK}"
+
+echo "Copy testing JDK started"
+cp -H -R ${TESTJAVA} ${ISOLATED_JDK} || exit 1
+chmod -R +w ${ISOLATED_JDK} || exit 1
+echo "Copy testing JDK ended"
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/TEST.properties Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,4 @@
+lib.dirs=/javax/xml/jaxp/libs
+
+# Declare module dependency
+modules=java.xml
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import static catalog.CatalogTestUtils.DEFER_FALSE;
+import static catalog.CatalogTestUtils.FEATURE_DEFER;
+import static catalog.CatalogTestUtils.FEATURE_FILES;
+import static catalog.CatalogTestUtils.FEATURE_PREFER;
+import static catalog.CatalogTestUtils.FEATURE_RESOLVE;
+import static catalog.CatalogTestUtils.PREFER_SYSTEM;
+import static catalog.CatalogTestUtils.RESOLVE_CONTINUE;
+import static catalog.CatalogTestUtils.catalogResolver;
+import static catalog.CatalogTestUtils.catalogUriResolver;
+import static catalog.CatalogTestUtils.createPropsContent;
+import static catalog.CatalogTestUtils.deleteJAXPProps;
+import static catalog.CatalogTestUtils.generateJAXPProps;
+import static catalog.CatalogTestUtils.getCatalogPath;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+/*
+ * This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
+ * jaxp.properties and system properties could be cared.
+ */
+public class PropertiesTest {
+
+ private static final String CATALOG_PROPERTIES = "properties.xml";
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("testJAXPProperties started");
+ testJAXPProperties();
+ System.out.println("testJAXPProperties ended");
+
+ System.out.println("testSystemProperties started");
+ testSystemProperties();
+ System.out.println("testSystemProperties ended");
+
+ System.out.println("Test passed");
+ }
+
+ /*
+ * Tests how does jaxp.properties affects the resolution.
+ */
+ private static void testJAXPProperties() throws IOException {
+ generateJAXPProps(createJAXPPropsContent());
+ testProperties();
+ deleteJAXPProps();
+ }
+
+ /*
+ * Tests how does system properties affects the resolution.
+ */
+ private static void testSystemProperties() {
+ setSystemProperties();
+ testProperties();
+ }
+
+ private static void testProperties() {
+ testPropertiesOnEntityResolver();
+ testPropertiesOnUriResolver();
+ }
+
+ private static void testPropertiesOnEntityResolver() {
+ CatalogResolver entityResolver = catalogResolver((String[]) null);
+ entityResolver.resolveEntity("-//REMOTE//DTD DOCDUMMY XML//EN",
+ "http://remote/sys/dtd/docDummy.dtd");
+ "http://local/base/dtd/docSys.dtd".equals(
+ entityResolver.resolveEntity("-//REMOTE//DTD DOC XML//EN",
+ "http://remote/dtd/doc.dtd").getSystemId());
+ }
+
+ private static void testPropertiesOnUriResolver() {
+ CatalogUriResolver uriResolver = catalogUriResolver((String[]) null);
+ uriResolver.resolve("http://remote/uri/dtd/docDummy.dtd", null);
+ "http://local/base/dtd/docURI.dtd".equals(uriResolver.resolve(
+ "http://remote/dtd/doc.dtd", null).getSystemId());
+ }
+
+ // The properties in jaxp.properties don't use default values
+ private static String createJAXPPropsContent() {
+ Map<String, String> props = new HashMap<>();
+ props.put(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
+ props.put(FEATURE_DEFER, DEFER_FALSE);
+ props.put(FEATURE_PREFER, PREFER_SYSTEM);
+ props.put(FEATURE_RESOLVE, RESOLVE_CONTINUE);
+ return createPropsContent(props);
+ }
+
+ // The system properties don't use default values
+ private static void setSystemProperties() {
+ System.setProperty(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
+ System.setProperty(FEATURE_DEFER, DEFER_FALSE);
+ System.setProperty(FEATURE_PREFER, PREFER_SYSTEM);
+ System.setProperty(FEATURE_RESOLVE, RESOLVE_CONTINUE);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.sh Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+# @test
+# @bug 8077931
+# @summary This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
+# jaxp.properties and system properties could be used.
+# @library ../../libs/
+# @build catalog.CatalogTestUtils
+# @build PropertiesTest
+# @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS
+# @run shell/timeout=600 PropertiesTest.sh
+
+echo "Copies properties.xml to class path"
+TEST_CATALOG_PATH=${TESTCLASSES}/catalog/catalogFiles
+echo "TEST_CATALOG_PATH=${TEST_CATALOG_PATH}"
+mkdir -p ${TEST_CATALOG_PATH}
+cp ${TESTSRC}/catalogFiles/properties.xml ${TEST_CATALOG_PATH}/properties.xml
+
+# Execute test
+ISOLATED_JDK=./ISOLATED_JDK_JAXP_PROPS
+echo "Executes PropertiesTest"
+${ISOLATED_JDK}/bin/java -Dtest.src="${TESTSRC}/.." ${TESTVMOPTS} -cp "${TESTCLASSPATH}" catalog.PropertiesTest
+exitCode=$?
+
+# Cleanup ISOLATED_JDK
+rm -rf ${ISOLATED_JDK}
+
+# Results
+echo ''
+if [ $exitCode -gt 0 ]; then
+ echo "PropertiesTest failed";
+else
+ echo "PropertiesTest passed";
+fi
+exit $exitCode
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/catalogFiles/properties.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
+ <system systemId="http://remote/dtd/doc.dtd" uri="docSys.dtd" />
+ <public publicId="-//REMOTE//DTD DOC XML//EN" uri="docPub.dtd" />
+ <uri name="http://remote/dtd/doc.dtd" uri="docURI.dtd" />
+</catalog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+/*
+ * Utilities for testing XML Catalog API.
+ */
+final class CatalogTestUtils {
+
+ /* catalog files */
+ static final String CATALOG_PUBLIC = "public.xml";
+ static final String CATALOG_SYSTEM = "system.xml";
+ static final String CATALOG_URI = "uri.xml";
+
+ /* features */
+ static final String FEATURE_FILES = "javax.xml.catalog.files";
+ static final String FEATURE_PREFER = "javax.xml.catalog.prefer";
+ static final String FEATURE_DEFER = "javax.xml.catalog.defer";
+ static final String FEATURE_RESOLVE = "javax.xml.catalog.resolve";
+
+ /* values of prefer feature */
+ static final String PREFER_SYSTEM = "system";
+ static final String PREFER_PUBLIC = "public";
+
+ /* values of defer feature */
+ static final String DEFER_TRUE = "true";
+ static final String DEFER_FALSE = "false";
+
+ /* values of resolve feature */
+ static final String RESOLVE_STRICT = "strict";
+ static final String RESOLVE_CONTINUE = "continue";
+ static final String RESOLVE_IGNORE = "ignore";
+
+ private static final String JAXP_PROPS = "jaxp.properties";
+ private static final String JAXP_PROPS_BAK = JAXP_PROPS + ".bak";
+
+ /*
+ * Force using slash as File separator as we always use cygwin to test in
+ * Windows platform.
+ */
+ private static final String FILE_SEP = "/";
+
+ private CatalogTestUtils() { }
+
+ /* ********** create resolver ********** */
+
+ /*
+ * Creates CatalogResolver with a set of catalogs.
+ */
+ static CatalogResolver catalogResolver(String... catalogName) {
+ return catalogResolver(null, catalogName);
+ }
+
+ /*
+ * Creates CatalogResolver with a feature and a set of catalogs.
+ */
+ static CatalogResolver catalogResolver(CatalogFeatures features,
+ String... catalogName) {
+ return CatalogManager.catalogResolver(features,
+ getCatalogPaths(catalogName));
+ }
+
+ /*
+ * Creates catalogUriResolver with a set of catalogs.
+ */
+ static CatalogUriResolver catalogUriResolver(String... catalogName) {
+ return catalogUriResolver(null, catalogName);
+ }
+
+ /*
+ * Creates catalogUriResolver with a feature and a set of catalogs.
+ */
+ static CatalogUriResolver catalogUriResolver(
+ CatalogFeatures features, String... catalogName) {
+ return CatalogManager.catalogUriResolver(features,
+ getCatalogPaths(catalogName));
+ }
+
+ // Gets the paths of the specified catalogs.
+ private static String[] getCatalogPaths(String... catalogNames) {
+ return catalogNames == null
+ ? null
+ : Stream.of(catalogNames).map(
+ catalogName -> getCatalogPath(catalogName)).collect(
+ Collectors.toList()).toArray(new String[0]);
+ }
+
+ // Gets the paths of the specified catalogs.
+ static String getCatalogPath(String catalogName) {
+ return catalogName == null
+ ? null
+ : getPathByClassName(CatalogTestUtils.class, "catalogFiles")
+ + catalogName;
+ }
+
+ /*
+ * Acquire a full path string by given class name and relative path string.
+ */
+ private static String getPathByClassName(Class<?> clazz,
+ String relativeDir) {
+ String packageName = FILE_SEP
+ + clazz.getPackage().getName().replaceAll("[.]", FILE_SEP);
+ String javaSourcePath = System.getProperty("test.src").replaceAll(
+ "\\" + File.separator, FILE_SEP) + packageName + FILE_SEP;
+ String normalizedPath = Paths.get(javaSourcePath,
+ relativeDir).normalize().toAbsolutePath().toString();
+ return normalizedPath.replace("\\", FILE_SEP) + FILE_SEP;
+ }
+
+ /* ********** jaxp.properties ********** */
+
+ /*
+ * Generates the jaxp.properties with the specified content.
+ */
+ static void generateJAXPProps(String content) throws IOException {
+ Path filePath = getJAXPPropsPath();
+ Path bakPath = filePath.resolveSibling(JAXP_PROPS_BAK);
+ if (Files.exists(filePath) && !Files.exists(bakPath)) {
+ Files.move(filePath, bakPath);
+ }
+
+ Files.write(filePath, content.getBytes());
+ }
+
+ /*
+ * Deletes the jaxp.properties.
+ */
+ static void deleteJAXPProps() throws IOException {
+ Path filePath = getJAXPPropsPath();
+ Files.delete(filePath);
+ Path bakFilePath = filePath.resolveSibling(JAXP_PROPS_BAK);
+ if (Files.exists(bakFilePath)) {
+ Files.move(bakFilePath, filePath);
+ }
+ }
+
+ /*
+ * Gets the path of jaxp.properties.
+ */
+ private static Path getJAXPPropsPath() {
+ return Paths.get(System.getProperty("java.home") + File.separator
+ + "conf" + File.separator + JAXP_PROPS);
+ }
+
+ /*
+ * Creates the content of properties file with the specified
+ * property-value pairs.
+ */
+ static String createPropsContent(Map<String, String> props) {
+ return props.entrySet().stream().map(
+ entry -> String.format("%s=%s%n", entry.getKey(),
+ entry.getValue())).reduce(
+ (line1, line2) -> line1 + line2).get();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/ResolutionChecker.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package catalog;
+
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.catalog.CatalogUriResolver;
+
+import org.testng.Assert;
+
+/*
+ * Utilities for checking catalog resolution.
+ */
+class ResolutionChecker {
+
+ /* ********** Checks normal resolution ********** */
+
+ /*
+ * Checks the resolution result for specified external identifier.
+ */
+ static void checkExtIdResolution(CatalogResolver resolver,
+ String publicId, String systemId, String matchedUri) {
+ Assert.assertEquals(
+ resolver.resolveEntity(publicId, systemId).getSystemId(),
+ matchedUri);
+ }
+
+ /*
+ * Checks the resolution result for specified system identifier.
+ */
+ static void checkSysIdResolution(CatalogResolver resolver,
+ String systemId, String matchedUri) {
+ checkExtIdResolution(resolver, null, systemId, matchedUri);
+ }
+
+ /*
+ * Checks the resolution result for specified public identifier.
+ */
+ static void checkPubIdResolution(CatalogResolver resolver,
+ String publicId, String matchedUri) {
+ checkExtIdResolution(resolver, publicId, null, matchedUri);
+ }
+
+ /*
+ * Checks the resolution result for specified URI references
+ * with the specified base location.
+ */
+ static void checkUriResolution(CatalogUriResolver resolver,
+ String href, String base, String matchedUri) {
+ Assert.assertEquals(resolver.resolve(href, base).getSystemId(),
+ matchedUri);
+ }
+
+ /*
+ * Checks the resolution result for specified URI references.
+ */
+ static void checkUriResolution(CatalogUriResolver resolver,
+ String href, String matchedUri) {
+ checkUriResolution(resolver, href, null, matchedUri);
+ }
+
+ /* ********** Checks no match is found ********** */
+
+ /*
+ * With strict resolution, if no match is found,
+ * CatalogResolver should throw CatalogException.
+ */
+ static void checkNoMatch(CatalogResolver resolver) {
+ resolver.resolveEntity("-//EXTID//DTD NOMATCH DOCNOMATCH XML//EN",
+ "http://extId/noMatch/docNoMatch.dtd");
+ }
+
+ /*
+ * With strict resolution, if no match is found,
+ * CatalogUriResolver should throw CatalogException.
+ */
+ static void checkNoMatch(CatalogUriResolver resolver) {
+ resolver.resolve("http://uri/noMatch/docNoMatch.dtd", null);
+ }
+
+ /* ********** Checks expected exception ********** */
+
+ /*
+ * Checks the expected exception during the resolution for specified
+ * external identifier.
+ */
+ static <T extends Throwable> void expectExceptionOnExtId(
+ CatalogResolver resolver, String publicId, String systemId,
+ Class<T> expectedExceptionClass) {
+ expectThrows(expectedExceptionClass, () -> {
+ resolver.resolveEntity(publicId, systemId);
+ });
+ }
+
+ /*
+ * Checks the expected exception during the resolution for specified
+ * system identifier.
+ */
+ static <T extends Throwable> void expectExceptionOnSysId(
+ CatalogResolver resolver, String systemId,
+ Class<? extends Throwable> expectedExceptionClass) {
+ expectExceptionOnExtId(resolver, null, systemId,
+ expectedExceptionClass);
+ }
+
+ /*
+ * Checks the expected exception during the resolution for specified
+ * public identifier.
+ */
+ static <T extends Throwable> void expectExceptionOnPubId(
+ CatalogResolver resolver, String publicId,
+ Class<T> expectedExceptionClass) {
+ expectExceptionOnExtId(resolver, publicId, null,
+ expectedExceptionClass);
+ }
+
+ /*
+ * Checks the expected exception during the resolution for specified
+ * URI reference with a specified base location.
+ */
+ static <T extends Throwable> void expectExceptionOnUri(
+ CatalogUriResolver resolver, String href, String base,
+ Class<T> expectedExceptionClass) {
+ expectThrows(expectedExceptionClass, () -> {
+ resolver.resolve(href, base);
+ });
+ }
+
+ /*
+ * Checks the expected exception during the resolution for specified
+ * URI reference without any specified base location.
+ */
+ static <T extends Throwable> void expectExceptionOnUri(
+ CatalogUriResolver resolver, String href,
+ Class<T> expectedExceptionClass) {
+ expectExceptionOnUri(resolver, href, null, expectedExceptionClass);
+ }
+
+ // The TestNG distribution in current JTREG build doesn't support
+ // method Assert.expectThrows().
+ private static <T extends Throwable> T expectThrows(Class<T> throwableClass,
+ ThrowingRunnable runnable) {
+ try {
+ runnable.run();
+ } catch (Throwable t) {
+ if (throwableClass.isInstance(t)) {
+ return throwableClass.cast(t);
+ } else {
+ String mismatchMessage = String.format(
+ "Expected %s to be thrown, but %s was thrown",
+ throwableClass.getSimpleName(),
+ t.getClass().getSimpleName());
+
+ throw new AssertionError(mismatchMessage, t);
+ }
+ }
+
+ String message = String.format(
+ "Expected %s to be thrown, but nothing was thrown",
+ throwableClass.getSimpleName());
+ throw new AssertionError(message);
+ }
+
+ private interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+}
--- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties Thu Nov 05 13:43:17 2015 -0800
+++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties Wed Jul 05 20:59:18 2017 +0200
@@ -1,6 +1,8 @@
# jaxp test uses TestNG
TestNG.dirs = .
+lib.dirs = /javax/xml/jaxp/libs
+
# Declare module dependency
modules=java.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import java.io.IOException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import static jaxp.library.JAXPTestUtilities.getPathByClassName;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.DefaultHandler2;
+
+/*
+ * @bug 8081248
+ * @summary Tests basic Catalog functions.
+ */
+
+public class CatalogTest {
+ /*
+ Tests basic catalog feature by using a CatalogResolver instance to
+ resolve a DTD reference to a locally specified DTD file. If the resolution
+ is successful, the Handler shall return the value of the entity reference
+ that matches the expected value.
+ */
+ @Test(dataProvider = "catalog")
+ public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) {
+ String catalog = null;
+ if (catalogFile != null) {
+ catalog = getClass().getResource(catalogFile).getFile();
+ }
+ String url = getClass().getResource(xml).getFile();
+ try {
+ CatalogResolver cr = CatalogManager.catalogResolver(null, catalog);
+ XMLReader reader = saxParser.getXMLReader();
+ reader.setEntityResolver(cr);
+ MyHandler handler = new MyHandler(saxParser);
+ reader.setContentHandler(handler);
+ reader.parse(url);
+ System.out.println(test + ": expected [" + expected + "] <> actual [" + handler.getResult() + "]");
+ Assert.assertEquals(handler.getResult(), expected);
+ } catch (SAXException | IOException e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
+ /*
+ Verifies that when there's no match, in this case only an invalid
+ catalog is provided, the resolver will throw an exception by default.
+ */
+ @Test
+ public void testInvalidCatalog() {
+ String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+
+ String test = "testInvalidCatalog";
+ try {
+ CatalogResolver resolver = CatalogManager.catalogResolver(null, catalog);
+ String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId();
+ } catch (Exception e) {
+ String msg = e.getMessage();
+ if (msg != null) {
+ if (msg.contains("No match found for publicId")) {
+ Assert.assertEquals(msg, "No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'.");
+ System.out.println(test + ": expected [No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'.]");
+ System.out.println("actual [" + msg + "]");
+ }
+ }
+ }
+ }
+
+ /*
+ Verifies that if resolve is "ignore", an empty InputSource will be returned
+ when there's no match. The systemId is then null.
+ */
+ @Test
+ public void testIgnoreInvalidCatalog() {
+ String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+ CatalogFeatures f = CatalogFeatures.builder()
+ .with(Feature.FILES, catalog)
+ .with(Feature.PREFER, "public")
+ .with(Feature.DEFER, "true")
+ .with(Feature.RESOLVE, "ignore")
+ .build();
+
+ String test = "testInvalidCatalog";
+ try {
+ CatalogResolver resolver = CatalogManager.catalogResolver(f, "");
+ String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId();
+ System.out.println("testIgnoreInvalidCatalog: expected [null]");
+ System.out.println("testIgnoreInvalidCatalog: expected [null]");
+ System.out.println("actual [" + actualSystemId + "]");
+ Assert.assertEquals(actualSystemId, null);
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
+
+ /*
+ DataProvider: provides test name, expected string, the catalog, and XML
+ document.
+ */
+ @DataProvider(name = "catalog")
+ Object[][] getCatalog() {
+ return new Object[][]{
+ {"testSystem", "Test system entry", "catalog.xml", "system.xml", getParser()},
+ {"testRewriteSystem", "Test rewritesystem entry", "catalog.xml", "rewritesystem.xml", getParser()},
+ {"testRewriteSystem1", "Test rewritesystem entry", "catalog.xml", "rewritesystem1.xml", getParser()},
+ {"testSystemSuffix", "Test systemsuffix entry", "catalog.xml", "systemsuffix.xml", getParser()},
+ {"testDelegateSystem", "Test delegatesystem entry", "catalog.xml", "delegatesystem.xml", getParser()},
+ {"testPublic", "Test public entry", "catalog.xml", "public.xml", getParser()},
+ {"testDelegatePublic", "Test delegatepublic entry", "catalog.xml", "delegatepublic.xml", getParser()},
+ };
+ }
+
+ SAXParser getParser() {
+ SAXParser saxParser = null;
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ saxParser = factory.newSAXParser();
+ } catch (ParserConfigurationException | SAXException e) {
+ }
+
+ return saxParser;
+ }
+
+
+ /**
+ * SAX handler
+ */
+ public class MyHandler extends DefaultHandler2 implements ErrorHandler {
+
+ StringBuilder textContent = new StringBuilder();
+ SAXParser saxParser;
+
+ MyHandler(SAXParser saxParser) {
+ textContent.setLength(0);
+ this.saxParser = saxParser;
+ }
+
+ String getResult() {
+ return textContent.toString();
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ textContent.delete(0, textContent.length());
+ try {
+ System.out.println("Element: " + uri + ":" + localName + " " + qName);
+ } catch (Exception e) {
+ throw new SAXException(e);
+ }
+
+ }
+
+ @Override
+ public void characters(char ch[], int start, int length) throws SAXException {
+ textContent.append(ch, start, length);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/catalog.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<catalog
+ xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+ <public publicId="-//W3C//DTD XHTML 1.0 Strict//EN"
+ uri="catalog/xhtml1-strict.dtd"/>
+
+ <systemSuffix systemIdSuffix="html1-strict.dtd"
+ uri="file:///share/mirrors/w3c/xhtml1/xhtml1-strict.dtd"/>
+
+ <public publicId="-//OPENJDK//XML CATALOG DTD//1.0" uri="public.dtd"/>
+ <system systemId="http://openjdk.java.net/xml/catalog/dtd/system.dtd" uri="system.dtd"/>
+
+ <rewriteSystem systemIdStartString="http://openjdk.java.net/"
+ rewritePrefix="files" />
+
+ <rewriteSystem systemIdStartString="http://openjdk.java.net/xml/catalog/dtd/"
+ rewritePrefix="files" />
+
+ <systemSuffix systemIdSuffix="systemsuffix.dtd" uri="systemsuffix.dtd"/>
+
+ <delegatePublic publicIdStartString="-//JAVASE//XML CATALOG DTD//DELEGATEPULIC" catalog="files/delegatecatalog.xml"/>
+ <delegateSystem systemIdStartString="http://java.com/xml/catalog/dtd/" catalog="files/delegatecatalog.xml"/>
+
+ <group resolve="continue">
+ <system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSys.dtd" />
+ </group>
+
+</catalog>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/catalog_invalid.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<catalog
+ xmlns="xyz">
+
+ <public publicId="-//W3C//DTD XHTML 1.0 Strict//EN"
+ uri="catalog/xhtml1-strict.dtd"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/delegatepublic.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//JAVASE//XML CATALOG DTD//DELEGATEPULIC"
+ "http://java.com/xml/catalog/dtd/delegatepublic.dtd">
+
+<catalogtest>Test &delegatepublic; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/delegatesystem.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//JAVASE//XML CATALOG DTD//DELEGATESYSTEM"
+ "http://java.com/xml/catalog/dtd/delegatesystem.dtd">
+
+<catalogtest>Test &delegatesystem; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/files/delegatecatalog.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<catalog
+ xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+ <public publicId="-//W3C//DTD XHTML 1.0 Strict//EN"
+ uri="catalog/xhtml1-strict.dtd"/>
+
+ <systemSuffix systemIdSuffix="html1-strict.dtd"
+ uri="file:///share/mirrors/w3c/xhtml1/xhtml1-strict.dtd"/>
+
+ <public publicId="-//OPENJDK//XML CATALOG DTD//1.0" uri="public.dtd"/>
+
+ <system systemId="http://openjdk.java.net/xml/catalog/dtd/system.dtd" uri="system.dtd"/>
+
+ <rewriteSystem systemIdStartString="http://openjdk.java.net/"
+ rewritePrefix="/C:/cygwin/home/huizwang/openjdk/jdk9-dev/jaxp1/" />
+
+ <rewriteSystem systemIdStartString="http://openjdk.java.net/xml/catalog/dtd/"
+ rewritePrefix="/C:/cygwin/home/huizwang/openjdk/jdk9-dev/jaxp1/jaxp-ri/src/unit-test/acatalogapi/" />
+
+ <public publicId="-//JAVASE//XML CATALOG DTD//DELEGATEPULIC" uri="delegatepublic.dtd"/>
+
+ <system systemId="http://java.com/xml/catalog/dtd/delegatesystem.dtd" uri="delegatesystem.dtd"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/files/delegatepublic.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY delegatepublic "delegatepublic">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/files/delegatesystem.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY delegatesystem "delegatesystem">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/files/rewritesystem.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY rewritesystem "rewritesystem">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/files/systemsuffix.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY systemsuffix "systemsuffix">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/public.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY public "public">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/public.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!-- make java.net java123.net to make sure no system match -->
+<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//1.0"
+ "http://openjdk.java123.net/catalog/public.dtd">
+
+<catalogtest>Test &public; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/rewritesystem.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//REWRITE"
+ "http://openjdk.java.net/xml/catalog/dtd/rewritesystem.dtd">
+
+<catalogtest>Test &rewritesystem; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/rewritesystem1.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//REWRITE"
+ "http://openjdk.java.net/rewritesystem.dtd">
+
+<catalogtest>Test &rewritesystem; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/system.dtd Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+
+<!ENTITY system "system">
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/system.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//1.0"
+ "http://openjdk.java.net/xml/catalog/dtd/system.dtd">
+
+<catalogtest>Test &system; entry</catalogtest>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/systemsuffix.xml Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//REWRITE"
+ "http://openjdk.java.net/xml/catalog/dtd/systemsuffix.dtd">
+
+<catalogtest>Test &systemsuffix; entry</catalogtest>
\ No newline at end of file
--- a/jdk/.hgtags Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/.hgtags Wed Jul 05 20:59:18 2017 +0200
@@ -333,3 +333,4 @@
6e50b992bef4def597a5033e696e5b1d4fe5b294 jdk9-b88
0d0a63b325592607974612f9cfb48590975aa2d6 jdk9-b89
b433e4dfb830fea60e5187e4580791b62cc362d2 jdk9-b90
+97624df5026a2fb191793697dbd2c604c4d5c66e jdk9-b91
--- a/jdk/make/CompileDemos.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/CompileDemos.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -23,6 +23,10 @@
# questions.
#
+################################################################################
+# Build demos for the JDK into $(SUPPORT_OUTPUTDIR)/demos/image.
+################################################################################
+
default: all
include $(SPEC)
@@ -31,428 +35,487 @@
include NativeCompilation.gmk
include SetupJavaCompilers.gmk
include TextFileProcessing.gmk
+include ZipArchive.gmk
# Prepare the find cache.
$(eval $(call FillCacheFind, $(JDK_TOPDIR)/src))
# Append demo goals to this variable.
-BUILD_DEMOS =
+TARGETS =
# The demo structure and contents should really be cleaned up.
# Now every other demo has its own quirks where to put the
# READMEs and other files.
DEMO_SHARE_SRC := $(JDK_TOPDIR)/src/demo/share
-DEMO_CLOSED_SHARE_SRC := $(JDK_TOPDIR)/src/closed/demo/share
-DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris
-DEMO_OS_TYPE_SRC := $(JDK_TOPDIR)/src/demo/$(OPENJDK_TARGET_OS_TYPE)
GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
-##################################################################################################
+DEMO_MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf
-# This rule will be depended on due to the MANIFEST line
+# This rule will be depended on due to the MANIFEST line in SetupBuildDemo
+# and SetupBuildJvmtiDemo.
$(eval $(call SetupTextFileProcessing, BUILD_JAVA_MANIFEST, \
SOURCE_FILES := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf, \
- OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \
+ OUTPUT_FILE := $(DEMO_MANIFEST), \
REPLACEMENTS := \
@@RELEASE@@ => $(RELEASE) ; \
@@COMPANY_NAME@@ => $(COMPANY_NAME) , \
))
-define SetupAppletDemo
- $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_APPLET_$1, \
+################################################################################
+# Build applet demos.
+
+# Setup make rules for building a demo applet.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name. It is also
+# used to locate the name of the applet subdir, and to determine the name
+# of the output directory.
+#
+# Remaining parameters are named arguments. These include:
+# SRC_DIR Alternative source directory to use for the demos.
+# DISABLE_SJAVAC Passed to SetupJavaCompilation
+
+SetupBuildAppletDemo = $(NamedParamsMacroTemplate)
+define SetupBuildAppletDemoBody
+ ifeq ($$($1_SRC_DIR), )
+ $1_SRC_DIR := $(DEMO_SHARE_SRC)/applets
+ endif
+
+ $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_APPLET_$1, \
SETUP := GENERATE_USINGJDKBYTECODE, \
- SRC := $(JDK_TOPDIR)/src/$3demo/share/applets/$1, \
- BIN := $(SUPPORT_OUTPUTDIR)/demo/image/applets/$1, \
+ SRC := $$($1_SRC_DIR)/$1, \
+ BIN := $(SUPPORT_OUTPUTDIR)/demos/image/applets/$1, \
COPY := .html .java .xyz .obj .au .gif, \
- DISABLE_SJAVAC := $2))
- BUILD_DEMOS += $$(BUILD_DEMO_APPLET_$1)
+ DISABLE_SJAVAC := $$($1_DISABLE_SJAVAC), \
+ ))
+
+ $1 := $$(BUILD_DEMO_APPLET_$1)
+
+ TARGETS += $$($1)
endef
ifneq ($(OPENJDK_TARGET_OS), solaris)
- $(eval $(call SetupAppletDemo,ArcTest))
- $(eval $(call SetupAppletDemo,BarChart))
- $(eval $(call SetupAppletDemo,Blink))
- $(eval $(call SetupAppletDemo,CardTest))
- $(eval $(call SetupAppletDemo,Clock))
- $(eval $(call SetupAppletDemo,DitherTest))
- $(eval $(call SetupAppletDemo,DrawTest))
- $(eval $(call SetupAppletDemo,Fractal))
- $(eval $(call SetupAppletDemo,GraphicsTest))
- $(eval $(call SetupAppletDemo,NervousText))
- $(eval $(call SetupAppletDemo,SimpleGraph))
- $(eval $(call SetupAppletDemo,SortDemo))
- $(eval $(call SetupAppletDemo,SpreadSheet))
-
- ifndef OPENJDK
- $(eval $(call SetupAppletDemo,Animator,,closed/))
- $(eval $(call SetupAppletDemo,GraphLayout,true,closed/))
- $(eval $(call SetupAppletDemo,JumpingBox,,closed/))
- $(eval $(call SetupAppletDemo,TicTacToe,,closed/))
- endif
+ $(eval $(call SetupBuildAppletDemo, ArcTest))
+ $(eval $(call SetupBuildAppletDemo, BarChart))
+ $(eval $(call SetupBuildAppletDemo, Blink))
+ $(eval $(call SetupBuildAppletDemo, CardTest))
+ $(eval $(call SetupBuildAppletDemo, Clock))
+ $(eval $(call SetupBuildAppletDemo, DitherTest))
+ $(eval $(call SetupBuildAppletDemo, DrawTest))
+ $(eval $(call SetupBuildAppletDemo, Fractal))
+ $(eval $(call SetupBuildAppletDemo, GraphicsTest))
+ $(eval $(call SetupBuildAppletDemo, NervousText))
+ $(eval $(call SetupBuildAppletDemo, SimpleGraph))
+ $(eval $(call SetupBuildAppletDemo, SortDemo))
+ $(eval $(call SetupBuildAppletDemo, SpreadSheet))
endif
-##################################################################################################
+################################################################################
+# Build normal demos.
-PATTERNS_TO_COPY = .html .txt .properties .js .gif .jpg .theme .data .opt README .c .h .png .ttf .xyz .obj
+COPY_TO_JAR := .html .txt .properties .js .gif .jpg .theme .data .opt .c .h \
+ .png .ttf .xyz .obj README COPYRIGHT
+
+COPY_TO_IMAGE := *.html *.txt *.png *.xml README*
-define SetupDemo
- # Param 1 = Name of the demo
- # Param 2 = Subdirectory of the demo below the demo directory.
- # Param 3 = Additional javac flags.
- # Param 4 = The main class for the jar.
- # Param 5 = Additional source directory.
- # Param 6 = Extra dir below $(JDK_TOPDIR)/src (closed)
- # Param 7 = List of files to copy
- # Param 8 = Base name of jar file. Defaults to $1
- # Param 9 = Exclude list
- # Param 10 = Extra copy patterns
- # Param 11 = Extra manifest attribute
- # Param 12 = Suffix for compiler setup name
+# Setup make rules for building a demo.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+# DEMO_SUBDIR The name of the subdir of the demo, below the demo top dir.
+# EXTRA_SRC_DIR Additional source directory.
+# SRC_SUB_DIR Optional subdir to locate source code in
+# SRC_DIR Alternative source directory to use for the demos.
+# EXCLUDE_FILES Exclude file list
+# JAR_NAME Base name of jar file. Defaults to $1.
+# MAIN_CLASS The main class for the jar. Defaults to $1.
+# EXTRA_COPY_TO_JAR Additional files to copy to jar (as patterns)
+# EXTRA_COPY_TO_IMAGE Additional files to copy to images (as wildcards)
+# EXTRA_MANIFEST_ATTR Extra manifest attribute
+# SKIP_COMPILATION Skip Java compilation iff true
+# DISABLE_SJAVAC Passed to SetupJavaCompilation
+SetupBuildDemo = $(NamedParamsMacroTemplate)
+define SetupBuildDemoBody
+ ifeq ($$($1_SRC_DIR), )
+ $1_SRC_DIR := $(DEMO_SHARE_SRC)
+ endif
- $1_SRC_BASE := $(JDK_TOPDIR)/src/$6demo/share/$2/$1
- # In some demos the source is found in a subdir called src.
- $1_MAIN_SRC := $$(wildcard $$($1_SRC_BASE)/src)
- ifeq ($$($1_MAIN_SRC), )
+ $1_SRC_BASE := $$($1_SRC_DIR)/$$($1_DEMO_SUBDIR)/$1
+
+ # In some demos the source is found in a subdir
+ ifneq ($$($1_SRC_SUB_DIR), )
+ $1_MAIN_SRC := $$($1_SRC_BASE)/$$($1_SRC_SUB_DIR)
+ else
+ # for allmost all
$1_MAIN_SRC := $$($1_SRC_BASE)
endif
- ifneq ($8, )
- $1_JARFILE := $8.jar
- else
- $1_JARFILE := $1.jar
+ # Default is to use demo name as jar file name.
+ ifeq ($$($1_JAR_NAME), )
+ $1_JAR_NAME := $1
endif
- ifeq ($(findstring $1,Laffy SwingSet3), )
- $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_$1, \
- SETUP := GENERATE_USINGJDKBYTECODE, \
- ADD_JAVAC_FLAGS := $3, \
- SRC := $$($1_MAIN_SRC) $5, \
- BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/$2/$1, \
- COPY := $(PATTERNS_TO_COPY) $(10), \
- JAR := $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/$$($1_JARFILE), \
- JARMAIN := $4, \
- MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \
- EXTRA_MANIFEST_ATTR := $(11), \
- SRCZIP := $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/src.zip, \
- EXCLUDE_FILES := $9, \
- DISABLE_SJAVAC := $(12)))
-
- BUILD_DEMOS += $$(BUILD_DEMO_$1) \
- $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/$$($1_JARFILE) \
- $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/src.zip
+ # Default is to use demo name as jar main class.
+ ifeq ($$($1_MAIN_CLASS), )
+ $1_MAIN_CLASS := $1
+ else ifeq ($$($1_MAIN_CLASS), NONE)
+ $1_MAIN_CLASS :=
+ $1_EXTRA_MANIFEST_ATTR += Main-Class: \n
endif
- # Copy files.
- $1_COPY_TARGETS := $$(patsubst $$($1_SRC_BASE)/%, \
- $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/%, \
- $$(wildcard $$(addprefix $$($1_SRC_BASE)/, $7)))
- ifneq ($7, )
- $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/%: $$($1_SRC_BASE)/%
- $$(call install-file)
- $(CHMOD) -f ug+w $$@
+ ifneq ($$($1_SKIP_COMPILATION), true)
+ $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_$1, \
+ SETUP := GENERATE_USINGJDKBYTECODE, \
+ SRC := $$($1_MAIN_SRC) $$($1_EXTRA_SRC_DIR), \
+ BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/$$($1_DEMO_SUBDIR)/$1, \
+ COPY := $(COPY_TO_JAR) $$($1_EXTRA_COPY_TO_JAR), \
+ JAR := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1/$$($1_JAR_NAME).jar, \
+ JARMAIN := $$($1_MAIN_CLASS), \
+ MANIFEST := $(DEMO_MANIFEST), \
+ EXTRA_MANIFEST_ATTR := $$($1_EXTRA_MANIFEST_ATTR), \
+ SRCZIP := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1/src.zip, \
+ EXCLUDE_FILES := $$($1_EXCLUDE_FILES), \
+ DISABLE_SJAVAC := $$($1_DISABLE_SJAVAC), \
+ ))
- BUILD_DEMOS += $$($1_COPY_TARGETS)
+ $1 += $$(BUILD_DEMO_$1)
endif
+ # Copy files. Sort is needed to remove duplicates.
+ $1_COPY_FILES := $$(sort $$(wildcard $$(addprefix $$($1_SRC_BASE)/, \
+ $(COPY_TO_IMAGE) $$($1_EXTRA_COPY_TO_IMAGE))))
+ $$(eval $$(call SetupCopyFiles, COPY_DEMO_$1, \
+ SRC := $$($1_SRC_BASE), \
+ DEST := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1, \
+ FILES := $$($1_COPY_FILES), \
+ ))
+
+ $1 += $$(COPY_DEMO_$1)
+
+ TARGETS += $$($1)
endef
-$(eval $(call SetupDemo,CodePointIM,jfc,,CodePointIM,,,*.html))
-$(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.services: \
- $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar \
- $(DEMO_SHARE_SRC)/jfc/CodePointIM/java.awt.im.spi.InputMethodDescriptor
- (cd $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM && \
- $(MKDIR) -p _the.tmp/META-INF/services && \
- $(CP) $(DEMO_SHARE_SRC)/jfc/CodePointIM/java.awt.im.spi.InputMethodDescriptor _the.tmp/META-INF/services && \
- cd ./_the.tmp && \
- $(JAR) uf $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar META-INF/services/java.awt.im.spi.InputMethodDescriptor && \
- cd ./META-INF/services && \
- $(JAR) uf $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar java.awt.im.spi.InputMethodDescriptor)
- $(RM) -r $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.tmp
- $(TOUCH) $@
+CODEPOINT_SERVICE := java.awt.im.spi.InputMethodDescriptor
+CODEPOINT_METAINF_SERVICE_FILE := \
+ $(SUPPORT_OUTPUTDIR)/demos/classes/jfc/CodePointIM/META-INF/services/$(CODEPOINT_SERVICE)
-BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.services
+$(eval $(call SetupBuildDemo, CodePointIM, \
+ DEMO_SUBDIR := jfc, \
+ EXTRA_COPY_TO_JAR := $(CODEPOINT_SERVICE), \
+))
+
+# We also need to copy the CODEPOINT_SERVICE file to the META-INF/services
+# location, and make sure the jar depends on that file to get it included.
+$(CODEPOINT_METAINF_SERVICE_FILE): $(DEMO_SHARE_SRC)/jfc/CodePointIM/$(CODEPOINT_SERVICE)
+ $(call install-file)
+
+$(BUILD_DEMO_CodePointIM_JAR): $(CODEPOINT_METAINF_SERVICE_FILE)
ifneq ($(OPENJDK_TARGET_OS), solaris)
- $(eval $(call SetupDemo,MoleculeViewer,applets,,XYZChemModel,,,example*.html *.java))
- $(eval $(call SetupDemo,WireFrame,applets,,ThreeD,,,example*.html *.java))
- $(eval $(call SetupDemo,SwingApplet,jfc,,SwingApplet,,,README* *.html))
-endif
-$(eval $(call SetupDemo,FileChooserDemo,jfc,,FileChooserDemo,,,README*))
-$(eval $(call SetupDemo,Font2DTest,jfc,,Font2DTest,,,*.html *.txt))
-$(eval $(call SetupDemo,Metalworks,jfc,,Metalworks,,,README*))
-$(eval $(call SetupDemo,Notepad,jfc,,Notepad,,,README*))
-$(eval $(call SetupDemo,SampleTree,jfc,,SampleTree,,,README*))
-$(eval $(call SetupDemo,TableExample,jfc,,TableExample,,,README*))
-$(eval $(call SetupDemo,TransparentRuler,jfc,,transparentruler.Ruler,,,README*))
-$(eval $(call SetupDemo,jconsole-plugin,scripting,,,,,*.xml *.txt,,,,Main-Class: \n))
-$(eval $(call SetupDemo,FullThreadDump,management,,FullThreadDump,,,README*))
-$(eval $(call SetupDemo,JTop,management,,JTop,,,README*))
-$(eval $(call SetupDemo,MemoryMonitor,management,,MemoryMonitor,,,README*))
-$(eval $(call SetupDemo,VerboseGC,management,,VerboseGC,,,README*))
+ $(eval $(call SetupBuildDemo, MoleculeViewer, \
+ DEMO_SUBDIR := applets, \
+ MAIN_CLASS := XYZChemModel, \
+ EXTRA_COPY_TO_IMAGE := *.java, \
+ ))
-ifndef OPENJDK
- $(eval $(call SetupDemo,Laffy,jfc,,,,closed/,*))
- $(eval $(call SetupDemo,SwingSet3,jfc,,,,closed/,*))
+ $(eval $(call SetupBuildDemo, WireFrame, \
+ DEMO_SUBDIR := applets, \
+ MAIN_CLASS := ThreeD, \
+ EXTRA_COPY_TO_IMAGE := *.java, \
+ ))
- $(eval $(call SetupDemo,Java2D,jfc,,java2d.Java2Demo,,closed/,*.html README*,Java2Demo))
- $(eval $(call SetupDemo,Stylepad,jfc,,Stylepad, \
- $(DEMO_SHARE_SRC)/jfc/Notepad,closed/,*.txt,,$(DEMO_SHARE_SRC)/jfc/Notepad/README.txt))
- $(eval $(call SetupDemo,SwingSet2,jfc,,SwingSet2,,closed/,README* *.html,,,.java COPYRIGHT, \
- SplashScreen-Image: resources/images/splash.png,true))
-
- BUILD_DEMOS += $(patsubst $(DEMO_CLOSED_SHARE_SRC)/nbproject/%, \
- $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \
- $(call CacheFind, $(DEMO_CLOSED_SHARE_SRC)/nbproject))
-
- $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%: $(DEMO_CLOSED_SHARE_SRC)/nbproject/%
- $(call install-file)
- $(CHMOD) -f ug+w $@
+ $(eval $(call SetupBuildDemo, SwingApplet, \
+ DEMO_SUBDIR := jfc, \
+ ))
endif
-##################################################################################################
+$(eval $(call SetupBuildDemo, FileChooserDemo, \
+ DEMO_SUBDIR := jfc, \
+))
+
+$(eval $(call SetupBuildDemo, Font2DTest, \
+ DEMO_SUBDIR := jfc, \
+))
+
+$(eval $(call SetupBuildDemo, Metalworks, \
+ DEMO_SUBDIR := jfc, \
+))
+
+$(eval $(call SetupBuildDemo, Notepad, \
+ DEMO_SUBDIR := jfc, \
+))
-# In the old makefiles, j2dbench was not compiled.
-#$(eval $(call SetupDemo,J2DBench, java2d, /src, , j2dbench/J2DBench))
+$(eval $(call SetupBuildDemo, SampleTree, \
+ DEMO_SUBDIR := jfc, \
+))
+
+$(eval $(call SetupBuildDemo, TableExample, \
+ DEMO_SUBDIR := jfc, \
+))
+
+$(eval $(call SetupBuildDemo, TransparentRuler, \
+ DEMO_SUBDIR := jfc, \
+ MAIN_CLASS := transparentruler.Ruler, \
+))
+
+$(eval $(call SetupBuildDemo, jconsole-plugin, \
+ DEMO_SUBDIR := scripting, \
+ SRC_SUB_DIR := src, \
+ MAIN_CLASS := NONE, \
+))
+
+$(eval $(call SetupBuildDemo, FullThreadDump, \
+ DEMO_SUBDIR := management, \
+))
-# JVMTI demos are a bit strange and share some files, but be careful the
-# shared files are just the *.c and *.h files, not the README or sample
-# makefiles. So we always exclude the README.txt and sample.makefile.txt
-# from the extra sources.
-define SetupJVMTIDemo
- # Param 1 = Name of the demo
- # Param 2 = add these directories to the includes, default is agent_util
- # Param 3 = extra CFLAGS
- # Param 4 = C or C++ (defaults to C)
- # Param 5 = libs for unix
- # Param 6 = libs for windows
- # Param 7 = libs for solaris
- # Param 8 = libs for linux
- # Param 9 = extra directories with required sources
- # Param 10 = DISABLED_WARNINGS_gcc
- # Param 11 = DISABLED_WARNINGS_microsoft
- # Param 12 = DISABLED_WARNINGS_clang
- BUILD_DEMO_JVMTI_$1_EXTRA_SRC := \
- $$(wildcard $(DEMO_OS_TYPE_SRC)/jvmti/$1) \
- $$(wildcard $$(addprefix $(DEMO_SHARE_SRC)/jvmti/, $2)) \
- $9
- BUILD_DEMO_JVMTI_$1_EXTRA_SRC_EXCLUDE := \
- $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, $2)) \
- $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, $2))
- BUILD_DEMO_JVMTI_$1_EXTRA_INC := $$(addprefix -I, $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC))
- ifeq (C++, $4)
- BUILD_DEMO_JVMTI_$1_TOOLCHAIN := TOOLCHAIN_LINK_CXX
- $1_EXTRA_CXX := $(LDFLAGS_CXX_JDK) $(LIBCXX)
+$(eval $(call SetupBuildDemo, JTop, \
+ DEMO_SUBDIR := management, \
+))
+
+$(eval $(call SetupBuildDemo, MemoryMonitor, \
+ DEMO_SUBDIR := management, \
+))
+
+$(eval $(call SetupBuildDemo, VerboseGC, \
+ DEMO_SUBDIR := management, \
+))
+
+################################################################################
+# Build JVMTI demos.
+
+# Setup make rules for building a JVMTI demo.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+# EXTRA_SRC_SUBDIR Also include these subdirectories
+# TOOLCHAIN Optionally specify toolchain to use
+SetupBuildJvmtiDemo = $(NamedParamsMacroTemplate)
+define SetupBuildJvmtiDemoBody
+ $1_SRC := \
+ $(DEMO_SHARE_SRC)/jvmti/$1 \
+ $$(wildcard $$(addprefix $(DEMO_SHARE_SRC)/jvmti/, \
+ agent_util $$($1_EXTRA_SRC_SUBDIR)))
+
+ ### Build the native lib
+ $1_CFLAGS_INCLUDE := $$(addprefix -I, $$($1_SRC))
+
+ $1_CXXFLAGS := $$($1_CFLAGS_INCLUDE) $(CXXFLAGS_JDKLIB) $(CXXFLAGS_DEBUG_SYMBOLS)
+
+ ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX)
+ # For C++, we also need some special treatment.
+ $1_LDFLAGS := $(LDFLAGS_CXX_JDK)
+ $1_LIBS := $(LIBCXX)
+
+ ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
+ $1_CXXFLAGS := $$(filter-out -xregs=no%appl, $$($1_CXXFLAGS))
+ endif
endif
- $1_CXXFLAGS := $(CXXFLAGS_JDKLIB) -I$(DEMO_SHARE_SRC)/jvmti/$1 \
- $$(BUILD_DEMO_JVMTI_$1_EXTRA_INC) $3 \
- $(CXXFLAGS_DEBUG_SYMBOLS)
- ifeq ($1-$(OPENJDK_TARGET_CPU_ARCH), waiters-sparc)
- $1_FILTER := -xregs=no%appl
- $1_CXXFLAGS := $$(filter-out $$($1_FILTER), $$($1_CXXFLAGS))
- endif
-
- # Workaround for CFLAGS_JDKLIB containing ',' on solaris. If this is added as 'CFLAGS' to the
- # eval call below, the comma gets expanded too early.
- BUILD_DEMO_JVMTI_$1_CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_DEBUG_SYMBOLS) \
- -I$(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_INC) $3
-
# Remove the -incremental:no setting to get .ilk-files like in the old build.
- $$(eval $$(call SetupNativeCompilation,BUILD_DEMO_JVMTI_$1, \
- SRC := $(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC), \
- TOOLCHAIN := $$(BUILD_DEMO_JVMTI_$1_TOOLCHAIN), \
+ $$(eval $$(call SetupNativeCompilation, BUILD_DEMO_JVMTI_NATIVE_$1, \
+ SRC := $$($1_SRC), \
+ TOOLCHAIN := $$($1_TOOLCHAIN), \
OPTIMIZATION := LOW, \
+ CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \
CXXFLAGS := $$($1_CXXFLAGS), \
- DISABLED_WARNINGS_gcc := $(10), \
- DISABLED_WARNINGS_clang := $(12), \
- DISABLED_WARNINGS_microsoft := $(11), \
- LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)), \
+ LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)) \
+ $$($1_LDFLAGS), \
LDFLAGS_macosx := $(call SET_EXECUTABLE_ORIGIN), \
- LIBS := $$($1_EXTRA_CXX), \
- LIBS_unix := $5, \
- LIBS_linux := $8, \
- LIBS_solaris := $7 -lc, \
- LIBS_windows := $6, \
+ LIBS := $$($1_LIBS), \
+ LIBS_solaris := -lc, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $$(RC_FLAGS) \
-D "JDK_FNAME=$1.dll" \
-D "JDK_INTERNAL_NAME=$1" \
-D "JDK_FTYPE=0x2L", \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1, \
- OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib, \
- LIBRARY := $1))
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib, \
+ LIBRARY := $1, \
+ ))
+
+ $1 += $$(BUILD_DEMO_JVMTI_NATIVE_$1)
+
+ ### Build the jar, if we have java sources
+ ifneq ($$(wildcard $(DEMO_SHARE_SRC)/jvmti/$1/*.java), )
+ $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_JVMTI_JAVA_$1, \
+ SETUP := GENERATE_USINGJDKBYTECODE, \
+ SRC := $(DEMO_SHARE_SRC)/jvmti/$1, \
+ BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jvmti/$1, \
+ COPY := $(COPY_TO_JAR), \
+ JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/$1.jar, \
+ EXTRA_MANIFEST_ATTR := Main-Class: \n, \
+ MANIFEST := $(DEMO_MANIFEST), \
+ ))
- $$(eval $$(call SetupZipArchive,BUILD_DEMO_JVMTI_SRC_$1, \
- SRC := $(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC), \
- EXCLUDE_FILES := $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC_EXCLUDE), \
- ZIP := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/src.zip))
+ $1 += $$(BUILD_DEMO_JVMTI_JAVA_$1_JAR)
+ endif
+
+ ### Build the source zip
+ $1_EXCLUDE_FILES := \
+ $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, \
+ agent_util $$($1_EXTRA_SRC_SUBDIR))) \
+ $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, \
+ agent_util $$($1_EXTRA_SRC_SUBDIR)))
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/README.txt: $(DEMO_SHARE_SRC)/jvmti/$1/README.txt
+ $$(eval $$(call SetupZipArchive, BUILD_DEMO_JVMTI_SRC_$1, \
+ SRC := $$($1_SRC), \
+ EXCLUDE_FILES := $$($1_EXCLUDE_FILES), \
+ ZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/src.zip, \
+ ))
+
+ $1 += $$(BUILD_DEMO_JVMTI_SRC_$1)
+
+ # Copy files to image
+ $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt: $(DEMO_SHARE_SRC)/jvmti/$1/README.txt
$$(call install-file)
$(CHMOD) -f ug+w $$@
- ifneq (, $$(wildcard $(DEMO_SHARE_SRC)/jvmti/$1/*.java))
- $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_JVMTI_$1_JAVA, \
- SETUP := GENERATE_USINGJDKBYTECODE, \
- SRC := $(DEMO_SHARE_SRC)/jvmti/$1, \
- BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/jvmti/$1, \
- COPY := $(PATTERNS_TO_COPY), \
- JAR := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/$1.jar, \
- EXTRA_MANIFEST_ATTR := Main-Class: \n, \
- MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf))
+ $1 += $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt
+
+ ifeq ($(OPENJDK_TARGET_OS), windows)
+ # These lib and exp files normally end up in OBJECT_DIR but for demos they
+ # are supposed to be included in the distro. Since they are created as
+ # a side-effect of the library compilation, make does not know about them.
+ $1_SUPPORT_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1
+ $1_IMAGE_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib
- BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/$1.jar
+ $$($1_SUPPORT_OUTPUTDIR)/$1.lib: $$(BUILD_DEMO_JVMTI_NATIVE_$1)
+
+ $$($1_SUPPORT_OUTPUTDIR)/$1.exp: $$(BUILD_DEMO_JVMTI_NATIVE_$1)
+
+ $$($1_IMAGE_OUTPUTDIR)/$1.lib: $$($1_SUPPORT_OUTPUTDIR)/$1.lib
+ $$(call install-file)
+
+ $$($1_IMAGE_OUTPUTDIR)/$1.exp: $$($1_SUPPORT_OUTPUTDIR)/$1.exp
+ $$(call install-file)
+
+ $1 += $$($1_IMAGE_OUTPUTDIR)/$1.lib $$($1_IMAGE_OUTPUTDIR)/$1.exp
endif
- BUILD_DEMOS += $$(BUILD_DEMO_JVMTI_$1) \
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/src.zip \
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/README.txt
-
- ifeq ($(OPENJDK_TARGET_OS), windows)
- # These files normally end up in OBJECT_DIR but for demos they
- # are supposed to be included in the distro.
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.lib: $$(BUILD_DEMO_JVMTI_$1)
- $(CP) $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1/$1.lib $$@
-
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.exp: $$(BUILD_DEMO_JVMTI_$1)
- $(CP) $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1/$1.exp $$@
-
- BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.lib \
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.exp
- endif
+ TARGETS += $$($1)
endef
-$(eval $(call SetupJVMTIDemo,compiledMethodLoad, agent_util))
-$(eval $(call SetupJVMTIDemo,gctest, agent_util))
-$(eval $(call SetupJVMTIDemo,heapTracker, agent_util java_crw_demo))
-$(eval $(call SetupJVMTIDemo,heapViewer, agent_util))
-$(eval $(call SetupJVMTIDemo,minst, agent_util java_crw_demo))
-$(eval $(call SetupJVMTIDemo,mtrace, agent_util java_crw_demo))
-$(eval $(call SetupJVMTIDemo,waiters, agent_util, , C++))
-$(eval $(call SetupJVMTIDemo,versionCheck, agent_util))
+$(eval $(call SetupBuildJvmtiDemo, compiledMethodLoad))
+$(eval $(call SetupBuildJvmtiDemo, gctest))
+$(eval $(call SetupBuildJvmtiDemo, heapViewer))
+$(eval $(call SetupBuildJvmtiDemo, versionCheck))
+
+$(eval $(call SetupBuildJvmtiDemo, heapTracker, \
+ EXTRA_SRC_SUBDIR := java_crw_demo, \
+))
+
+$(eval $(call SetupBuildJvmtiDemo, minst, \
+ EXTRA_SRC_SUBDIR := java_crw_demo, \
+))
-##################################################################################################
+$(eval $(call SetupBuildJvmtiDemo, mtrace, \
+ EXTRA_SRC_SUBDIR := java_crw_demo, \
+))
-$(SUPPORT_OUTPUTDIR)/demo/image/management/index.html: $(DEMO_SHARE_SRC)/management/index.html
- $(call install-file)
- $(CHMOD) -f ug+w $@
+$(eval $(call SetupBuildJvmtiDemo, waiters, \
+ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+))
-$(SUPPORT_OUTPUTDIR)/demo/image/jvmti/index.html: $(DEMO_SHARE_SRC)/jvmti/index.html
- $(call install-file)
- $(CHMOD) -f ug+w $@
+################################################################################
+# Build the Poller demo (on Solaris only).
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+ DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris
-BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/management/index.html \
- $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/index.html
+ $(eval $(call SetupJavaCompilation, BUILD_DEMO_JAVA_Poller, \
+ SETUP := GENERATE_USINGJDKBYTECODE, \
+ SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
+ BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
+ HEADERS := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
+ JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/Poller.jar, \
+ MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf, \
+ SRCZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/src.zip, \
+ COPY := README.txt Poller.c, \
+ JARMAIN := Client, \
+ ))
-##################################################################################################
+ TARGETS += $(BUILD_DEMO_JAVA_Poller)
-# The netbeans project files are copied into the demo directory.
-ifeq ($(OPENJDK_TARGET_OS), solaris)
- BUILD_DEMOS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \
- $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \
- $(filter-out $(DEMO_SHARE_SRC)/nbproject/jfc/SwingApplet%, \
- $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject)))
-else
- BUILD_DEMOS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \
- $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \
- $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject))
-endif
+ $(eval $(call SetupNativeCompilation, BUILD_DEMO_NATIVE_Poller, \
+ SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) \
+ -I$(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
+ LDFLAGS := $(LDFLAGS_JDKLIB), \
+ LIBS_solaris := -lc, \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native, \
+ LIBRARY := Poller, \
+ ))
-$(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%: $(DEMO_SHARE_SRC)/nbproject/%
+ TARGETS += $(BUILD_DEMO_NATIVE_Poller)
+
+ # We can only compile native code after java has been compiled (since we
+ # depend on generated .h files)
+ $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller/Poller.o: \
+ $(BUILD_DEMO_JAVA_POLLER_COMPILE_TARGETS)
+
+ # Copy to image
+ $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt: \
+ $(DEMO_SOLARIS_SRC)/jni/Poller/README.txt
$(call install-file)
$(CHMOD) -f ug+w $@
-##################################################################################################
+ TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt
-$(SUPPORT_OUTPUTDIR)/demo/image/README: $(DEMO_SHARE_SRC)/README
+ $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so: \
+ $(SUPPORT_OUTPUTDIR)/demos/native/libPoller.so
$(call install-file)
-BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/README
-
-##################################################################################################
+ TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so
+endif
-ifeq ($(OPENJDK_TARGET_OS), solaris)
+################################################################################
+# Copy html and README files.
- $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/%: $(DEMO_SOLARIS_SRC)/jni/Poller/%
+$(SUPPORT_OUTPUTDIR)/demos/image/management/index.html: $(DEMO_SHARE_SRC)/management/index.html
$(call install-file)
$(CHMOD) -f ug+w $@
- $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/README.txt: $(DEMO_SOLARIS_SRC)/jni/Poller/README.txt
+$(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html: $(DEMO_SHARE_SRC)/jvmti/index.html
$(call install-file)
$(CHMOD) -f ug+w $@
- $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar: \
- $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/README.txt \
- $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/Poller.c
-
- $(eval $(call SetupJavaCompilation,BUILD_DEMO_POLLER_JAR, \
- SETUP := GENERATE_USINGJDKBYTECODE, \
- SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
- BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \
- HEADERS := $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \
- JAR := $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar, \
- MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \
- SRCZIP := $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/src.zip, \
- COPY := README.txt Poller.c, \
- JARMAIN := Client))
-
-
-
- BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar \
- $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/src.zip \
- $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/README.txt
-
- $(eval $(call SetupNativeCompilation,BUILD_LIBPOLLER, \
- SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
- OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) \
- -I$(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \
- LDFLAGS := $(LDFLAGS_JDKLIB), \
- LIBS_solaris := -lc, \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native/jni/Poller, \
- OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native, \
- LIBRARY := Poller))
-
- #
- # We can only compile native code after jar has been build (since we depend on generated .h files)
- #
- $(SUPPORT_OUTPUTDIR)/demo/native/jni/Poller/Poller.o: $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar
-
- $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX): \
- $(SUPPORT_OUTPUTDIR)/demo/native/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX)
+$(SUPPORT_OUTPUTDIR)/demos/image/README: $(DEMO_SHARE_SRC)/README
$(call install-file)
- BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX)
+TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/management/index.html \
+ $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html \
+ $(SUPPORT_OUTPUTDIR)/demos/image/README
+
+################################################################################
+# Copy netbeans project files.
+$(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%: $(DEMO_SHARE_SRC)/nbproject/%
+ $(call install-file)
+ $(CHMOD) -f ug+w $@
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+ TARGETS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \
+ $(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%, \
+ $(filter-out $(DEMO_SHARE_SRC)/nbproject/jfc/SwingApplet%, \
+ $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject)))
+else
+ TARGETS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \
+ $(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%, \
+ $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject))
endif
-##################################################################################################
-
-ifndef OPENJDK
- DB_ZIP_DIR := $(wildcard $(JDK_TOPDIR)/src/closed/db)
- DB_DEMO_ZIPFILE := $(wildcard $(DB_ZIP_DIR)/*.zip)
-
- $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped: $(DB_DEMO_ZIPFILE)
- $(MKDIR) -p $(@D)
- $(RM) -r $(SUPPORT_OUTPUTDIR)/demo/image/db $(SUPPORT_OUTPUTDIR)/demo/image/demo
- $(CD) $(SUPPORT_OUTPUTDIR)/demo/image && $(UNZIP) -q -o $<
- $(MV) $(SUPPORT_OUTPUTDIR)/demo/image/db-derby-*-bin/demo $(SUPPORT_OUTPUTDIR)/demo/image/db
- $(CD) $(SUPPORT_OUTPUTDIR)/demo/image && $(RM) -r db-derby-*-bin
- $(TOUCH) $@
+################################################################################
- # Copy this after the unzip above to avoid race with directory creation and mv command.
- $(SUPPORT_OUTPUTDIR)/demo/image/db/README-JDK-DEMOS.html: \
- $(DB_ZIP_DIR)/README-JDK-DEMOS.html \
- | $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped
- $(MKDIR) -p $(@D)
- $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(DB_ZIP_DIR)/COPYRIGHTYEAR)/" > $@
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, CompileDemos.gmk))
- BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped $(SUPPORT_OUTPUTDIR)/demo/image/db/README-JDK-DEMOS.html
-endif
-
-##################################################################################################
-
-all: $(BUILD_DEMOS)
+all: $(TARGETS)
.PHONY: all
--- a/jdk/make/gendata/GendataPolicyJars.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/gendata/GendataPolicyJars.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -27,7 +27,7 @@
include $(SPEC)
include MakeBase.gmk
-include JavaCompilation.gmk
+include JarArchive.gmk
################################################################################
@@ -57,7 +57,7 @@
endif
#
-# TODO fix so that SetupArchive does not write files into SRCS
+# TODO fix so that SetupJarArchive does not write files into SRCS
# then we don't need this extra copying
#
# NOTE: We currently do not place restrictions on our limited export
@@ -76,13 +76,14 @@
US_EXPORT_POLICY_JAR_DEPS := \
$(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
-$(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, \
+$(eval $(call SetupJarArchive, BUILD_US_EXPORT_POLICY_JAR, \
DEPENDENCIES := $(US_EXPORT_POLICY_JAR_DEPS), \
SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
SUFFIXES := .policy, \
JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \
EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true))
+ SKIP_METAINF := true, \
+))
$(US_EXPORT_POLICY_JAR_LIMITED): \
$(US_EXPORT_POLICY_JAR_UNLIMITED)
@@ -122,7 +123,7 @@
$(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar
#
-# TODO fix so that SetupArchive does not write files into SRCS
+# TODO fix so that SetupJarArchive does not write files into SRCS
# then we don't need this extra copying
#
LOCAL_POLICY_JAR_LIMITED_TMP := \
@@ -138,22 +139,24 @@
$(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/%
$(install-file)
-$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_LIMITED, \
+$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_LIMITED, \
DEPENDENCIES := $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \
$(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \
SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \
SUFFIXES := .policy, \
JAR := $(LOCAL_POLICY_JAR_LIMITED), \
EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \
- SKIP_METAINF := true))
+ SKIP_METAINF := true, \
+))
-$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_UNLIMITED, \
+$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_UNLIMITED, \
DEPENDENCIES := $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \
SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \
SUFFIXES := .policy, \
JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \
EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true))
+ SKIP_METAINF := true, \
+))
TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED)
--- a/jdk/make/launcher/Launcher-java.base.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.base.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,32 +25,51 @@
include LauncherCommon.gmk
+JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common
+ifdef OPENJDK
+ JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+else
+ JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+endif
+
################################################################################
# On windows, the debuginfo files get the same name as for java.dll. Build
# into another dir and copy selectively so debuginfo for java.dll isn't
# overwritten.
-$(eval $(call SetupLauncher,java, \
- -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES,,,user32.lib comctl32.lib, \
- $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jli_static.lib, $(JAVA_RC_FLAGS), \
- $(JAVA_VERSION_INFO_RESOURCE), $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs,true))
+$(eval $(call SetupBuildLauncher, java, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \
+ LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \
+ LIBS_windows := user32.lib comctl32.lib, \
+ RC_FLAGS := $(JAVA_RC_FLAGS), \
+ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \
+ OPTIMIZATION := HIGH, \
+ WINDOWS_STATIC_LINK := true, \
+ NO_JAVA_MS := true, \
+))
$(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX): $(BUILD_LAUNCHER_java)
$(MKDIR) -p $(@D)
$(RM) $@
- $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs$(OUTPUT_SUBDIR)/java$(EXE_SUFFIX) $@
+ $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs/java$(EXE_SUFFIX) $@
TARGETS += $(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX)
ifeq ($(OPENJDK_TARGET_OS), windows)
- $(eval $(call SetupLauncher,javaw, \
- -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES,,,user32.lib comctl32.lib, \
- $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jli_static.lib, $(JAVA_RC_FLAGS), \
- $(JAVA_VERSION_INFO_RESOURCE),,true))
+ $(eval $(call SetupBuildLauncher, javaw, \
+ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \
+ LIBS_windows := user32.lib comctl32.lib, \
+ RC_FLAGS := $(JAVA_RC_FLAGS), \
+ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \
+ WINDOWS_STATIC_LINK := true, \
+ NO_JAVA_MS := true, \
+ ))
endif
-$(eval $(call SetupLauncher,keytool, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.keytool.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, keytool, \
+ MAIN_CLASS := sun.security.tools.keytool.Main, \
+))
################################################################################
--- a/jdk/make/launcher/Launcher-java.corba.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.corba.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,23 +25,26 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,idlj, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.corba.se.idl.toJavaPortable.Compile"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, idlj, \
+ MAIN_CLASS := com.sun.tools.corba.se.idl.toJavaPortable.Compile, \
+))
-$(eval $(call SetupLauncher,orbd, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
- "-J-Dcom.sun.CORBA.activation.DbDir=./orb.db"$(COMMA) \
- "-J-Dcom.sun.CORBA.activation.Port=1049"$(COMMA) \
- "-J-Dcom.sun.CORBA.POA.ORBServerId=1"$(COMMA) \
- "com.sun.corba.se.impl.activation.ORBD"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, orbd, \
+ MAIN_CLASS := com.sun.corba.se.impl.activation.ORBD, \
+ JAVA_ARGS := \
+ -Dcom.sun.CORBA.activation.DbDir=./orb.db \
+ -Dcom.sun.CORBA.activation.Port=1049 \
+ -Dcom.sun.CORBA.POA.ORBServerId=1, \
+))
-$(eval $(call SetupLauncher,servertool, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.corba.se.impl.activation.ServerTool"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, servertool, \
+ MAIN_CLASS := com.sun.corba.se.impl.activation.ServerTool, \
+))
-$(eval $(call SetupLauncher,tnameserv, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
- "-J-Dcom.sun.CORBA.activation.DbDir=./orb.db"$(COMMA) \
- "-J-Djava.util.logging.LoggingPermission=contol"$(COMMA) \
- "-J-Dcom.sun.CORBA.POA.ORBServerId=1"$(COMMA) \
- "com.sun.corba.se.impl.naming.cosnaming.TransientNameServer"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, tnameserv, \
+ MAIN_CLASS := com.sun.corba.se.impl.naming.cosnaming.TransientNameServer, \
+ JAVA_ARGS := \
+ -Dcom.sun.CORBA.activation.DbDir=./orb.db \
+ -Djava.util.logging.LoggingPermission=contol \
+ -Dcom.sun.CORBA.POA.ORBServerId=1, \
+))
--- a/jdk/make/launcher/Launcher-java.desktop.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.desktop.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,8 @@
$(eval $(call IncludeCustomExtension, jdk, launcher/Launcher-java.desktop.gmk))
ifndef BUILD_HEADLESS_ONLY
- $(eval $(call SetupLauncher,appletviewer, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.applet.Main"$(COMMA) }',, \
- $(XLIBS)))
+ $(eval $(call SetupBuildLauncher, appletviewer, \
+ MAIN_CLASS := sun.applet.Main, \
+ LIBS_unix := $(X_LIBS), \
+ ))
endif
-
--- a/jdk/make/launcher/Launcher-java.rmi.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.rmi.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,39 +25,10 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,rmid, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.server.Activation"$(COMMA) }'))
-
-$(eval $(call SetupLauncher,rmiregistry, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.registry.RegistryImpl"$(COMMA) }'))
-
-##########################################################################################
+$(eval $(call SetupBuildLauncher, rmid, \
+ MAIN_CLASS := sun.rmi.server.Activation, \
+))
-#
-# The java-rmi.cgi script in bin/ only gets delivered in certain situations
-#
-JAVA_RMI_CGI := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/java-rmi.cgi
-ifeq ($(OPENJDK_TARGET_OS), linux)
- TARGETS += $(JAVA_RMI_CGI)
-endif
-ifeq ($(OPENJDK_TARGET_OS), solaris)
- TARGETS += $(JAVA_RMI_CGI)
-endif
-
-# TODO:
-# On windows java-rmi.cgi shouldn't be bundled since Java 1.2, but has been built all
-# this time anyway. Since jdk6, it has been built from the wrong source and resulted
-# in a (almost) copy of the standard java launcher named "java-rmi.exe" ending up in
-# the final images bin dir. This weird behavior is mimicked here in the converted
-# makefiles for now. Should probably just be deleted.
-# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6512052
-ifeq ($(OPENJDK_TARGET_OS), windows)
- $(eval $(call SetupLauncher,java-rmi, , \
- $(call SET_SHARED_LIBRARY_MAPFILE,$(JDK_TOPDIR)/make/java/main/java/mapfile-$(OPENJDK_TARGET_CPU)),,,,,,,,,RMI))
-else
- $(JAVA_RMI_CGI): $(JDK_TOPDIR)/src/java.rmi/unix/bin/java-rmi.cgi.sh
- $(call install-file)
- $(CHMOD) a+x $@
-endif
-
-##########################################################################################
+$(eval $(call SetupBuildLauncher, rmiregistry, \
+ MAIN_CLASS := sun.rmi.registry.RegistryImpl, \
+))
--- a/jdk/make/launcher/Launcher-java.scripting.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.scripting.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,6 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jrunscript, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.script.shell.Main"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, jrunscript, \
+ MAIN_CLASS := com.sun.tools.script.shell.Main, \
+))
--- a/jdk/make/launcher/Launcher-java.security.jgss.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-java.security.jgss.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -26,13 +26,15 @@
include LauncherCommon.gmk
ifeq ($(OPENJDK_TARGET_OS), windows)
- $(eval $(call SetupLauncher,kinit, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Kinit"$(COMMA) }'))
+ $(eval $(call SetupBuildLauncher, kinit, \
+ MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \
+ ))
- $(eval $(call SetupLauncher,klist, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Klist"$(COMMA) }'))
+ $(eval $(call SetupBuildLauncher, klist, \
+ MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \
+ ))
- $(eval $(call SetupLauncher,ktab, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Ktab"$(COMMA) }'))
+ $(eval $(call SetupBuildLauncher, ktab, \
+ MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \
+ ))
endif
-
--- a/jdk/make/launcher/Launcher-jdk.compiler.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,26 +25,30 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,javac, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javac.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, javac, \
+ MAIN_CLASS := com.sun.tools.javac.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
-$(eval $(call SetupLauncher,javah, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javah.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, javah, \
+ MAIN_CLASS := com.sun.tools.javah.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
-$(eval $(call SetupLauncher,serialver, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.serialver.SerialVer"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, serialver, \
+ MAIN_CLASS := sun.tools.serialver.SerialVer, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
+))
ifeq ($(ENABLE_SJAVAC), yes)
# Build sjavac directly to the exploded image so that it does not get included
# into any real images
- $(eval $(call SetupLauncher,sjavac, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.sjavac.Main"$(COMMA) }',,,,,,, \
- $(JDK_OUTPUTDIR)/bin))
+ $(eval $(call SetupBuildLauncher, sjavac, \
+ MAIN_CLASS := com.sun.tools.sjavac.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+ OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \
+ ))
endif
--- a/jdk/make/launcher/Launcher-jdk.dev.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.dev.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,5 +25,6 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jimage,\
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.tools.jimage.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jimage,\
+ MAIN_CLASS := jdk.tools.jimage.Main, \
+))
--- a/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,13 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jsadebugd, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.jvm.hotspot.jdi.SADebugServer"$(COMMA) }' \
- ,,,,,,,,,Info-privileged.plist))
+$(eval $(call SetupBuildLauncher, jsadebugd, \
+ MAIN_CLASS := sun.jvm.hotspot.jdi.SADebugServer, \
+ MACOSX_SIGNED := true, \
+))
-$(eval $(call SetupLauncher,jhsdb, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.jvm.hotspot.SALauncher"$(COMMA) }' \
- ,,,,,,,,,Info-privileged.plist))
-
+$(eval $(call SetupBuildLauncher, jhsdb, \
+ MAIN_CLASS := sun.jvm.hotspot.SALauncher, \
+ MACOSX_SIGNED := true, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jartool.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jartool.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,8 +25,10 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jar, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jar.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jar, \
+ MAIN_CLASS := sun.tools.jar.Main, \
+))
-$(eval $(call SetupLauncher,jarsigner, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.jarsigner.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jarsigner, \
+ MAIN_CLASS := sun.security.tools.jarsigner.Main, \
+))
--- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,javadoc, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javadoc.Main"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, javadoc, \
+ MAIN_CLASS := com.sun.tools.javadoc.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jcmd.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jcmd.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,36 +25,41 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jinfo, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \
- "sun.tools.jinfo.JInfo"$(COMMA) }' \
- -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
- ,,,,,,,,,Info-privileged.plist))
+$(eval $(call SetupBuildLauncher, jinfo, \
+ MAIN_CLASS := sun.tools.jinfo.JInfo, \
+ JAVA_ARGS := \
+ -Dsun.jvm.hotspot.debugger.useProcDebugger \
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
+ APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \
+ MACOSX_SIGNED := true, \
+))
-$(eval $(call SetupLauncher,jmap, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \
- "sun.tools.jmap.JMap"$(COMMA) }' \
- -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
- ,,,,,,,,,Info-privileged.plist))
+$(eval $(call SetupBuildLauncher, jmap, \
+ MAIN_CLASS := sun.tools.jmap.JMap, \
+ JAVA_ARGS := \
+ -Dsun.jvm.hotspot.debugger.useProcDebugger \
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
+ APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \
+ MACOSX_SIGNED := true, \
+))
-$(eval $(call SetupLauncher,jps, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jps.Jps"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jps, \
+ MAIN_CLASS := sun.tools.jps.Jps, \
+))
-$(eval $(call SetupLauncher,jstack, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \
- "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \
- "sun.tools.jstack.JStack"$(COMMA) }' \
- -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
- ,,,,,,,,,Info-privileged.plist))
+$(eval $(call SetupBuildLauncher, jstack, \
+ MAIN_CLASS := sun.tools.jstack.JStack, \
+ JAVA_ARGS := \
+ -Dsun.jvm.hotspot.debugger.useProcDebugger \
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
+ APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \
+ MACOSX_SIGNED := true, \
+))
-$(eval $(call SetupLauncher,jstat, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jstat.Jstat"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jstat, \
+ MAIN_CLASS := sun.tools.jstat.Jstat, \
+))
-$(eval $(call SetupLauncher,jcmd, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jcmd.JCmd"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, jcmd, \
+ MAIN_CLASS := sun.tools.jcmd.JCmd, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jconsole.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jconsole.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,9 +25,10 @@
include LauncherCommon.gmk
-BUILD_LAUNCHER_jconsole_CFLAGS_windows := -DJAVAW
-BUILD_LAUNCHER_jconsole_LIBS_windows := user32.lib
-
-$(eval $(call SetupLauncher,jconsole, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "-J-Djconsole.showOutputViewer"$(COMMA) "sun.tools.jconsole.JConsole"$(COMMA) }' \
- -DAPP_CLASSPATH='{ "/lib/jconsole.jar"$(COMMA) "/lib/tools.jar"$(COMMA) "/classes" }'))
+$(eval $(call SetupBuildLauncher, jconsole, \
+ MAIN_CLASS := sun.tools.jconsole.JConsole, \
+ JAVA_ARGS := -Djconsole.showOutputViewer, \
+ APP_CLASSPATH := /lib/jconsole.jar /lib/tools.jar /classes, \
+ CFLAGS_windows := -DJAVAW, \
+ LIBS_windows := user32.lib, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,12 +25,14 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,javap, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javap.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, javap, \
+ MAIN_CLASS := com.sun.tools.javap.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
-$(eval $(call SetupLauncher,jdeps, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.jdeps.Main"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jdeps, \
+ MAIN_CLASS := com.sun.tools.jdeps.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jdi.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jdi.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jdb, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.example.debug.tty.TTY"$(COMMA) }' \
- -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }'))
-
+$(eval $(call SetupBuildLauncher, jdb, \
+ MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \
+ APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jshell.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jshell.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,7 +25,8 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jshell, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.internal.jshell.tool.JShellTool"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, jshell, \
+ MAIN_CLASS := jdk.internal.jshell.tool.JShellTool, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jvmstat.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.jvmstat.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,6 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jstatd, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jstatd.Jstatd"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, jstatd, \
+ MAIN_CLASS := sun.tools.jstatd.Jstatd, \
+))
--- a/jdk/make/launcher/Launcher-jdk.pack200.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -25,8 +25,9 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,pack200, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.java.util.jar.pack.Driver"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, pack200, \
+ MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
+))
################################################################################
# The order of the object files on the link command line affects the size of the resulting
@@ -92,7 +93,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
LIBS_solaris := -lc, \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE), \
PROGRAM := unpack200, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/jdk/make/launcher/Launcher-jdk.policytool.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.policytool.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,8 @@
include LauncherCommon.gmk
ifndef BUILD_HEADLESS_ONLY
- $(eval $(call SetupLauncher,policytool, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.policytool.PolicyTool"$(COMMA) }',, \
- $(XLIBS)))
+ $(eval $(call SetupBuildLauncher, policytool, \
+ MAIN_CLASS := sun.security.tools.policytool.PolicyTool, \
+ LIBS_unix := $(X_LIBS), \
+ ))
endif
--- a/jdk/make/launcher/Launcher-jdk.rmic.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.rmic.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,rmic, \
- -DEXPAND_CLASSPATH_WILDCARDS \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.rmic.Main"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, rmic, \
+ MAIN_CLASS := sun.rmi.rmic.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
+))
--- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jjs, \
- -DENABLE_ARG_FILES \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.nashorn.tools.jjs.Main"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, jjs, \
+ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
+ CFLAGS := -DENABLE_ARG_FILES, \
+))
--- a/jdk/make/launcher/Launcher-jdk.xml.bind.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.xml.bind.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,10 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,schemagen, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.jxc.SchemaGenerator"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, schemagen, \
+ MAIN_CLASS := com.sun.tools.internal.jxc.SchemaGenerator, \
+))
-$(eval $(call SetupLauncher,xjc, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.xjc.Driver"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, xjc, \
+ MAIN_CLASS := com.sun.tools.internal.xjc.Driver, \
+))
--- a/jdk/make/launcher/Launcher-jdk.xml.ws.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.xml.ws.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,10 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,wsgen, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.ws.WsGen"$(COMMA) }'))
+$(eval $(call SetupBuildLauncher, wsgen, \
+ MAIN_CLASS := com.sun.tools.internal.ws.WsGen, \
+))
-$(eval $(call SetupLauncher,wsimport, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.ws.WsImport"$(COMMA) }'))
-
+$(eval $(call SetupBuildLauncher, wsimport, \
+ MAIN_CLASS := com.sun.tools.internal.ws.WsImport, \
+))
--- a/jdk/make/launcher/LauncherCommon.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/launcher/LauncherCommon.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -28,28 +28,17 @@
# Prepare the find cache.
$(eval $(call FillCacheFind, $(JDK_TOPDIR)/src/java.base/share/native/launcher))
-# When building a legacy overlay image (on solaris 64 bit), the launchers
-# need to be built with a different rpath and a different output dir.
-ifeq ($(OVERLAY_IMAGES), true)
- ORIGIN_ROOT := /../..
- OUTPUT_SUBDIR := $(OPENJDK_TARGET_CPU_ISADIR)
-else
- ORIGIN_ROOT := /..
-endif
-
ifeq ($(OPENJDK_TARGET_OS), macosx)
ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN)
else
- ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli)
-endif
+ ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli)
-#
-# Applications expect to be able to link against libjawt without invoking
-# System.loadLibrary("jawt") first. This was the behaviour described in the
-# devloper documentation of JAWT and what worked with OpenJDK6.
-#
-ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
- ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR))
+ # Applications expect to be able to link against libjawt without invoking
+ # System.loadLibrary("jawt") first. This was the behaviour described in the
+ # devloper documentation of JAWT and what worked with OpenJDK6.
+ ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
+ ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR))
+ endif
endif
LAUNCHER_SRC := $(JDK_TOPDIR)/src/java.base/share/native/launcher
@@ -61,51 +50,78 @@
GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
JAVA_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/launcher/java.rc
MACOSX_PLIST_DIR := $(JDK_TOPDIR)/src/java.base/macosx/native/launcher
-# Until the shuffle is permanent, we can't add this in configure
-CFLAGS_JDKEXE := $(filter-out %javavm/export, $(CFLAGS_JDKEXE))
-CFLAGS_JDKEXE += -I$(JDK_TOPDIR)/src/java.base/share/native/include \
- -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include
-CXXFLAGS_JDKEXE := $(filter-out %javavm/export, $(CXXFLAGS_JDKEXE))
-CXXFLAGS_JDKEXE += -I$(JDK_TOPDIR)/src/java.base/share/native/include \
- -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include
JAVA_MANIFEST := $(JDK_TOPDIR)/src/java.base/windows/native/launcher/java.manifest
-define SetupLauncher
- # TODO: Fix mapfile on solaris. Won't work with ld as linker.
- # Parameter 1 is the name of the launcher (java, javac, jar...)
- # Parameter 2 is extra CFLAGS
- # Parameter 3 is extra LDFLAGS
- # Parameter 4 is extra LIBS_unix
- # Parameter 5 is extra LIBS_windows
- # Parameter 6 is optional Windows JLI library (full path)
- # Parameter 7 is optional Windows resource (RC) flags
- # Parameter 8 is optional Windows version resource file (.rc)
- # Parameter 9 is different output dir
- # Parameter 10 if set, link statically with c runtime on windows.
- # Parameter 11 if set, override plist file on macosx.
- $(call LogSetupMacroEntry,SetupLauncher($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11))
- $(if $(13),$(error Internal makefile error: Too many arguments to SetupLauncher, please update CompileLaunchers.gmk))
+################################################################################
+# Build standard launcher.
- $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib
- ifneq ($6, )
- $1_WINDOWS_JLI_LIB := $6
- endif
- $1_VERSION_INFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE)
- ifneq ($8, )
- $1_VERSION_INFO_RESOURCE := $8
+# Setup make rules for building a standard launcher.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name. It is also
+# used as the name of the executable.
+#
+# Remaining parameters are named arguments. These include:
+# MAIN_CLASS The Java main class to launch
+# JAVA_ARGS Processed into a -DJAVA_ARGS C flag
+# APP_CLASSPATH Processed into a -DAPP_CLASSPATH C flag
+# CFLAGS Additional CFLAGS
+# CFLAGS_windows Additional CFLAGS_windows
+# LIBS_unix Additional LIBS_unix
+# LIBS_windows Additional LIBS_windows
+# LDFLAGS_solaris Additional LDFLAGS_solaris
+# RC_FLAGS Additional RC_FLAGS
+# MACOSX_SIGNED On macosx, sign this binary
+# WINDOWS_STATIC_LINK On windows, link statically with C runtime and libjli.
+# OPTIMIZATION Override default optimization level (LOW)
+# OUTPUT_DIR Override default output directory
+# VERSION_INFO_RESOURCE Override default Windows resource file
+# NO_JAVA_MS Do not add -ms8m to JAVA_ARGS.
+SetupBuildLauncher = $(NamedParamsMacroTemplate)
+define SetupBuildLauncherBody
+ # Setup default values (unless overridden)
+ ifeq ($$($1_VERSION_INFO_RESOURCE), )
+ $1_VERSION_INFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE)
endif
- $1_LDFLAGS := $3
+ ifeq ($$($1_OUTPUT_DIR), )
+ $1_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)
+ endif
+
+ ifeq ($$($1_OPTIMIZATION), )
+ $1_OPTIMIZATION := LOW
+ endif
+
+ ifneq ($$($1_NO_JAVA_MS), true)
+ # The norm is to append -ms8m, unless otherwise instructed.
+ $1_JAVA_ARGS += -ms8m
+ endif
+
+ ifneq ($$($1_JAVA_ARGS), )
+ $1_JAVA_ARGS_STR := '{ $$(strip $$(foreach a, \
+ $$(addprefix -J, $$($1_JAVA_ARGS)) $$($1_MAIN_CLASS), "$$a"$(COMMA) )) }'
+ $1_CFLAGS += -DJAVA_ARGS=$$($1_JAVA_ARGS_STR)
+ endif
+
+ ifneq ($$($1_APP_CLASSPATH), )
+ $1_APP_CLASSPATH_STR := '{ $$(strip $$(foreach a, \
+ $$($1_APP_CLASSPATH), "$$a"$(COMMA) )) }'
+ # Remove the trailing comma
+ $1_APP_CLASSPATH_STR := $$(strip $$(subst $$(COMMA) }', }', \
+ $$($1_APP_CLASSPATH_STR)))
+ $1_CFLAGS += -DAPP_CLASSPATH=$$($1_APP_CLASSPATH_STR)
+ endif
+
$1_LIBS :=
ifeq ($(OPENJDK_TARGET_OS), macosx)
- $1_PLIST_FILE := Info-cmdline.plist
- ifneq ($(11), )
- $1_PLIST_FILE := $(11)
- ifneq ($$(findstring privileged, $$($1_PLIST_FILE)), )
+ ifeq ($$($1_MACOSX_SIGNED), true)
+ $1_PLIST_FILE := Info-privileged.plist
$1_CODESIGN := true
- endif
+ else
+ $1_PLIST_FILE := Info-cmdline.plist
endif
+ $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"'
$1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \
-sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE)
$1_LIBS += -framework Cocoa -framework Security \
@@ -121,22 +137,12 @@
$1_LIBS += -lz
endif
- $1_OUTPUT_DIR_ARG := $9
- ifeq (, $$($1_OUTPUT_DIR_ARG))
- $1_OUTPUT_DIR_ARG := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)
- endif
-
- # TODO: maybe it's better to move this if-statement out of this function
- ifeq ($1, java)
- $1_OPTIMIZATION_ARG := HIGH
- $1_LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR)
+ ifeq ($$($1_WINDOWS_STATIC_LINK), true)
+ $1_CFLAGS += $(filter-out -MD, $(CFLAGS_JDKEXE))
+ $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib
else
- $1_OPTIMIZATION_ARG := LOW
- endif
-
- $1_CFLAGS := $(CFLAGS_JDKEXE)
- ifeq ($(10), true)
- $1_CFLAGS := $(filter-out -MD, $(CFLAGS_JDKEXE))
+ $1_CFLAGS += $(CFLAGS_JDKEXE)
+ $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib
endif
# The linker on older SuSE distros (e.g. on SLES 10) complains with:
@@ -156,22 +162,23 @@
endif
endif
- $(call SetupNativeCompilation,BUILD_LAUNCHER_$1, \
+ $$(eval $$(call SetupNativeCompilation, BUILD_LAUNCHER_$1, \
SRC := $(LAUNCHER_SRC), \
INCLUDE_FILES := main.c, \
- OPTIMIZATION := $$($1_OPTIMIZATION_ARG), \
+ OPTIMIZATION := $$($1_OPTIMIZATION), \
CFLAGS := $$($1_CFLAGS) \
$(LAUNCHER_CFLAGS) \
-DFULL_VERSION='"$(FULL_VERSION)"' \
-DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
-DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"' \
-DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \
- -DPROGNAME='"$1"' $(DPACKAGEPATH) \
- $2, \
+ -DPROGNAME='"$1"' \
+ $$($1_CFLAGS), \
CFLAGS_linux := -fPIC, \
CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \
+ CFLAGS_windows := $$($1_CFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKEXE) \
- $(ORIGIN_ARG) \
+ $$(ORIGIN_ARG) \
$$($1_LDFLAGS), \
LDFLAGS_linux := \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
@@ -182,27 +189,29 @@
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
MAPFILE := $$($1_MAPFILE), \
LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
- LIBS_unix := $4, \
+ LIBS_unix := $$($1_LIBS_unix), \
LIBS_linux := -lpthread -ljli $(LIBDL) -lc, \
LIBS_solaris := -ljli -lthread $(LIBDL) -lc, \
LIBS_windows := $$($1_WINDOWS_JLI_LIB) \
- $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib advapi32.lib $5, \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/$1_objs$(OUTPUT_SUBDIR), \
- OUTPUT_DIR := $$($1_OUTPUT_DIR_ARG)$(OUTPUT_SUBDIR), \
+ $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib advapi32.lib \
+ $$($1_LIBS_windows), \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/$1_objs, \
+ OUTPUT_DIR := $$($1_OUTPUT_DIR), \
PROGRAM := $1, \
DEBUG_SYMBOLS := true, \
VERSIONINFO_RESOURCE := $$($1_VERSION_INFO_RESOURCE), \
- RC_FLAGS := $(RC_FLAGS) \
+ RC_FLAGS := $$(RC_FLAGS) \
-D "JDK_FNAME=$1$(EXE_SUFFIX)" \
-D "JDK_INTERNAL_NAME=$1" \
-D "JDK_FTYPE=0x1L" \
- $7, \
+ $$($1_RC_FLAGS), \
MANIFEST := $(JAVA_MANIFEST), \
MANIFEST_VERSION := $(JDK_VERSION_FOR_MANIFEST), \
CODESIGN := $$($1_CODESIGN), \
- )
+ ))
- TARGETS += $$(BUILD_LAUNCHER_$1)
+ $1 += $$(BUILD_LAUNCHER_$1)
+ TARGETS += $$($1)
ifneq (,$(filter $(OPENJDK_TARGET_OS), macosx aix))
$$(BUILD_LAUNCHER_$1): $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a
@@ -213,18 +222,3 @@
$$($1_WINDOWS_JLI_LIB)
endif
endef
-
-##########################################################################################
-
-XLIBS := $(X_LIBS) -lX11
-ifeq ($(OPENJDK_TARGET_OS), macosx)
- DPACKAGEPATH := -DPACKAGE_PATH='"$(PACKAGE_PATH)"'
- XLIBS :=
-endif
-
-JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common
-ifdef OPENJDK
- JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
-else
- JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
-endif
--- a/jdk/make/lib/Awt2dLibraries.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -890,9 +890,9 @@
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsplashscreen/mapfile-vers, \
LDFLAGS := $(LIBSPLASHSCREEN_LDFLAGS) $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
- LIBS := $(LIBSPLASHSCREEN_LIBS) $(LIBZ) \
+ LIBS := $(JDKLIB_LIBS) $(LIBSPLASHSCREEN_LIBS) $(LIBZ) \
$(GIFLIB_LIBS) $(LIBJPEG_LIBS) $(PNG_LIBS), \
- LIBS_solaris := -lc, \
+ LIBS_aix := -liconv, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=splashscreen.dll" \
--- a/jdk/make/lib/CoreLibraries.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -139,6 +139,12 @@
endif
endif
+ifeq ($(OPENJDK_TARGET_OS), linux)
+ ifeq ($(OPENJDK_TARGET_CPU), x86_64)
+ BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM)
+ endif
+endif
+
$(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
LIBRARY := java, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
--- a/jdk/make/lib/Lib-java.instrument.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/lib/Lib-java.instrument.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -68,10 +68,11 @@
LDFLAGS_macosx := -Xlinker -all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
LDFLAGS_windows := -export:Agent_OnAttach, \
+ LIBS := $(JDKLIB_LIBS), \
LIBS_unix := -ljava $(LIBZ), \
LIBS_linux := -ljli $(LIBDL), \
- LIBS_solaris := -ljli $(LIBDL) -lc, \
- LIBS_aix := -ljli_static $(LIBDL),\
+ LIBS_solaris := -ljli $(LIBDL), \
+ LIBS_aix := -liconv -ljli_static $(LIBDL), \
LIBS_macosx := -liconv -framework Cocoa -framework Security \
-framework ApplicationServices, \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \
--- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -84,10 +84,11 @@
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdwp/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
+ LIBS := $(JDKLIB_LIBS), \
LIBS_linux := $(LIBDL), \
- LIBS_solaris := $(LIBDL) -lc, \
+ LIBS_solaris := $(LIBDL), \
LIBS_macosx := -liconv, \
- LIBS_windows := $(JDKLIB_LIBS), \
+ LIBS_aix := -liconv, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=jdwp.dll" \
--- a/jdk/src/java.base/share/classes/java/lang/Byte.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Byte.java Wed Jul 05 20:59:18 2017 +0200
@@ -463,6 +463,22 @@
}
/**
+ * Compares two {@code byte} values numerically treating the values
+ * as unsigned.
+ *
+ * @param x the first {@code byte} to compare
+ * @param y the second {@code byte} to compare
+ * @return the value {@code 0} if {@code x == y}; a value less
+ * than {@code 0} if {@code x < y} as unsigned values; and
+ * a value greater than {@code 0} if {@code x > y} as
+ * unsigned values
+ * @since 9
+ */
+ public static int compareUnsigned(byte x, byte y) {
+ return Byte.toUnsignedInt(x) - Byte.toUnsignedInt(y);
+ }
+
+ /**
* Converts the argument to an {@code int} by an unsigned
* conversion. In an unsigned conversion to an {@code int}, the
* high-order 24 bits of the {@code int} are zero and the
--- a/jdk/src/java.base/share/classes/java/lang/Deprecated.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Deprecated.java Wed Jul 05 20:59:18 2017 +0200
@@ -36,7 +36,7 @@
*
* <p>Use of the @Deprecated annotation on a local variable
* declaration or on a parameter declaration or a package declaration
- * has no effect.
+ * has no effect on the warnings issued by a compiler.
*
* @author Neal Gafter
* @since 1.5
--- a/jdk/src/java.base/share/classes/java/lang/Short.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Short.java Wed Jul 05 20:59:18 2017 +0200
@@ -468,6 +468,22 @@
}
/**
+ * Compares two {@code short} values numerically treating the values
+ * as unsigned.
+ *
+ * @param x the first {@code short} to compare
+ * @param y the second {@code short} to compare
+ * @return the value {@code 0} if {@code x == y}; a value less
+ * than {@code 0} if {@code x < y} as unsigned values; and
+ * a value greater than {@code 0} if {@code x > y} as
+ * unsigned values
+ * @since 9
+ */
+ public static int compareUnsigned(short x, short y) {
+ return Short.toUnsignedInt(x) - Short.toUnsignedInt(y);
+ }
+
+ /**
* The number of bits used to represent a {@code short} value in two's
* complement binary form.
* @since 1.5
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Wed Jul 05 20:59:18 2017 +0200
@@ -66,15 +66,15 @@
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
private static final String NAME_METHOD_READ_OBJECT = "readObject";
private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
+
+ private static final String DESCR_CLASS = "Ljava/lang/Class;";
+ private static final String DESCR_STRING = "Ljava/lang/String;";
+ private static final String DESCR_OBJECT = "Ljava/lang/Object;";
private static final String DESCR_CTOR_SERIALIZED_LAMBDA
- = MethodType.methodType(void.class,
- Class.class,
- String.class, String.class, String.class,
- int.class, String.class, String.class, String.class,
- String.class,
- Object[].class).toMethodDescriptorString();
- private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
- = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
+ = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I"
+ + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V";
+
+ private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V";
private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Wed Jul 05 20:59:18 2017 +0200
@@ -1187,20 +1187,23 @@
// store them into the implementation-specific final fields.
checkRtype(rtype);
checkPtypes(ptypes);
- UNSAFE.putObject(this, rtypeOffset, rtype);
- UNSAFE.putObject(this, ptypesOffset, ptypes);
+ UNSAFE.putObject(this, OffsetHolder.rtypeOffset, rtype);
+ UNSAFE.putObject(this, OffsetHolder.ptypesOffset, ptypes);
}
- // Support for resetting final fields while deserializing
- private static final long rtypeOffset, ptypesOffset;
- static {
- try {
- rtypeOffset = UNSAFE.objectFieldOffset
- (MethodType.class.getDeclaredField("rtype"));
- ptypesOffset = UNSAFE.objectFieldOffset
- (MethodType.class.getDeclaredField("ptypes"));
- } catch (Exception ex) {
- throw new Error(ex);
+ // Support for resetting final fields while deserializing. Implement Holder
+ // pattern to make the rarely needed offset calculation lazy.
+ private static class OffsetHolder {
+ private static final long rtypeOffset, ptypesOffset;
+ static {
+ try {
+ rtypeOffset = UNSAFE.objectFieldOffset
+ (MethodType.class.getDeclaredField("rtype"));
+ ptypesOffset = UNSAFE.objectFieldOffset
+ (MethodType.class.getDeclaredField("ptypes"));
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
}
}
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Wed Jul 05 20:59:18 2017 +0200
@@ -25,6 +25,8 @@
package java.util;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
@@ -42,7 +44,6 @@
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import jdk.internal.HotSpotIntrinsicCandidate;
/**
* This class contains various methods for manipulating arrays (such as
@@ -2586,6 +2587,55 @@
}
/**
+ * Returns true if the two specified arrays of longs, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of ints are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2615,6 +2665,55 @@
}
/**
+ * Returns true if the two specified arrays of ints, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of shorts are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2644,6 +2743,55 @@
}
/**
+ * Returns true if the two specified arrays of shorts, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of chars are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2674,6 +2822,55 @@
}
/**
+ * Returns true if the two specified arrays of chars, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of bytes are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2703,6 +2900,55 @@
}
/**
+ * Returns true if the two specified arrays of bytes, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of booleans are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2732,6 +2978,55 @@
}
/**
+ * Returns true if the two specified arrays of booleans, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++)
+ if (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of doubles are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2759,9 +3054,70 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (Double.doubleToLongBits(a[i])!=Double.doubleToLongBits(a2[i]))
- return false;
+ for (int i=0; i<length; i++) {
+ double v1 = a[i], v2 = a2[i];
+ if (Double.doubleToRawLongBits(v1) != Double.doubleToRawLongBits(v2))
+ if (!Double.isNaN(v1) || !Double.isNaN(v2))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of doubles, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * <p>Two doubles {@code d1} and {@code d2} are considered equal if:
+ * <pre> {@code new Double(d1).equals(new Double(d2))}</pre>
+ * (Unlike the {@code ==} operator, this method considers
+ * {@code NaN} equals to itself, and 0.0d unequal to -0.0d.)
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @see Double#equals(Object)
+ * @since 9
+ */
+ public static boolean equals(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++) {
+ Double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return false;
+ }
return true;
}
@@ -2794,9 +3150,70 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (Float.floatToIntBits(a[i])!=Float.floatToIntBits(a2[i]))
- return false;
+ for (int i=0; i<length; i++) {
+ float v1 = a[i], v2 = a2[i];
+ if (Float.floatToRawIntBits(v1) != Float.floatToRawIntBits(v2))
+ if (!Float.isNaN(v1) || !Float.isNaN(v2))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of floats, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * <p>Two floats {@code f1} and {@code f2} are considered equal if:
+ * <pre> {@code new Float(f1).equals(new Float(f2))}</pre>
+ * (Unlike the {@code ==} operator, this method considers
+ * {@code NaN} equals to itself, and 0.0f unequal to -0.0f.)
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @see Float#equals(Object)
+ * @since 9
+ */
+ public static boolean equals(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return false;
+ }
return true;
}
@@ -2827,9 +3244,60 @@
return false;
for (int i=0; i<length; i++) {
- Object o1 = a[i];
- Object o2 = a2[i];
- if (!(o1==null ? o2==null : o1.equals(o2)))
+ if (!Objects.equals(a[i], a2[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of Objects, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>Two arrays are considered equal if the number of elements covered by
+ * each range is the same, and all corresponding pairs of elements over the
+ * specified ranges in the two arrays are equal. In other words, two arrays
+ * are equal if they contain, over the specified ranges, the same elements
+ * in the same order.
+ *
+ * <p>Two objects {@code e1} and {@code e2} are considered <i>equal</i> if
+ * {@code Objects.equals(e1, e2)}.
+ *
+ * @param a the first array to be tested for equality
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested fro equality
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return {@code true} if the two arrays, over the specified ranges, are
+ * equal
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static boolean equals(Object[] a, int aFromIndex, int aToIndex,
+ Object[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++) {
+ if (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
return false;
}
@@ -5185,4 +5653,3233 @@
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}
-}
+
+
+ // Comparison methods
+
+ // Compare boolean
+
+ /**
+ * Compares two {@code boolean} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Boolean#compare(boolean, boolean)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(boolean[], boolean[])} for the definition of a
+ * common and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(boolean[], boolean[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Boolean.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(boolean[] a, boolean[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Boolean.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code boolean} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Boolean#compare(boolean, boolean)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(boolean[], int, int, boolean[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(boolean[], int, int, boolean[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ boolean va = a[aFromIndex++];
+ boolean vb = b[bFromIndex++];
+ if (va != vb) return Boolean.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare byte
+
+ /**
+ * Compares two {@code byte} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Byte#compare(byte, byte)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(byte[], byte[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(byte[], byte[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Byte.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Byte.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code byte} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Byte#compare(byte, byte)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(byte[], int, int, byte[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ byte va = a[aFromIndex++];
+ byte vb = b[bFromIndex++];
+ if (va != vb) return Byte.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code byte} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Byte#compareUnsigned(byte, byte)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(byte[], byte[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Byte.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Byte.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+
+ /**
+ * Compares two {@code byte} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Byte#compareUnsigned(byte, byte)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is null
+ * @since 9
+ */
+ public static int compareUnsigned(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ byte va = a[aFromIndex++];
+ byte vb = b[bFromIndex++];
+ if (va != vb) return Byte.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare short
+
+ /**
+ * Compares two {@code short} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Short#compare(short, short)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(short[], short[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(short[], short[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Short.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(short[] a, short[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Short.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Short#compare(short, short)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(short[], int, int, short[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ short va = a[aFromIndex++];
+ short vb = b[bFromIndex++];
+ if (va != vb) return Short.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Short#compareUnsigned(short, short)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(short[], short[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Short.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(short[] a, short[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Short.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Short#compareUnsigned(short, short)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is null
+ * @since 9
+ */
+ public static int compareUnsigned(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ short va = a[aFromIndex++];
+ short vb = b[bFromIndex++];
+ if (va != vb) return Short.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare char
+
+ /**
+ * Compares two {@code char} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Character#compare(char, char)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(char[], char[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(char[], char[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Character.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(char[] a, char[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Character.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code char} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Character#compare(char, char)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(char[], int, int, char[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(char[], int, int, char[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ char va = a[aFromIndex++];
+ char vb = b[bFromIndex++];
+ if (va != vb) return Character.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare int
+
+ /**
+ * Compares two {@code int} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Integer#compare(int, int)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(int[], int[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(int[], int[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Integer.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(int[] a, int[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Integer.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Integer#compare(int, int)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(int[], int, int, int[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ int va = a[aFromIndex++];
+ int vb = b[bFromIndex++];
+ if (va != vb) return Integer.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Integer#compareUnsigned(int, int)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(int[], int[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Integer.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(int[] a, int[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Integer.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Integer#compareUnsigned(int, int)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is null
+ * @since 9
+ */
+ public static int compareUnsigned(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ int va = a[aFromIndex++];
+ int vb = b[bFromIndex++];
+ if (va != vb) return Integer.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare long
+
+ /**
+ * Compares two {@code long} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Long#compare(long, long)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(long[], long[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(long[], long[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Long.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(long[] a, long[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Long.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Long#compare(long, long)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(long[], int, int, long[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ long va = a[aFromIndex++];
+ long vb = b[bFromIndex++];
+ if (va != vb) return Long.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Long#compareUnsigned(long, long)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(long[], long[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Long.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(long[] a, long[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Long.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Long#compareUnsigned(long, long)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is null
+ * @since 9
+ */
+ public static int compareUnsigned(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ long va = a[aFromIndex++];
+ long vb = b[bFromIndex++];
+ if (va != vb) return Long.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare float
+
+ /**
+ * Compares two {@code float} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Float#compare(float, float)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(float[], float[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(float[], float[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Float.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(float[] a, float[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ float va = a[i], vb = b[i];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
+ int c = Float.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code float} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Float#compare(float, float)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(float[], int, int, float[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(float[], int, int, float[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
+ int c = Float.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare double
+
+ /**
+ * Compares two {@code double} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Double#compare(double, double)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(double[], double[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(double[], double[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Double.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(double[] a, double[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ double va = a[i], vb = b[i];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
+ int c = Double.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code double} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Double#compare(double, double)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(double[], int, int, double[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(double[], int, int, double[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int compare(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
+ int c = Double.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare objects
+
+ /**
+ * Compares two {@code Object} arrays, within comparable elements,
+ * lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements of type {@code T} at
+ * an index {@code i} within the respective arrays that is the prefix
+ * length, as if by:
+ * <pre>{@code
+ * Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+ * compare(a[i], b[i])
+ * }</pre>
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ * A {@code null} array element is considered lexicographically than a
+ * non-{@code null} array element. Two {@code null} array elements are
+ * considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(Object[], Object[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references
+ * and elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return a[i].compareTo(b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @param <T> the type of comparable array elements
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static <T extends Comparable<? super T>> int compare(T[] a, T[] b) {
+ if (a == b)
+ return 0;
+ // A null array is less than a non-null array
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // A null element is less than a non-null element
+ if (oa == null || ob == null)
+ return oa == null ? -1 : 1;
+ int v = oa.compareTo(ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements of type {@code T} at a relative index {@code i} within the
+ * respective arrays that is the prefix length, as if by:
+ * <pre>{@code
+ * Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+ * compare(a[aFromIndex + i, b[bFromIndex + i])
+ * }</pre>
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(Object[], int, int, Object[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return a[aFromIndex + i].compareTo(b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @param <T> the type of comparable array elements
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static <T extends Comparable<? super T>> int compare(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ if (oa == null || ob == null)
+ return oa == null ? -1 : 1;
+ int v = oa.compareTo(ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically using a specified
+ * comparator.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing with the specified comparator two
+ * elements at an index within the respective arrays that is the prefix
+ * length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b, cmp);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return cmp.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @throws NullPointerException if the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int compare(T[] a, T[] b,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing with the
+ * specified comparator two elements at a relative index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex, cmp);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return cmp.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array or the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int compare(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+
+ // Mismatch methods
+
+ // Mismatch boolean
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code boolean} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(boolean[] a, boolean[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code boolean} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch byte
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code byte}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(byte[] a, byte[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code byte} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch char
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code char}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(char[] a, char[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code char} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch short
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code short}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(short[] a, short[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code short} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch int
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code int}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(int[] a, int[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code int} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch long
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code long}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(long[] a, long[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code long} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch float
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code float}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * Float.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(float[] a, float[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ float va = a[i], vb = b[i];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code float} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * Float.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch double
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code double} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * Double.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(double[] a, double[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ double va = a[i], vb = b[i];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code double} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * Double.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch objects
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code Object} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * !Objects.equals(a[pl], b[pl])
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(Object[] a, Object[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (!Objects.equals(a[i], b[i]))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code Object} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * !Objects.equals(a[aFromIndex + pl], b[bFromIndex + pl])
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(
+ Object[] a, int aFromIndex, int aToIndex,
+ Object[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code Object} arrays, otherwise return -1 if no mismatch is found.
+ * The index will be in the range of 0 (inclusive) up to the length
+ * (inclusive) of the smaller array.
+ *
+ * <p>The specified comparator is used to determine if two array elements
+ * from the each array are not equal.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * IntStream.range(0, pl).
+ * map(i -> cmp.compare(a[i], b[i])).
+ * allMatch(c -> c == 0) &&
+ * cmp.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * IntStream.range(0, Math.min(a.length, b.length)).
+ * map(i -> cmp.compare(a[i], b[i])).
+ * allMatch(c -> c == 0) &&
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array or the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int mismatch(T[] a, T[] b, Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return i;
+ }
+ }
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code Object} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * IntStream.range(0, pl).
+ * map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
+ * allMatch(c -> c == 0) &&
+ * cmp.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * IntStream.range(0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex)).
+ * map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
+ * allMatch(c -> c == 0)
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be tested
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be tested
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be tested
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be tested
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @throws IllegalArgumentException
+ * if {@code aFromIndex > aToIndex} or
+ * if {@code bFromIndex > bToIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code aFromIndex < 0 or aToIndex > a.length} or
+ * if {@code bFromIndex < 0 or bToIndex > b.length}
+ * @throws NullPointerException
+ * if either array or the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int mismatch(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return i;
+ }
+ }
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java Wed Jul 05 20:59:18 2017 +0200
@@ -123,25 +123,27 @@
* <ul>
* <li> "CLDR": A provider based on Unicode Consortium's
* <a href="http://cldr.unicode.org/">CLDR Project</a>.
- * <li> "JRE": represents the locale sensitive services that is compatible
- * with the prior JDK releases (same with JDK8's "JRE").
+ * <li> "COMPAT": represents the locale sensitive services that is compatible
+ * with the prior JDK releases up to JDK8 (same as JDK8's "JRE").
* <li> "SPI": represents the locale sensitive services implementing the subclasses of
* this {@code LocaleServiceProvider} class.
* <li> "HOST": A provider that reflects the user's custom settings in the
* underlying operating system. This provider may not be available, depending
* on the Java Runtime Environment implementation.
+ * <li> "JRE": represents a synonym to "COMPAT". This name
+ * is deprecated and will be removed in the future release of JDK.
* </ul>
* <p>
* For example, if the following is specified in the property:
* <pre>
- * java.locale.providers=SPI,CLDR,JRE
+ * java.locale.providers=SPI,CLDR,COMPAT
* </pre>
* the locale sensitive services in the SPI providers are looked up first. If the
* desired locale sensitive service is not available, then the runtime looks for CLDR,
- * JRE in that order.
+ * COMPAT in that order.
* <p>
- * The default order for looking up the preferred locale providers is "CLDR,JRE",
- * so specifying "CLDR,JRE" is identical to the default behavior. Applications which
+ * The default order for looking up the preferred locale providers is "CLDR,COMPAT",
+ * so specifying "CLDR,COMPAT" is identical to the default behavior. Applications which
* require implementations of the locale sensitive services must explicitly specify
* "SPI" in order for the Java runtime to load them from the classpath.
*
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Wed Jul 05 20:59:18 2017 +0200
@@ -124,6 +124,10 @@
if (order != null && order.length() != 0) {
String[] types = order.split(",");
for (String type : types) {
+ type = type.trim().toUpperCase(Locale.ROOT);
+ if (type.equals("COMPAT")) {
+ type = "JRE";
+ }
try {
Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
if (!typeList.contains(aType)) {
--- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -26,8 +26,7 @@
#include <string.h>
#include "jni.h"
-#include "jni_util.h"
-#include "jdk_util.h"
+
#include "endian.hpp"
#include "imageDecompressor.hpp"
#include "imageFile.hpp"
@@ -39,6 +38,17 @@
extern bool MemoryMapImage;
+/////////////////////////////////////////////////////////////////////////////
+
+// Static function for primitive throw since libjimage is not linked with libjava
+static void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg)
+{
+ jclass cls = (env)->FindClass(name);
+
+ if (cls != 0) /* Otherwise an exception has already been thrown */
+ (env)->ThrowNew(cls, msg);
+}
+
// jdk.internal.jimage /////////////////////////////////////////////////////////
// Java entry to open an image file for sharing.
@@ -446,6 +456,23 @@
jlong size = 0;
jlong ret = 0;
+ if (moduleName == NULL) {
+ ThrowByName(env, "java/lang/NullPointerException", "moduleName");
+ return 0;
+ }
+ if (version == NULL) {
+ ThrowByName(env, "java/lang/NullPointerException", "version");
+ return 0;
+ }
+ if (path == NULL) {
+ ThrowByName(env, "java/lang/NullPointerException", "path");
+ return 0;
+ }
+ if (output_size == NULL) {
+ ThrowByName(env, "java/lang/NullPointerException", "size");
+ return 0;
+ }
+
do {
native_module = env->GetStringUTFChars(moduleName, NULL);
if (native_module == NULL)
@@ -529,25 +556,47 @@
// Store if there is room in the array
// Concatenate to get full path
char fullpath[IMAGE_MAX_PATH];
- fullpath[0] = '\0';
- if (*module != '\0') {
- strncpy(fullpath, "/", IMAGE_MAX_PATH - 1);
- strncat(fullpath, module, IMAGE_MAX_PATH - 1);
- strncat(fullpath, "/", IMAGE_MAX_PATH - 1);
+ size_t moduleLen = strlen(module);
+ size_t packageLen = strlen(package);
+ size_t nameLen = strlen(name);
+ size_t extLen = strlen(extension);
+ size_t index;
+
+ if (1 + moduleLen + 1 + packageLen + 1 + nameLen + 1 + extLen + 1 > IMAGE_MAX_PATH) {
+ ThrowByName(env, "java/lang/InternalError", "concatenated name too long");
+ return true;
}
- if (*package != '\0') {
- strncat(fullpath, package, IMAGE_MAX_PATH - 1);
- strncat(fullpath, "/", IMAGE_MAX_PATH - 1);
+
+ index = 0;
+ if (moduleLen > 0) {
+ fullpath[index++] = '/';
+ memcpy(&fullpath[index], module, moduleLen);
+ index += moduleLen;
+ fullpath[index++] = '/';
}
- strncat(fullpath, name, IMAGE_MAX_PATH - 1);
- if (*extension != '\0') {
- strncat(fullpath, ".", IMAGE_MAX_PATH - 1);
- strncat(fullpath, extension, IMAGE_MAX_PATH - 1);
+ if (packageLen > 0) {
+ memcpy(&fullpath[index], package, packageLen);
+ index += packageLen;
+ fullpath[index++] = '/';
+ }
+ memcpy(&fullpath[index], name, nameLen);
+ index += nameLen;
+ if (extLen > 0) {
+ fullpath[index++] = '.';
+ memcpy(&fullpath[index], extension, extLen);
+ index += extLen;
}
+ fullpath[index++] = '\0';
+
jobject str = env->NewStringUTF(fullpath);
- JNU_CHECK_EXCEPTION_RETURN(env, true);
+ if (env->ExceptionCheck()) {
+ return true;
+ }
+
env->SetObjectArrayElement(vdata->array, vdata->size, str);
- JNU_CHECK_EXCEPTION_RETURN(env, true);
+ if (env->ExceptionCheck()) {
+ return true;
+ }
}
vdata->size++; // always count so the total size is returned
return true;
@@ -584,7 +633,10 @@
jstring module = NULL;
native_package = env->GetStringUTFChars(package_name, NULL);
- JNU_CHECK_EXCEPTION_RETURN(env, NULL);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package);
if (native_module != NULL) {
--- a/jdk/src/java.base/share/native/libjimage/jimage.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -102,14 +102,29 @@
extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* image,
const char* module_name, const char* version, const char* name,
jlong* size) {
- ImageLocation location;
+ // Concatenate to get full path
char fullpath[IMAGE_MAX_PATH];
+ size_t moduleNameLen = strlen(module_name);
+ size_t nameLen = strlen(name);
+ size_t index;
+
+ // TBD: assert(moduleNameLen > 0 && "module name must be non-empty");
+ assert(nameLen > 0 && "name must non-empty");
- // Concatenate to get full path
- strncpy(fullpath, "/", IMAGE_MAX_PATH - 1);
- strncat(fullpath, module_name, IMAGE_MAX_PATH - 1);
- strncat(fullpath, "/", IMAGE_MAX_PATH - 1);
- strncat(fullpath, name, IMAGE_MAX_PATH - 1);
+ // If the concatenated string is too long for the buffer, return not found
+ if (1 + moduleNameLen + 1 + nameLen + 1 > IMAGE_MAX_PATH) {
+ return 0L;
+ }
+
+ index = 0;
+ fullpath[index++] = '/';
+ memcpy(&fullpath[index], module_name, moduleNameLen);
+ index += moduleNameLen;
+ fullpath[index++] = '/';
+ memcpy(&fullpath[index], name, nameLen);
+ index += nameLen;
+ fullpath[index++] = '\0';
+
JImageLocationRef loc =
(JImageLocationRef) ((ImageFileReader*) image)->find_location_index(fullpath, (u8*) size);
return loc;
--- a/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties Wed Jul 05 20:59:18 2017 +0200
@@ -72,6 +72,7 @@
TIFF=image/x-java-image;class=java.awt.Image
RICH_TEXT=text/rtf
HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1
-URL=application/x-java-url;class=java.net.URL,\
- text/uri-list;eoln="\r\n";terminators=1
+URL=application/x-java-url;class=java.net.URL
+FILE_NAME=text/uri-list;eoln="\r\n";terminators=1
+URL=text/uri-list;eoln="\r\n";terminators=1
XPICT=image/x-pict;class=java.io.InputStream
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java Wed Jul 05 20:59:18 2017 +0200
@@ -845,7 +845,7 @@
boolean isDefaultFocusReceiver(final JComponent component) {
if (isDefaultFocusReceiver == null) {
Component defaultFocusReceiver = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy().getDefaultComponent(getTopLevelFocusCycleRootAncestor(component));
- isDefaultFocusReceiver = new Boolean(defaultFocusReceiver != null && defaultFocusReceiver.equals(component));
+ isDefaultFocusReceiver = defaultFocusReceiver != null && defaultFocusReceiver.equals(component);
}
return isDefaultFocusReceiver.booleanValue();
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Wed Jul 05 20:59:18 2017 +0200
@@ -175,7 +175,7 @@
final AccessibleSelection as = ac.getAccessibleSelection();
if (as == null) return Boolean.FALSE;
- return new Boolean(as.isAccessibleChildSelected(index));
+ return as.isAccessibleChildSelected(index);
}
}, c);
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Wed Jul 05 20:59:18 2017 +0200
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,12 +29,13 @@
import java.awt.*;
import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.*;
-import java.util.regex.*;
import java.awt.datatransfer.*;
import sun.awt.datatransfer.*;
@@ -127,51 +129,33 @@
long format, Transferable transferable) throws IOException {
if (format == CF_URL && URL.class.equals(flavor.getRepresentationClass())) {
- String charset = Charset.defaultCharset().name();
- if (transferable != null && transferable.isDataFlavorSupported(javaTextEncodingFlavor)) {
- try {
- charset = new String((byte[]) transferable.getTransferData(javaTextEncodingFlavor), "UTF-8");
- } catch (UnsupportedFlavorException cannotHappen) {
- }
+ String[] strings = dragQueryFile(bytes);
+ if(strings == null || strings.length == 0) {
+ return null;
}
- String xml = new String(bytes, charset);
- // macosx pasteboard returns a property list that consists of one URL
- // let's extract it.
- return new URL(extractURL(xml));
- }
-
- if (format == CF_STRING) {
+ return new URL(strings[0]);
+ } else if(isUriListFlavor(flavor)) {
+ // dragQueryFile works fine with files and url,
+ // it parses and extracts values from property list.
+ // maxosx always returns property list for
+ // CF_URL and CF_FILE
+ String[] strings = dragQueryFile(bytes);
+ if(strings == null) {
+ return null;
+ }
+ bytes = String.join(System.getProperty("line.separator"),
+ strings).getBytes();
+ // now we extracted uri from xml, now we should treat it as
+ // regular string that allows to translate data to target represantation
+ // class by base method
+ format = CF_STRING;
+ } else if (format == CF_STRING) {
bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8");
}
return super.translateBytes(bytes, flavor, format, transferable);
}
- /**
- * Macosx pasteboard returns xml document that contains one URL, for exmple:
- * <pre>
- * {@code
- * <?xml version=\"1.0\" encoding=\"UTF-8\"?>
- * <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
- * <plist version=\"1.0\">
- * <array>
- * <string>file:///path_to_file</string>
- * <string></string>
- * </array>
- * </plist>
- * }
- * </pre>
- */
- private String extractURL(String xml) {
- Pattern urlExtractorPattern = Pattern.compile("<string>(.*)</string>");
- Matcher matcher = urlExtractorPattern.matcher(xml);
- if (matcher.find()) {
- return matcher.group(1);
- } else {
- return null;
- }
- }
-
@Override
protected synchronized Long getFormatForNativeAsLong(String str) {
Long format = predefinedClipboardNameMap.get(str);
@@ -247,6 +231,7 @@
return nativeDragQueryFile(bytes);
}
+
@Override
protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException {
return CImage.getCreator().createImageFromPlatformImageBytes(bytes);
@@ -271,7 +256,7 @@
}
try {
DataFlavor df = new DataFlavor(nat);
- if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) {
+ if (isUriListFlavor(df)) {
return true;
}
} catch (Exception e) {
@@ -279,4 +264,11 @@
}
return false;
}
+
+ private boolean isUriListFlavor(DataFlavor df) {
+ if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) {
+ return true;
+ }
+ return false;
+ }
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Jul 05 20:59:18 2017 +0200
@@ -380,7 +380,7 @@
desktopProperties.put("DnD.Autoscroll.interval", new Integer(50));
desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5));
- desktopProperties.put("DnD.isDragImageSupported", new Boolean(true));
+ desktopProperties.put("DnD.isDragImageSupported", Boolean.TRUE);
// Register DnD cursors
desktopProperties.put("DnD.Cursor.CopyDrop", new NamedCursor("DnD.Cursor.CopyDrop"));
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m Wed Jul 05 20:59:18 2017 +0200
@@ -26,6 +26,7 @@
#import "AWT_debug.h"
#import "jni_util.h"
+#import "ThreadUtilities.h"
#import <JavaNativeFoundation/JavaNativeFoundation.h>
@@ -114,17 +115,20 @@
{
if (flags == kCGDisplayBeginConfigurationFlag) return;
- JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) {
- JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo;
+ [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
+
+ JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) {
+ JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo;
- jobject graphicsEnv = [wrapper jObjectWithEnv:env];
- if (graphicsEnv == NULL) return; // ref already GC'd
- static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
- static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V");
- JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
- (jint) display,
- (jboolean) flags & kCGDisplayRemoveFlag);
- });
+ jobject graphicsEnv = [wrapper jObjectWithEnv:env];
+ if (graphicsEnv == NULL) return; // ref already GC'd
+ static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
+ static JNF_MEMBER_CACHE(jm_displayReconfiguration,
+ jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V");
+ JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
+ (jint) display, (jboolean) flags & kCGDisplayRemoveFlag);
+ });
+ }];
}
/*
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m Wed Jul 05 20:59:18 2017 +0200
@@ -233,6 +233,7 @@
}
NSOpenGLPixelFormatAttribute attrs[] = {
+ NSOpenGLPFAAllowOfflineRenderers,
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java Wed Jul 05 20:59:18 2017 +0200
@@ -247,11 +247,11 @@
node.appendChild(subNode);
subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing");
- subNode.setAttribute("value", "" + (1 / xPixelsPerMeter * 1000));
+ subNode.setAttribute("value", "" + (1000.0F / xPixelsPerMeter));
node.appendChild(subNode);
subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing");
- subNode.setAttribute("value", "" + (1 / yPixelsPerMeter * 1000));
+ subNode.setAttribute("value", "" + (1000.0F / yPixelsPerMeter));
node.appendChild(subNode);
return node;
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java Wed Jul 05 20:59:18 2017 +0200
@@ -312,7 +312,7 @@
* @see GraphicsConfiguration
* @see #getGraphicsConfiguration
*/
- private transient GraphicsConfiguration graphicsConfig = null;
+ private transient volatile GraphicsConfiguration graphicsConfig;
/**
* A reference to a <code>BufferStrategy</code> object
@@ -1143,9 +1143,7 @@
* @since 1.3
*/
public GraphicsConfiguration getGraphicsConfiguration() {
- synchronized(getTreeLock()) {
- return getGraphicsConfiguration_NoClientCode();
- }
+ return getGraphicsConfiguration_NoClientCode();
}
final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() {
@@ -3622,18 +3620,17 @@
}
/**
- * Creates an off-screen drawable image
- * to be used for double buffering.
- * @param width the specified width
- * @param height the specified height
- * @return an off-screen drawable image, which can be used for double
- * buffering. The return value may be <code>null</code> if the
- * component is not displayable. This will always happen if
- * <code>GraphicsEnvironment.isHeadless()</code> returns
- * <code>true</code>.
+ * Creates an off-screen drawable image to be used for double buffering.
+ *
+ * @param width the specified width
+ * @param height the specified height
+ * @return an off-screen drawable image, which can be used for double
+ * buffering. The {@code null} value if the component is not
+ * displayable or {@code GraphicsEnvironment.isHeadless()} returns
+ * {@code true}.
* @see #isDisplayable
* @see GraphicsEnvironment#isHeadless
- * @since 1.0
+ * @since 1.0
*/
public Image createImage(int width, int height) {
ComponentPeer peer = this.peer;
@@ -3646,19 +3643,19 @@
}
/**
- * Creates a volatile off-screen drawable image
- * to be used for double buffering.
- * @param width the specified width.
- * @param height the specified height.
- * @return an off-screen drawable image, which can be used for double
- * buffering. The return value may be <code>null</code> if the
- * component is not displayable. This will always happen if
- * <code>GraphicsEnvironment.isHeadless()</code> returns
- * <code>true</code>.
+ * Creates a volatile off-screen drawable image to be used for double
+ * buffering.
+ *
+ * @param width the specified width
+ * @param height the specified height
+ * @return an off-screen drawable image, which can be used for double
+ * buffering. The {@code null} value if the component is not
+ * displayable or {@code GraphicsEnvironment.isHeadless()} returns
+ * {@code true}.
* @see java.awt.image.VolatileImage
* @see #isDisplayable
* @see GraphicsEnvironment#isHeadless
- * @since 1.4
+ * @since 1.4
*/
public VolatileImage createVolatileImage(int width, int height) {
ComponentPeer peer = this.peer;
@@ -3674,22 +3671,26 @@
}
/**
- * Creates a volatile off-screen drawable image, with the given capabilities.
- * The contents of this image may be lost at any time due
- * to operating system issues, so the image must be managed
- * via the <code>VolatileImage</code> interface.
- * @param width the specified width.
- * @param height the specified height.
- * @param caps the image capabilities
- * @exception AWTException if an image with the specified capabilities cannot
- * be created
- * @return a VolatileImage object, which can be used
- * to manage surface contents loss and capabilities.
+ * Creates a volatile off-screen drawable image, with the given
+ * capabilities. The contents of this image may be lost at any time due to
+ * operating system issues, so the image must be managed via the
+ * {@code VolatileImage} interface.
+ *
+ * @param width the specified width
+ * @param height the specified height
+ * @param caps the image capabilities
+ * @return a VolatileImage object, which can be used to manage surface
+ * contents loss and capabilities. The {@code null} value if the
+ * component is not displayable or
+ * {@code GraphicsEnvironment.isHeadless()} returns {@code true}.
+ * @throws AWTException if an image with the specified capabilities cannot
+ * be created
* @see java.awt.image.VolatileImage
* @since 1.4
*/
public VolatileImage createVolatileImage(int width, int height,
- ImageCapabilities caps) throws AWTException {
+ ImageCapabilities caps)
+ throws AWTException {
// REMIND : check caps
return createVolatileImage(width, height);
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Window.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java Wed Jul 05 20:59:18 2017 +0200
@@ -347,7 +347,7 @@
* @see #getOpacity()
* @since 1.7
*/
- private float opacity = 1.0f;
+ private volatile float opacity = 1.0f;
/**
* The shape assigned to this window. This field is set to {@code null} if
@@ -1040,9 +1040,7 @@
closeSplashScreen();
Dialog.checkShouldBeBlocked(this);
super.show();
- synchronized (getTreeLock()) {
- this.locationByPlatform = false;
- }
+ locationByPlatform = false;
for (int i = 0; i < ownedWindowList.size(); i++) {
Window child = ownedWindowList.elementAt(i).get();
if ((child != null) && child.showWithParent) {
@@ -1115,9 +1113,7 @@
modalBlocker.unblockWindow(this);
}
super.hide();
- synchronized (getTreeLock()) {
- this.locationByPlatform = false;
- }
+ locationByPlatform = false;
}
final void clearMostRecentFocusOwnerOnHide() {
@@ -3411,7 +3407,7 @@
return super.canContainFocusOwner(focusOwnerCandidate) && isFocusableWindow();
}
- private boolean locationByPlatform = locationByPlatformProp;
+ private volatile boolean locationByPlatform = locationByPlatformProp;
/**
@@ -3482,9 +3478,7 @@
* @since 1.5
*/
public boolean isLocationByPlatform() {
- synchronized (getTreeLock()) {
- return locationByPlatform;
- }
+ return locationByPlatform;
}
/**
@@ -3573,9 +3567,7 @@
* @since 1.7
*/
public float getOpacity() {
- synchronized (getTreeLock()) {
- return opacity;
- }
+ return opacity;
}
/**
--- a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,9 +53,7 @@
*/
public abstract class CachedPainter {
// CacheMap maps from class to ImageCache.
- private static final Map<Object,ImageCache> cacheMap =
- new HashMap<Object,ImageCache>();
-
+ private static final Map<Object,ImageCache> cacheMap = new HashMap<>();
private static ImageCache getCache(Object key) {
synchronized(CachedPainter.class) {
@@ -96,20 +94,8 @@
if (w <= 0 || h <= 0) {
return;
}
- if (c != null) {
- synchronized(c.getTreeLock()) {
- synchronized(CachedPainter.class) {
- // If c is non-null, synchronize on the tree lock.
- // This is necessary because asking for the
- // GraphicsConfiguration will grab a tree lock.
- paint0(c, g, x, y, w, h, args);
- }
- }
- }
- else {
- synchronized(CachedPainter.class) {
- paint0(c, g, x, y, w, h, args);
- }
+ synchronized (CachedPainter.class) {
+ paint0(c, g, x, y, w, h, args);
}
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Wed Jul 05 20:59:18 2017 +0200
@@ -272,7 +272,8 @@
}
protected String[] getWMClass() {
- return new String[] {XToolkit.getCorrectXIDString(getClass().getName()), XToolkit.getAWTAppClassName()};
+ return new String[] {XToolkit.getAWTAppClassName(),
+ XToolkit.getAWTAppClassName()};
}
void setReparented(boolean newValue) {
@@ -992,10 +993,13 @@
// if ( Check if it's a resize, a move, or a stacking order change )
// {
Rectangle bounds = getBounds();
+ final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
if (!bounds.getSize().equals(oldBounds.getSize())) {
+ acc.setSize(target, bounds.width, bounds.height);
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
}
if (!bounds.getLocation().equals(oldBounds.getLocation())) {
+ acc.setLocation(target, bounds.x, bounds.y);
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
}
// }
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java Wed Jul 05 20:59:18 2017 +0200
@@ -494,24 +494,48 @@
*/
float fontSize = font.getSize2D();
+ double devResX = wPrinterJob.getXRes();
+ double devResY = wPrinterJob.getYRes();
+
+ double fontDevScaleY = devResY / DEFAULT_USER_RES;
+
+ int orient = getPageFormat().getOrientation();
+ if (orient == PageFormat.LANDSCAPE ||
+ orient == PageFormat.REVERSE_LANDSCAPE)
+ {
+ double tmp = devResX;
+ devResX = devResY;
+ devResY = tmp;
+ }
+
+ double devScaleX = devResX / DEFAULT_USER_RES;
+ double devScaleY = devResY / DEFAULT_USER_RES;
+ fontTransform.scale(1.0/devScaleX, 1.0/devScaleY);
+
Point2D.Double pty = new Point2D.Double(0.0, 1.0);
fontTransform.deltaTransform(pty, pty);
double scaleFactorY = Math.sqrt(pty.x*pty.x+pty.y*pty.y);
- float scaledFontSizeY = (float)(fontSize * scaleFactorY);
+ float scaledFontSizeY = (float)(fontSize * scaleFactorY * fontDevScaleY);
Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
fontTransform.deltaTransform(ptx, ptx);
double scaleFactorX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y);
- float scaledFontSizeX = (float)(fontSize * scaleFactorX);
float awScale = getAwScale(scaleFactorX, scaleFactorY);
int iangle = getAngle(ptx);
+ ptx = new Point2D.Double(1.0, 0.0);
+ deviceTransform.deltaTransform(ptx, ptx);
+ double advanceScaleX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y);
+ pty = new Point2D.Double(0.0, 1.0);
+ deviceTransform.deltaTransform(pty, pty);
+ double advanceScaleY = Math.sqrt(pty.x*pty.x+pty.y*pty.y);
+
Font2D font2D = FontUtilities.getFont2D(font);
if (font2D instanceof TrueTypeFont) {
textOut(str, font, (TrueTypeFont)font2D, frc,
scaledFontSizeY, iangle, awScale,
- deviceTransform, scaleFactorX,
+ advanceScaleX, advanceScaleY,
x, y, devpos.x, devpos.y, targetW);
} else if (font2D instanceof CompositeFont) {
/* Composite fonts are made up of multiple fonts and each
@@ -542,7 +566,7 @@
PhysicalFont slotFont = compFont.getSlotFont(slot);
textOut(substr, font, slotFont, frc,
scaledFontSizeY, iangle, awScale,
- deviceTransform, scaleFactorX,
+ advanceScaleX, advanceScaleY,
userx, usery, devx, devy, 0f);
Rectangle2D bds = font.getStringBounds(substr, frc);
float xAdvance = (float)bds.getWidth();
@@ -635,18 +659,42 @@
*/
float fontSize = font.getSize2D();
+ double devResX = wPrinterJob.getXRes();
+ double devResY = wPrinterJob.getYRes();
+
+ double fontDevScaleY = devResY / DEFAULT_USER_RES;
+
+ int orient = getPageFormat().getOrientation();
+ if (orient == PageFormat.LANDSCAPE ||
+ orient == PageFormat.REVERSE_LANDSCAPE)
+ {
+ double tmp = devResX;
+ devResX = devResY;
+ devResY = tmp;
+ }
+
+ double devScaleX = devResX / DEFAULT_USER_RES;
+ double devScaleY = devResY / DEFAULT_USER_RES;
+ fontTransform.scale(1.0/devScaleX, 1.0/devScaleY);
+
Point2D.Double pty = new Point2D.Double(0.0, 1.0);
fontTransform.deltaTransform(pty, pty);
double scaleFactorY = Math.sqrt(pty.x*pty.x+pty.y*pty.y);
- float scaledFontSizeY = (float)(fontSize * scaleFactorY);
+ float scaledFontSizeY = (float)(fontSize * scaleFactorY * fontDevScaleY);
- Point2D.Double pt = new Point2D.Double(1.0, 0.0);
- fontTransform.deltaTransform(pt, pt);
- double scaleFactorX = Math.sqrt(pt.x*pt.x+pt.y*pt.y);
- float scaledFontSizeX = (float)(fontSize * scaleFactorX);
+ Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
+ fontTransform.deltaTransform(ptx, ptx);
+ double scaleFactorX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y);
float awScale = getAwScale(scaleFactorX, scaleFactorY);
- int iangle = getAngle(pt);
+ int iangle = getAngle(ptx);
+
+ ptx = new Point2D.Double(1.0, 0.0);
+ deviceTransform.deltaTransform(ptx, ptx);
+ double advanceScaleX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y);
+ pty = new Point2D.Double(0.0, 1.0);
+ deviceTransform.deltaTransform(pty, pty);
+ double advanceScaleY = Math.sqrt(pty.x*pty.x+pty.y*pty.y);
int numGlyphs = gv.getNumGlyphs();
int[] glyphCodes = gv.getGlyphCodes(0, numGlyphs, null);
@@ -705,8 +753,7 @@
* rotation element of the deviceTransform.
*/
AffineTransform advanceTransform =
- new AffineTransform(deviceTransform);
- advanceTransform.rotate(iangle*Math.PI/1800.0);
+ AffineTransform.getScaleInstance(advanceScaleX, advanceScaleY);
float[] glyphAdvPos = new float[glyphPos.length];
advanceTransform.transform(glyphPos, 0, //source
@@ -784,8 +831,7 @@
Font font, PhysicalFont font2D,
FontRenderContext frc,
float deviceSize, int rotation, float awScale,
- AffineTransform deviceTransform,
- double scaleFactorX,
+ double scaleFactorX, double scaleFactorY,
float userx, float usery,
float devx, float devy, float targetW) {
@@ -826,8 +872,7 @@
* See earlier comment in printGlyphVector() for details.
*/
AffineTransform advanceTransform =
- new AffineTransform(deviceTransform);
- advanceTransform.rotate(rotation*Math.PI/1800.0);
+ AffineTransform.getScaleInstance(scaleFactorX, scaleFactorY);
float[] glyphAdvPos = new float[glyphPos.length];
advanceTransform.transform(glyphPos, 0, //source
@@ -841,11 +886,11 @@
/* If 2D and GDI agree on the advance of the string we do not
* need to explicitly assign glyph positions.
* If we are to use the GDI advance, require it to agree with
- * JDK to a precision of <= 0.2% - ie 1 pixel in 500
+ * JDK to a precision of <= 1.0% - ie 1 pixel in 100
* discrepancy after rounding the 2D advance to the
* nearest pixel and is greater than one pixel in total.
- * ie strings < 500 pixels in length will be OK so long
- * as they differ by only 1 pixel even though that is > 0.02%
+ * ie strings < 100 pixels in length will be OK so long
+ * as they differ by only 1 pixel even though that is > 1%
* The bounds from 2D are in user space so need to
* be scaled to device space for comparison with GDI.
* scaleX is the scale from user space to device space needed for this.
@@ -863,7 +908,7 @@
if (ratio < 1) {
ratio = 1/ratio;
}
- return diff <= 1 || ratio < 1.002;
+ return diff <= 1 || ratio < 1.01;
}
return true;
}
--- a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,8 +114,9 @@
// which may've been disposed by this time, and we have
// no means of checking against it.
if (oldhDC != NULL) {
- MoveDCToPassiveList(oldhDC);
+ MoveDCToPassiveList(oldhDC, info->hWnd);
info->hDC = NULL;
+ info->hWnd = NULL;
}
if (wsdo->window != NULL){
@@ -150,6 +151,7 @@
// Finally, set these new values in the info for this thread
info->hDC = hDC;
+ info->hWnd = wsdo->window;
}
// cached brush and pen are not associated with any DC, and can be
@@ -187,7 +189,7 @@
if (info->hDC != NULL) {
// move the DC from the active dcs list to
// the passive dc list to be released later
- MoveDCToPassiveList(info->hDC);
+ MoveDCToPassiveList(info->hDC, info->hWnd);
}
if (info->clip != NULL) {
--- a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -196,6 +196,7 @@
*/
typedef struct {
HDC hDC;
+ HWND hWnd;
GDIWinSDOps *wsdo;
LONG wsdoTimeStamp; // wsdo creation time stamp.
// Other threads may deallocate wsdo
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Wed Jul 05 20:59:18 2017 +0200
@@ -1382,7 +1382,7 @@
case WM_AWT_RELEASEDC:
{
HDC hDC = (HDC)wParam;
- MoveDCToPassiveList(hDC);
+ MoveDCToPassiveList(hDC, GetHWnd());
ReleaseDCList(GetHWnd(), passiveDCList);
mr = mrConsume;
break;
@@ -7165,8 +7165,8 @@
}
/**
- * Given a DC, remove it from the DC list and return
- * TRUE if it exists on the current list. Otherwise
+ * Given a DC and window handle, remove the DC from the DC list
+ * and return TRUE if it exists on the current list. Otherwise
* return FALSE.
* A DC may not exist on the list because it has already
* been released elsewhere (for example, the window
@@ -7174,14 +7174,14 @@
* thread may also want to release a DC when it notices that
* its DC is obsolete for the current window).
*/
-DCItem *DCList::RemoveDC(HDC hDC)
+DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd)
{
listLock.Enter();
DCItem **prevPtrPtr = &head;
DCItem *listPtr = head;
while (listPtr) {
DCItem *nextPtr = listPtr->next;
- if (listPtr->hDC == hDC) {
+ if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) {
*prevPtrPtr = nextPtr;
break;
}
@@ -7235,9 +7235,9 @@
listLock.Leave();
}
-void MoveDCToPassiveList(HDC hDC) {
+void MoveDCToPassiveList(HDC hDC, HWND hWnd) {
DCItem *removedDC;
- if ((removedDC = activeDCList.RemoveDC(hDC)) != NULL) {
+ if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) {
passiveDCList.AddDCItem(removedDC);
}
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -900,13 +900,13 @@
void AddDC(HDC hDC, HWND hWnd);
void AddDCItem(DCItem *newItem);
- DCItem *RemoveDC(HDC hDC);
+ DCItem *RemoveDC(HDC hDC, HWND hWnd);
DCItem *RemoveAllDCs(HWND hWnd);
void RealizePalettes(int screen);
};
void ReleaseDCList(HWND hwnd, DCList &list);
-void MoveDCToPassiveList(HDC hDC);
+void MoveDCToPassiveList(HDC hDC, HWND hWnd);
#include "ObjectList.h"
--- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Jul 05 20:59:18 2017 +0200
@@ -60,6 +60,7 @@
import javax.management.JMX;
import javax.management.ObjectName;
+import javax.management.ConstructorParameters;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataInvocationHandler;
@@ -1132,8 +1133,8 @@
}
/** Builder for when the target class has a constructor that is
- annotated with @ConstructorProperties so we can see the correspondence
- to getters. */
+ annotated with {@linkplain ConstructorParameters @ConstructorParameters}
+ or {@code @ConstructorProperties} so we can see the correspondence to getters. */
private static final class CompositeBuilderViaConstructor
extends CompositeBuilder {
@@ -1141,10 +1142,19 @@
super(targetClass, itemNames);
}
+ private String[] getConstPropValues(Constructor<?> ctr) {
+ // is constructor annotated by javax.management.ConstructorParameters ?
+ ConstructorParameters ctrProps = ctr.getAnnotation(ConstructorParameters.class);
+ if (ctrProps != null) {
+ return ctrProps.value();
+ } else {
+ // try the legacy java.beans.ConstructorProperties annotation
+ String[] vals = JavaBeansAccessor.getConstructorPropertiesValue(ctr);
+ return vals;
+ }
+ }
+
String applicable(Method[] getters) throws InvalidObjectException {
- if (!JavaBeansAccessor.isAvailable())
- return "@ConstructorProperties annotation not available";
-
Class<?> targetClass = getTargetClass();
Constructor<?>[] constrs = targetClass.getConstructors();
@@ -1152,12 +1162,13 @@
List<Constructor<?>> annotatedConstrList = newList();
for (Constructor<?> constr : constrs) {
if (Modifier.isPublic(constr.getModifiers())
- && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null)
+ && getConstPropValues(constr) != null)
annotatedConstrList.add(constr);
}
if (annotatedConstrList.isEmpty())
- return "no constructor has @ConstructorProperties annotation";
+ return "no constructor has either @ConstructorParameters " +
+ "or @ConstructorProperties annotation";
annotatedConstructors = newList();
@@ -1181,13 +1192,17 @@
// so we can test unambiguity.
Set<BitSet> getterIndexSets = newSet();
for (Constructor<?> constr : annotatedConstrList) {
- String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr);
+ String annotationName =
+ constr.isAnnotationPresent(ConstructorParameters.class) ?
+ "@ConstructorParameters" : "@ConstructorProperties";
+
+ String[] propertyNames = getConstPropValues(constr);
Type[] paramTypes = constr.getGenericParameterTypes();
if (paramTypes.length != propertyNames.length) {
final String msg =
"Number of constructor params does not match " +
- "@ConstructorProperties annotation: " + constr;
+ annotationName + " annotation: " + constr;
throw new InvalidObjectException(msg);
}
@@ -1200,7 +1215,7 @@
String propertyName = propertyNames[i];
if (!getterMap.containsKey(propertyName)) {
String msg =
- "@ConstructorProperties includes name " + propertyName +
+ annotationName + " includes name " + propertyName +
" which does not correspond to a property";
for (String getterName : getterMap.keySet()) {
if (getterName.equalsIgnoreCase(propertyName)) {
@@ -1215,7 +1230,7 @@
paramIndexes[getterIndex] = i;
if (present.get(getterIndex)) {
final String msg =
- "@ConstructorProperties contains property " +
+ annotationName + " contains property " +
propertyName + " more than once: " + constr;
throw new InvalidObjectException(msg);
}
@@ -1224,7 +1239,7 @@
Type propertyType = getter.getGenericReturnType();
if (!propertyType.equals(paramTypes[i])) {
final String msg =
- "@ConstructorProperties gives property " + propertyName +
+ annotationName + " gives property " + propertyName +
" of type " + propertyType + " for parameter " +
" of type " + paramTypes[i] + ": " + constr;
throw new InvalidObjectException(msg);
@@ -1233,7 +1248,8 @@
if (!getterIndexSets.add(present)) {
final String msg =
- "More than one constructor has a @ConstructorProperties " +
+ "More than one constructor has " +
+ "@ConstructorParameters or @ConstructorProperties " +
"annotation with this set of names: " +
Arrays.toString(propertyNames);
throw new InvalidObjectException(msg);
@@ -1252,10 +1268,10 @@
* just the bigger constructor.
*
* The algorithm here is quadratic in the number of constructors
- * with a @ConstructorProperties annotation. Typically this corresponds
- * to the number of versions of the class there have been. Ten
- * would already be a large number, so although it's probably
- * possible to have an O(n lg n) algorithm it wouldn't be
+ * with a @ConstructorParameters or @ConstructructorProperties annotation.
+ * Typically this corresponds to the number of versions of the class
+ * there have been. Ten would already be a large number, so although
+ * it's probably possible to have an O(n lg n) algorithm it wouldn't be
* worth the complexity.
*/
for (BitSet a : getterIndexSets) {
@@ -1272,8 +1288,9 @@
i = u.nextSetBit(i+1))
names.add(itemNames[i]);
final String msg =
- "Constructors with @ConstructorProperties annotation " +
- " would be ambiguous for these items: " +
+ "Constructors with @ConstructorParameters or " +
+ "@ConstructorProperties annotation " +
+ "would be ambiguous for these items: " +
names;
throw new InvalidObjectException(msg);
}
@@ -1310,7 +1327,8 @@
if (max == null) {
final String msg =
- "No constructor has a @ConstructorProperties for this set of " +
+ "No constructor has either @ConstructorParameters " +
+ "or @ConstructorProperties annotation for this set of " +
"items: " + ct.keySet();
throw new InvalidObjectException(msg);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/javax/management/ConstructorParameters.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * <p>
+ * An annotation on a constructor that shows how the parameters of
+ * that constructor correspond to the constructed object's getter
+ * methods. For example:
+ * </p>
+ * <blockquote>
+ * <pre>
+ * public class MemoryUsage {
+ * // standard JavaBean conventions with getters
+ * <b>@ConstructorParameters({"init", "used", "committed", "max"})</b>
+ * public MemoryUsage(long init, long used,
+ * long committed, long max) {...}
+ * public long getInit() {...}
+ * public long getUsed() {...}
+ * public long getCommitted() {...}
+ * public long getMax() {...}
+ * }
+ * </pre>
+ * </blockquote>
+ * <p>
+ * The annotation shows that the first parameter of the constructor
+ * can be retrieved with the {@code getInit()} method, the second one with
+ * the {@code getUsed()} method, and so on. Since parameter names are not in
+ * general available at runtime, without the annotation there would be
+ * no way of knowing which parameter corresponds to which property.
+ * </p>
+ * <p>
+ * If a constructor is annotated by the both {@code @java.beans.ConstructorProperties}
+ * and {@code @javax.management.ConstructorParameters} annotations
+ * the JMX introspection will give an absolute precedence to the latter one.
+ * </p>
+ *
+ * @since 1.9
+ */
+@Documented @Target(CONSTRUCTOR) @Retention(RUNTIME)
+public @interface ConstructorParameters {
+ /**
+ * <p>The getter names.</p>
+ *
+ * @return the getter names corresponding to the parameters in the
+ * annotated constructor.
+ */
+ String[] value();
+}
--- a/jdk/src/java.management/share/classes/javax/management/MXBean.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/MXBean.java Wed Jul 05 20:59:18 2017 +0200
@@ -153,7 +153,7 @@
<td><pre>
public class MemoryUsage {
// standard JavaBean conventions with getters
- <b>@ConstructorProperties({"init", "used", "committed", "max"})</b>
+ <b>@ConstructorParameters({"init", "used", "committed", "max"})</b>
public MemoryUsage(long init, long used,
long committed, long max) {...}
long getInit() {...}
@@ -168,8 +168,8 @@
<p>The definitions are the same in the two cases, except
that with the MXBean, <code>MemoryUsage</code> no longer needs to
be marked <code>Serializable</code> (though it can be). On
- the other hand, we have added a {@code @ConstructorProperties} annotation
- to link the constructor parameters to the corresponding getters.
+ the other hand, we have added a {@link ConstructorParameters @ConstructorParameters}
+ annotation to link the constructor parameters to the corresponding getters.
We will see more about this below.</p>
<p><code>MemoryUsage</code> is a <em>model-specific class</em>.
@@ -850,18 +850,24 @@
<em>J</em>.</p></li>
<li><p>Otherwise, if <em>J</em> has at least one public
- constructor with a {@link java.beans.ConstructorProperties
- ConstructorProperties} annotation, then one
- of those constructors (not necessarily always the same one)
- will be called to reconstruct an instance of <em>J</em>.
+ constructor with either {@link javax.management.ConstructorParameters
+ @javax.management.ConstructorParameters} or
+ {@code @java.beans.ConstructoProperties} annotation, then one of those
+ constructors (not necessarily always the same one) will be called to
+ reconstruct an instance of <em>J</em>.
+ If a constructor is annotated with both
+ {@code @javax.management.ConstructorParameters} and
+ {@code @java.beans.ConstructorProperties},
+ {@code @javax.management.ConstructorParameters} will be used and
+ {@code @java.beans.ConstructorProperties} will be ignored.
Every such annotation must list as many strings as the
constructor has parameters; each string must name a property
corresponding to a getter of <em>J</em>; and the type of this
getter must be the same as the corresponding constructor
parameter. It is not an error for there to be getters that
- are not mentioned in the {@code ConstructorProperties} annotation
- (these may correspond to information that is not needed to
- reconstruct the object).</p>
+ are not mentioned in the {@code @ConstructorParameters} or
+ {@code @ConstructorProperties} annotations (these may correspond to
+ information that is not needed to reconstruct the object).</p>
<p>An instance of <em>J</em> is reconstructed by calling a
constructor with the appropriate reconstructed items from the
@@ -871,9 +877,10 @@
CompositeData} might come from an earlier version of
<em>J</em> where not all the items were present. A
constructor is <em>applicable</em> if all the properties named
- in its {@code ConstructorProperties} annotation are present as items
- in the {@code CompositeData}. If no constructor is
- applicable, then the attempt to reconstruct <em>J</em> fails.</p>
+ in its {@code @ConstructorParameters} or {@code @ConstructorProperties}
+ annotation are present as items in the {@code CompositeData}.
+ If no constructor is applicable, then the attempt to reconstruct
+ <em>J</em> fails.</p>
<p>For any possible combination of properties, it must be the
case that either (a) there are no applicable constructors, or
@@ -909,8 +916,9 @@
<li><p>Otherwise, <em>J</em> is not reconstructible.</p></li>
</ol>
- <p>Rule 2 is not applicable to subset Profiles of Java SE that do not
- include the {@code java.beans} package. When targeting a runtime that does
+ <p>When only {@code @java.beans.ConstructorProperties} is present then
+ rule 2 is not applicable to subset Profiles of Java SE that do not include
+ the {@code java.beans} package. When targeting a runtime that does
not include the {@code java.beans} package, and where there is a mismatch
between the compile-time and runtime environment whereby <em>J</em> is
compiled with a public constructor and the {@code ConstructorProperties}
@@ -957,14 +965,14 @@
</blockquote>
</li>
- <li>Public constructor with <code>@ConstructorProperties</code> annotation:
+ <li>Public constructor with <code>@ConstructorParameters</code> annotation:
<blockquote>
<pre>
public class NamedNumber {
public int getNumber() {return number;}
public String getName() {return name;}
- <b>@ConstructorProperties({"number", "name"})
+ <b>@ConstructorParameters({"number", "name"})
public NamedNumber(int number, String name)</b> {
this.number = number;
this.name = name;
--- a/jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh Thu Nov 05 13:43:17 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute 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.
-#
-
-#
-#
-
-#
-# This script executes the Java interpreter, defines properties
-# that correspond to the CGI 1.0 environment variables, and executes
-# the class "sun.rmi.transport.proxy.CGIHandler". It should be
-# installed in the directory to which the HTTP server maps the
-# URL path "/cgi-bin".
-#
-# (Configuration is necessary as noted below.)
-#
-# This class will support a QUERY_STRING of the form "forward=<port>"
-# with a REQUEST_METHOD "POST". The body of the request will be
-# forwarded (as another POST request) to the server listening on the
-# specified port (must be >= 1024). The response from this forwarded
-# request will be the response to the original request.
-#
-# CONFIGURATION:
-#
-# Fill in correct absolute path to Java interpreter below. For example,
-# the "PATH=" line might be changed to the follow if the JDK is installed
-# at the path "/home/peter/java":
-#
-# PATH=/home/peter/java/bin:$PATH
-#
-PATH=/usr/local/java/bin:$PATH
-exec java \
- -DAUTH_TYPE="$AUTH_TYPE" \
- -DCONTENT_LENGTH="$CONTENT_LENGTH" \
- -DCONTENT_TYPE="$CONTENT_TYPE" \
- -DGATEWAY_INTERFACE="$GATEWAY_INTERFACE" \
- -DHTTP_ACCEPT="$HTTP_ACCEPT" \
- -DPATH_INFO="$PATH_INFO" \
- -DPATH_TRANSLATED="$PATH_TRANSLATED" \
- -DQUERY_STRING="$QUERY_STRING" \
- -DREMOTE_ADDR="$REMOTE_ADDR" \
- -DREMOTE_HOST="$REMOTE_HOST" \
- -DREMOTE_IDENT="$REMOTE_IDENT" \
- -DREMOTE_USER="$REMOTE_USER" \
- -DREQUEST_METHOD="$REQUEST_METHOD" \
- -DSCRIPT_NAME="$SCRIPT_NAME" \
- -DSERVER_NAME="$SERVER_NAME" \
- -DSERVER_PORT="$SERVER_PORT" \
- -DSERVER_PROTOCOL="$SERVER_PROTOCOL" \
- -DSERVER_SOFTWARE="$SERVER_SOFTWARE" \
- sun.rmi.transport.proxy.CGIHandler
--- a/jdk/src/java.sql/share/classes/java/sql/Connection.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.sql/share/classes/java/sql/Connection.java Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1482,4 +1482,109 @@
* @since 1.7
*/
int getNetworkTimeout() throws SQLException;
+
+ // JDBC 4.3
+
+ /**
+ * Hints to the driver that a request, an independent unit of work, is beginning
+ * on this connection. Each request is independent of all other requests
+ * with regard to state local to the connection either on the client or the
+ * server. Work done between {@code beginRequest}, {@code endRequest}
+ * pairs does not depend on any other work done on the connection either as
+ * part of another request or outside of any request. A request may include multiple
+ * transactions. There may be dependencies on committed database state as
+ * that is not local to the connection.
+ * <p>
+ * Local state is defined as any state associated with a Connection that is
+ * local to the current Connection either in the client or the database that
+ * is not transparently reproducible.
+ * <p>
+ * Calls to {@code beginRequest} and {@code endRequest} are not nested.
+ * Multiple calls to {@code beginRequest} without an intervening call
+ * to {@code endRequest} is not an error. The first {@code beginRequest} call
+ * marks the start of the request and subsequent calls are treated as
+ * a no-op
+ * <p>
+ * Use of {@code beginRequest} and {@code endRequest} is optional, vendor
+ * specific and should largely be transparent. In particular
+ * implementations may detect conditions that indicate dependence on
+ * other work such as an open transaction. It is recommended though not
+ * required that implementations throw a {@code SQLException} if there is an active
+ * transaction and {@code beginRequest} is called.
+ * Using these methods may improve performance or provide other benefits.
+ * Consult your vendors documentation for additional information.
+ * <p>
+ * It is recommended to
+ * enclose each unit of work in {@code beginRequest}, {@code endRequest}
+ * pairs such that there is no open transaction at the beginning or end of
+ * the request and no dependency on local state that crosses request
+ * boundaries. Committed database state is not local.
+ *
+ * @implSpec
+ * The default implementation is a no-op.
+ * <p>
+ * @apiNote
+ * This method is to be used by Connection pooling managers.
+ * <p>
+ * The pooling manager should call {@code beginRequest} on the underlying connection
+ * prior to returning a connection to the caller.
+ * <p>
+ * The pooling manager does not need to call {@code beginRequest} if:
+ * <ul>
+ * <li>The connection pool caches {@code PooledConnection} objects</li>
+ * <li>Returns a logical connection handle when {@code getConnection} is
+ * called by the application</li>
+ * <li>The pool manager calls {@code Connection.close} on the logical connection handle
+ * prior to returning the {@code PooledConnection} back to the cache</li>
+ * </ul>
+ * @throws SQLException if an error occurs
+ * @since 1.9
+ * @see endRequest
+ * @see javax.sql.PooledConnection
+ */
+ default void beginRequest() throws SQLException {
+ // Default method takes no action
+ }
+
+ /**
+ * Hints to the driver that a request, an independent unit of work,
+ * has completed. Calls to {@code beginRequest}
+ * and {@code endRequest} are not nested. Multiple
+ * calls to {@code endRequest} without an intervening call to {@code beginRequest}
+ * is not an error. The first {@code endRequest} call
+ * marks the request completed and subsequent calls are treated as
+ * a no-op. If {@code endRequest} is called without an initial call to
+ * {@code beginRequest} is a no-op.
+ *<p>
+ * The exact behavior of this method is vendor specific. In particular
+ * implementations may detect conditions that indicate dependence on
+ * other work such as an open transaction. It is recommended though not
+ * required that implementations throw a {@code SQLException} if there is an active
+ * transaction and {@code endRequest} is called.
+ *
+ * @implSpec
+ * The default implementation is a no-op.
+ * @apiNote
+ *
+ * This method is to be used by Connection pooling managers.
+ * <p>
+ * The pooling manager should call {@code endRequest} on the underlying connection
+ * when the applications returns the connection back to the connection pool.
+ * <p>
+ * The pooling manager does not need to call {@code endRequest} if:
+ * <ul>
+ * <li>The connection pool caches {@code PooledConnection} objects</li>
+ * <li>Returns a logical connection handle when {@code getConnection} is
+ * called by the application</li>
+ * <li>The pool manager calls {@code Connection.close} on the logical connection handle
+ * prior to returning the {@code PooledConnection} back to the cache</li>
+ * </ul>
+ * @throws SQLException if an error occurs
+ * @since 1.9
+ * @see beginRequest
+ * @see javax.sql.PooledConnection
+ */
+ default void endRequest() throws SQLException {
+ // Default method takes no action
+ }
}
--- a/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,16 @@
* <code>PooledConnection</code> object to the pool of connections so that
* it can be used again. Thus, when an application closes its connection,
* the underlying physical connection is recycled rather than being closed.
- * <P>
+ * <p>
+ * If the connection pool manager wraps or provides a proxy to the logical
+ * handle returned from a call to {@code PoolConnection.getConnection}, the pool
+ * manager must do
+ * one of the following when the application calls {@code Connection.close}:
+ * <ul>
+ * <li>call {@code endRequest} on the logical {@code Connection} handle
+ * <li>call {@code close} on the logical {@code Connection} handle
+ * </ul>
+ * <p>
* The physical connection is not closed until the connection pool manager
* calls the <code>PooledConnection</code> method <code>close</code>.
* This method is generally called to have an orderly shutdown of the server or
--- a/jdk/test/TEST.groups Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/TEST.groups Wed Jul 05 20:59:18 2017 +0200
@@ -27,6 +27,7 @@
tier1 = \
:jdk_lang \
+ -java/lang/ProcessHandle/TreeTest.java \
:jdk_util \
sun/nio/cs/ISO8859x.java \
java/nio/Buffer \
@@ -34,6 +35,7 @@
:jdk_math
tier2 = \
+ java/lang/ProcessHandle/TreeTest.java \
:jdk_io \
:jdk_nio \
-sun/nio/cs/ISO8859x.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Component/CreateImage/CreateImage.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsEnvironment;
+
+import javax.swing.JButton;
+
+/**
+ * @test
+ * @bug 6815345
+ * @run main CreateImage
+ * @run main/othervm -Djava.awt.headless=true CreateImage
+ */
+public final class CreateImage {
+
+ public static void main(final String[] args) throws Exception {
+ EventQueue.invokeAndWait(CreateImage::test);
+ }
+
+ private static void test() {
+ final JButton jbutton1 = new JButton();
+ final JButton jbutton2 = new JButton();
+
+ if (GraphicsEnvironment.isHeadless()) {
+ checkCreateImage(jbutton1, true);
+ checkCreateImage(jbutton2, true);
+ return;
+ }
+
+ final Frame frame = new Frame();
+ final Button button1 = new Button();
+ final Button button2 = new Button();
+ try {
+ // all components are not displayable
+ checkCreateImage(frame, true);
+ checkCreateImage(button1, true);
+ checkCreateImage(button2, true);
+ checkCreateImage(jbutton1, true);
+ checkCreateImage(jbutton2, true);
+
+ // some components added to the non-displayable frame
+ frame.add(button1);
+ frame.add(jbutton1);
+ checkCreateImage(button1, true);
+ checkCreateImage(jbutton1, true);
+ frame.pack();
+
+ // tests previously added components when the frame is displayable
+ checkCreateImage(frame, false);
+ checkCreateImage(button1, false);
+ checkCreateImage(jbutton1, false);
+
+ // some components added to the displayable frame
+ frame.add(button2);
+ frame.add(jbutton2);
+ checkCreateImage(button2, false);
+ checkCreateImage(jbutton2, false);
+
+ } finally {
+ frame.dispose();
+ }
+ // tests all components after the frame became non-displayable again
+ checkCreateImage(frame, true);
+ checkCreateImage(button1, true);
+ checkCreateImage(button2, true);
+ checkCreateImage(jbutton1, true);
+ checkCreateImage(jbutton2, true);
+ }
+
+ private static void checkCreateImage(final Component comp,
+ final boolean isNull) {
+ if ((comp.createImage(10, 10) != null) == isNull) {
+ throw new RuntimeException("Image is wrong");
+ }
+ if ((comp.createVolatileImage(10, 10) != null) == isNull) {
+ throw new RuntimeException("Image is wrong");
+ }
+ try {
+ if ((comp.createVolatileImage(10, 10, null) != null) == isNull) {
+ throw new RuntimeException("Image is wrong");
+ }
+ } catch (final AWTException ignored) {
+ // this check is not applicable
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Frame;
+import java.awt.GraphicsConfiguration;
+import java.awt.Window;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+/**
+ * @test
+ * @bug 8138764
+ */
+public final class TreeLockDeadlock extends Frame {
+
+ @Override
+ public synchronized GraphicsConfiguration getGraphicsConfiguration() {
+ return super.getGraphicsConfiguration();
+ }
+
+ @Override
+ public synchronized void reshape(int x, int y, int width, int height) {
+ super.reshape(x, y, width, height);
+ }
+
+ @Override
+ public synchronized float getOpacity() {
+ return super.getOpacity();
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Window window = new TreeLockDeadlock();
+ window.setSize(300, 300);
+ test(window);
+ }
+
+ private static void test(final Window window) throws Exception {
+ final long start = System.nanoTime();
+ final long end = start + NANOSECONDS.convert(1, MINUTES);
+
+ final Runnable r1 = () -> {
+ while (System.nanoTime() < end) {
+ window.setBounds(window.getBounds());
+ }
+ };
+ final Runnable r2 = () -> {
+ while (System.nanoTime() < end) {
+ window.getGraphicsConfiguration();
+ window.getOpacity();
+ }
+ };
+
+ final Thread t1 = new Thread(r1);
+ final Thread t2 = new Thread(r1);
+ final Thread t3 = new Thread(r2);
+ final Thread t4 = new Thread(r2);
+
+ t1.start();
+ t2.start();
+ t3.start();
+ t4.start();
+ t1.join();
+ t2.join();
+ t3.join();
+ t4.join();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6356322
+ * @summary Tests that embedded frame's graphics configuration is updated
+ * correctly when it is moved to another screen in multiscreen system,
+ * XToolkit
+ * @author artem.ananiev@sun.com: area=awt.multiscreen
+ * @requires (os.family == "linux") | (os.family == "solaris")
+ * @modules java.desktop/sun.awt
+ * java.desktop/sun.awt.X11
+ * java.desktop/java.awt.peer
+ * @run main GraphicsConfigTest
+ */
+
+import java.awt.*;
+import java.awt.peer.*;
+import java.lang.reflect.*;
+import java.util.*;
+import sun.awt.*;
+
+public class GraphicsConfigTest {
+
+ private static void init()
+ throws InterruptedException, AWTException {
+ if (!isXToolkit()) {
+ System.err.println("The test should be run only on XToolkit");
+ return;
+ }
+
+ GraphicsEnvironment ge =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice[] gds = ge.getScreenDevices();
+ if (gds.length < 2) {
+ System.err.println("The test should be run only in"
+ + " multiscreen configuration");
+ return;
+ }
+
+ boolean xinerama = Arrays.stream(gds)
+ .map((gd) -> gd.getDefaultConfiguration().getBounds())
+ .filter((r) -> r.x != 0 || r.y != 0).findFirst().isPresent();
+
+ if (!xinerama) {
+ System.err.println("The test should be run only with Xinerama ON");
+ return;
+ }
+
+ Rectangle r0 = gds[0].getDefaultConfiguration().getBounds();
+ Rectangle r1 = gds[1].getDefaultConfiguration().getBounds();
+
+ System.setProperty("sun.awt.xembedserver", "true");
+ Frame f = new Frame("F");
+ try {
+ final Robot robot = new Robot();
+
+ f.setBounds(r0.x + 100, r0.y + 100, 200, 200);
+ f.setVisible(true);
+ robot.waitForIdle();
+ Thread.sleep(1000);
+
+ Canvas c = new Canvas();
+ f.add(c);
+ AWTAccessor.ComponentAccessor acc =
+ AWTAccessor.getComponentAccessor();
+ WindowIDProvider wip = acc.getPeer(c);
+ long h = wip.getWindow();
+
+ EmbeddedFrame e = createEmbeddedFrame(h);
+ acc.<FramePeer>getPeer(e).setBoundsPrivate(0, 0, 100,
+ 100); // triggers XConfigureEvent
+ e.registerListeners();
+ e.setVisible(true);
+ robot.waitForIdle();
+ Thread.sleep(1000);
+
+ if (!checkGC(f, e)) {
+ throw new RuntimeException("Failed at checkpoint 1");
+ }
+
+ f.setLocation(r1.x + 100, r1.y + 100);
+ Thread.sleep(100);
+ acc.<FramePeer>getPeer(e).setBoundsPrivate(0, 0, 101,
+ 101); // triggers XConfigureEvent
+ robot.waitForIdle();
+ Thread.sleep(1000);
+
+ if (!checkGC(f, e)) {
+ throw new RuntimeException("Failed at checkpoint 2");
+ }
+
+ f.setLocation(r0.x + 100, r0.y + 100);
+ Thread.sleep(100);
+ acc.<FramePeer>getPeer(e).setBoundsPrivate(0, 0, 102,
+ 102); // triggers XConfigureEvent
+ robot.waitForIdle();
+ Thread.sleep(1000);
+
+ if (!checkGC(f, e)) {
+ throw new RuntimeException("Failed at checkpoint 3");
+ }
+
+ } finally {
+ f.dispose();
+ }
+ }
+
+ private static boolean isXToolkit() {
+ return Toolkit.getDefaultToolkit().getClass()
+ .getName().equals("sun.awt.X11.XToolkit");
+ }
+
+ private static EmbeddedFrame createEmbeddedFrame(long window) {
+ try {
+ Class cl = Class.forName("sun.awt.X11.XEmbeddedFrame");
+ Constructor cons = cl.getConstructor(
+ new Class[]{Long.TYPE, Boolean.TYPE});
+ return (EmbeddedFrame) cons.newInstance(new Object[]{window, true});
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("Can't create embedded frame");
+ }
+ }
+
+ private static boolean checkGC(Component c, Component d) {
+ GraphicsConfiguration g1 = c.getGraphicsConfiguration();
+ System.err.println(g1);
+ GraphicsConfiguration g2 = d.getGraphicsConfiguration();
+ System.err.println(g2);
+
+ return g1.equals(g2);
+ }
+
+ public static void main(String args[]) throws InterruptedException, AWTException {
+ init();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,47 @@
+<!--
+ Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+-->
+<html>
+<!--
+ @test
+ @bug 6387275
+ @summary List: the focus is at the top of the first item, XAWT
+ @author Dmitry.Cherepanov@SUN.COM area=awt.list
+ @requires (os.family == "linux" | os.family == "solaris")
+ @modules java.desktop/sun.awt
+ java.desktop/java.awt.peer
+ java.desktop/sun.awt.X11
+ @run applet FocusEmptyListTest.html
+ -->
+<head>
+<title> FocusEmptyListTest </title>
+</head>
+<body>
+
+<h1>FocusEmptyListTest<br>Bug ID: 6387275 </h1>
+
+<p> This is an AUTOMATIC test, simply wait for completion </p>
+
+<APPLET CODE="FocusEmptyListTest.class" WIDTH=200 HEIGHT=200></APPLET>
+</body>
+</html>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6387275
+ @summary List: the focus is at the top of the first item, XAWT
+ @author Dmitry.Cherepanov@SUN.COM area=awt.list
+ @run applet FocusEmptyListTest.html
+*/
+
+import java.applet.Applet;
+import java.awt.*;
+import java.lang.reflect.*;
+import java.awt.peer.ListPeer;
+
+import sun.awt.AWTAccessor;
+
+public class FocusEmptyListTest extends Applet {
+
+ public void init() {
+ setLayout(new BorderLayout());
+ }//End init()
+
+ public void start() {
+ boolean isXToolkit = Toolkit.getDefaultToolkit()
+ .getClass().getName().equals("sun.awt.X11.XToolkit");
+ if (!isXToolkit) {
+ System.out.println("The test is XAWT-only.");
+ return;
+ }
+
+ List list = new List();
+ Object isIndexDisplayed = null;
+ setLayout(new FlowLayout());
+
+ getToolkit().addAWTEventListener(System.out::println,
+ AWTEvent.FOCUS_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK);
+
+ add(list);
+ list.add("item1");
+
+ setSize(200, 200);
+ setVisible(true);
+ validate();
+
+ list.removeAll();
+
+ try {
+
+ // peer = List.getPeer()
+ ListPeer peer = AWTAccessor.getComponentAccessor().getPeer(list);
+ System.out.println("peer = " + peer);
+ Class peerClass = peer.getClass();
+ System.out.println("peer's class = " + peerClass);
+
+ // isIndexDisplayed = peer.isIndexDisplayed(-1)
+ Method isIndexDisplayedM
+ = peerClass.getDeclaredMethod("isIndexDisplayed", Integer.TYPE);
+ System.out.println("method = " + isIndexDisplayedM);
+ isIndexDisplayedM.setAccessible(true);
+ isIndexDisplayed = isIndexDisplayedM.invoke(peer, -1);
+ System.out.println("isIndexDisplayed=" + isIndexDisplayed);
+
+ } catch (Throwable thr) {
+ throw new RuntimeException("TEST FAILED: " + thr);
+ }
+
+ if ((Boolean) isIndexDisplayed) {
+ throw new RuntimeException("TEST FAILED: -1 should be"
+ + " invisible index");
+ }
+
+ }// start()
+
+}// class AutomaticAppletTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Window/MultiWindowApp/MultiWindowAppTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary After calling frame.toBack() dialog goes to the back on Ubuntu 12.04
+ * @bug 8022334
+ * @author Semyon Sadetsky
+ * @run main MultiWindowAppTest
+ */
+
+import java.awt.*;
+
+public class MultiWindowAppTest {
+
+ public static void main(String[] args) throws Exception {
+ Window win1 = new Frame();
+ Window win2 = new Dialog((Frame) null);
+
+ win1.setBounds(100, 100, 200, 200);
+ win1.setBackground(Color.RED);
+ win1.setVisible(true);
+
+ Robot robot = new Robot();
+ robot.delay(200);
+ robot.waitForIdle();
+
+ win2.setBounds(win1.getBounds());
+ win2.setVisible(true);
+
+ robot.delay(200);
+ robot.waitForIdle();
+
+ win1.toFront();
+ robot.delay(200);
+ robot.waitForIdle();
+
+ Point point = win1.getLocationOnScreen();
+ Color color = robot.getPixelColor(point.x + 100, point.y + 100);
+
+ if(!color.equals(Color.RED)) {
+ win1.dispose();
+ win2.dispose();
+ throw new RuntimeException("Window was not sent to front.");
+ }
+
+ win1.toBack();
+ robot.delay(200);
+ robot.waitForIdle();
+
+ color = robot.getPixelColor(point.x + 100, point.y + 100);
+
+ win1.dispose();
+ win2.dispose();
+
+ if(color.equals(Color.RED)) {
+ throw new RuntimeException("Window was not sent to back.");
+ }
+
+ System.out.println("ok");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Window/ScreenLocation/ScreenLocationTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @bug 8011616
+ @summary JWindow.getLocation and JWindow.getLocationOnScreen return different
+ values on Unity
+ @author Semyon Sadetsky
+ */
+
+import java.awt.*;
+
+public class ScreenLocationTest {
+
+
+ public static void main(String[] args) throws Exception {
+ testLocation();
+ testSize();
+ System.out.println("ok");
+ }
+
+ public static void testLocation() throws Exception {
+ Window window = new Window((Frame) null);
+ window.setSize(100, 100);
+ window.setLocation(0, 0);
+ window.setVisible(true);
+
+ Robot robot = new Robot();
+ robot.delay(200);
+ robot.waitForIdle();
+
+ Point location1 = window.getLocation();
+ Point location2 = window.getLocationOnScreen();
+ window.setLocation(10000, 10000);
+
+ if (!location1.equals(location2)) {
+ window.dispose();
+ throw new RuntimeException("getLocation is different");
+ }
+
+ robot.delay(200);
+ robot.waitForIdle();
+ location1 = window.getLocation();
+ location2 = window.getLocationOnScreen();
+
+ if (!location1.equals(location2)) {
+ window.dispose();
+ throw new RuntimeException("getLocation is different");
+ }
+
+ window.dispose();
+ }
+
+ public static void testSize() throws Exception {
+ Window window = new Window((Frame) null);
+ window.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ window.setVisible(true);
+
+ Robot robot = new Robot();
+ robot.delay(200);
+ robot.waitForIdle();
+
+ Dimension size = window.getSize();
+ if (size.width == Integer.MAX_VALUE ||
+ size.height == Integer.MAX_VALUE) {
+ window.dispose();
+ throw new RuntimeException("size is wrong");
+ }
+
+ window.dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/DataFlavor/MacOsXFileAndMultipleFileCopingTest/MacOsXFileAndMultipleFileCopingTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ @test
+ @bug 8081787 8136763
+ @author Mikhail Cherkasov
+ @run main/manual MacOsXFileAndMultipleFileCopingTest
+*/
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.URL;
+
+public class MacOsXFileAndMultipleFileCopingTest {
+ private static void init() {
+ String[] instructions =
+ {"Test for MacOS X only:",
+ "1. The aim is to test that java works fine with \"application/" +
+ "x-java-url;class=java.net.URL\"falvor and support coping of multiple files",
+ "2. Open finder and select any file.",
+ "3. Press CMD+C or press \"Copy\" in context menu",
+ "4. Focus window with \"Test URL\" Button.",
+ "5. If you see URL for selected file, then test PASSED,",
+ "otherwise test FAILED.",
+
+ "6. Open finder again and select several files.",
+ "7. Press CMD+C or press \"Copy\" in context menu",
+ "8. Focus window with \"Test multiple files coping\" Button.",
+ "9. If you see list of selected files, then test PASSED,",
+ "otherwise test FAILED.",
+
+ };
+
+ Sysout.createDialog();
+ Sysout.printInstructions(instructions);
+
+ final Frame frame = new Frame();
+ Panel panel = new Panel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+
+ frame.add(panel);
+ Button testUrlBtn = new Button("Test URL");
+ final TextArea textArea = new TextArea(5, 80);
+ testUrlBtn.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ try {
+ Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
+ URL url = (URL) board.getData(new DataFlavor("application/x-java-url;class=java.net.URL"));
+ textArea.setText(url.toString());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ panel.add(testUrlBtn);
+ Button testUriList = new Button("Test multiple files coping");
+ testUriList.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ try {
+ Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
+ String files = (String) board.getData(new DataFlavor("text/uri-list;class=java.lang.String"));
+ textArea.setText(files);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ panel.add(testUriList);
+ panel.add(textArea);
+ frame.setBounds(200, 200, 400, 400);
+ frame.setVisible(true);
+
+ }//End init()
+
+
+ /*****************************************************
+ * Standard Test Machinery Section
+ * DO NOT modify anything in this section -- it's a
+ * standard chunk of code which has all of the
+ * synchronisation necessary for the test harness.
+ * By keeping it the same in all tests, it is easier
+ * to read and understand someone else's test, as
+ * well as insuring that all tests behave correctly
+ * with the test harness.
+ * There is a section following this for test-defined
+ * classes
+ ******************************************************/
+ private static boolean theTestPassed = false;
+ private static boolean testGeneratedInterrupt = false;
+ private static String failureMessage = "";
+
+ private static Thread mainThread = null;
+
+ private static int sleepTime = 300000;
+
+ public static void main(String args[]) throws InterruptedException {
+ if (!System.getProperty("os.name").startsWith("Mac")) {
+ return;
+ }
+ mainThread = Thread.currentThread();
+ try {
+ init();
+ } catch (TestPassedException e) {
+ //The test passed, so just return from main and harness will
+ // interepret this return as a pass
+ return;
+ }
+ //At this point, neither test passed nor test failed has been
+ // called -- either would have thrown an exception and ended the
+ // test, so we know we have multiple threads.
+
+ //Test involves other threads, so sleep and wait for them to
+ // called pass() or fail()
+ try {
+ Thread.sleep(sleepTime);
+ //Timed out, so fail the test
+ throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
+ } catch (InterruptedException e) {
+ if (!testGeneratedInterrupt) throw e;
+
+ //reset flag in case hit this code more than once for some reason (just safety)
+ testGeneratedInterrupt = false;
+ if (theTestPassed == false) {
+ throw new RuntimeException(failureMessage);
+ }
+ }
+
+ }//main
+
+ public static synchronized void setTimeoutTo(int seconds) {
+ sleepTime = seconds * 1000;
+ }
+
+ public static synchronized void pass() {
+ Sysout.println("The test passed.");
+ Sysout.println("The test is over, hit Ctl-C to stop Java VM");
+ //first check if this is executing in main thread
+ if (mainThread == Thread.currentThread()) {
+ //Still in the main thread, so set the flag just for kicks,
+ // and throw a test passed exception which will be caught
+ // and end the test.
+ theTestPassed = true;
+ throw new TestPassedException();
+ }
+ //pass was called from a different thread, so set the flag and interrupt
+ // the main thead.
+ theTestPassed = true;
+ testGeneratedInterrupt = true;
+ if (mainThread != null) {
+ mainThread.interrupt();
+ }
+ }//pass()
+
+ public static synchronized void fail() {
+ //test writer didn't specify why test failed, so give generic
+ fail("it just plain failed! :-)");
+ }
+
+ public static synchronized void fail(String whyFailed) {
+ Sysout.println("The test failed: " + whyFailed);
+ Sysout.println("The test is over, hit Ctl-C to stop Java VM");
+ //check if this called from main thread
+ if (mainThread == Thread.currentThread()) {
+ //If main thread, fail now 'cause not sleeping
+ throw new RuntimeException(whyFailed);
+ }
+ theTestPassed = false;
+ testGeneratedInterrupt = true;
+ failureMessage = whyFailed;
+ mainThread.interrupt();
+ }//fail()
+
+}// class ManualMainTest
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException {
+}
+
+//*********** End Standard Test Machinery Section **********
+
+
+/****************************************************
+ * Standard Test Machinery
+ * DO NOT modify anything below -- it's a standard
+ * chunk of code whose purpose is to make user
+ * interaction uniform, and thereby make it simpler
+ * to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+ for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+ WithInstructions method. Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+ with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+ as standalone.
+ */
+
+class Sysout {
+ private static TestDialog dialog;
+ private static boolean numbering = false;
+ private static int messageNumber = 0;
+
+ public static void createDialogWithInstructions(String[] instructions) {
+ dialog = new TestDialog(new Frame(), "Instructions");
+ dialog.printInstructions(instructions);
+ dialog.setVisible(true);
+ println("Any messages for the tester will display here.");
+ }
+
+ public static void createDialog() {
+ dialog = new TestDialog(new Frame(), "Instructions");
+ String[] defInstr = {"Instructions will appear here. ", ""};
+ dialog.printInstructions(defInstr);
+ dialog.setVisible(true);
+ println("Any messages for the tester will display here.");
+ }
+
+
+ /* Enables message counting for the tester. */
+ public static void enableNumbering(boolean enable) {
+ numbering = enable;
+ }
+
+ public static void printInstructions(String[] instructions) {
+ dialog.printInstructions(instructions);
+ }
+
+
+ public static void println(String messageIn) {
+ if (numbering) {
+ messageIn = "" + messageNumber + " " + messageIn;
+ messageNumber++;
+ }
+ dialog.displayMessage(messageIn);
+ }
+
+}// Sysout class
+
+/**
+ This is part of the standard test machinery. It provides a place for the
+ test instructions to be displayed, and a place for interactive messages
+ to the user to be displayed.
+ To have the test instructions displayed, see Sysout.
+ To have a message to the user be displayed, see Sysout.
+ Do not call anything in this dialog directly.
+ */
+class TestDialog extends Dialog implements ActionListener {
+
+ TextArea instructionsText;
+ TextArea messageText;
+ int maxStringLength = 80;
+ Panel buttonP = new Panel();
+ Button passB = new Button("pass");
+ Button failB = new Button("fail");
+
+ //DO NOT call this directly, go through Sysout
+ public TestDialog(Frame frame, String name) {
+ super(frame, name);
+ int scrollBoth = TextArea.SCROLLBARS_BOTH;
+ instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
+ add("North", instructionsText);
+
+ messageText = new TextArea("", 5, maxStringLength, scrollBoth);
+ add("Center", messageText);
+
+ passB = new Button("pass");
+ passB.setActionCommand("pass");
+ passB.addActionListener(this);
+ buttonP.add("East", passB);
+
+ failB = new Button("fail");
+ failB.setActionCommand("fail");
+ failB.addActionListener(this);
+ buttonP.add("West", failB);
+
+ add("South", buttonP);
+ pack();
+
+ setVisible(true);
+ }// TestDialog()
+
+ //DO NOT call this directly, go through Sysout
+ public void printInstructions(String[] instructions) {
+ //Clear out any current instructions
+ instructionsText.setText("");
+
+ //Go down array of instruction strings
+
+ String printStr, remainingStr;
+ for (int i = 0; i < instructions.length; i++) {
+ //chop up each into pieces maxSringLength long
+ remainingStr = instructions[i];
+ while (remainingStr.length() > 0) {
+ //if longer than max then chop off first max chars to print
+ if (remainingStr.length() >= maxStringLength) {
+ //Try to chop on a word boundary
+ int posOfSpace = remainingStr.
+ lastIndexOf(' ', maxStringLength - 1);
+
+ if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
+
+ printStr = remainingStr.substring(0, posOfSpace + 1);
+ remainingStr = remainingStr.substring(posOfSpace + 1);
+ }
+ //else just print
+ else {
+ printStr = remainingStr;
+ remainingStr = "";
+ }
+
+ instructionsText.append(printStr + "\n");
+
+ }// while
+
+ }// for
+
+ }//printInstructions()
+
+ //DO NOT call this directly, go through Sysout
+ public void displayMessage(String messageIn) {
+ messageText.append(messageIn + "\n");
+ System.out.println(messageIn);
+ }
+
+ //catch presses of the passed and failed buttons.
+ //simply call the standard pass() or fail() static methods of
+ //ManualMainTest
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand() == "pass") {
+ MacOsXFileAndMultipleFileCopingTest.pass();
+ } else {
+ MacOsXFileAndMultipleFileCopingTest.fail();
+ }
+ }
+
+}// TestDialog class
\ No newline at end of file
--- a/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java Thu Nov 05 13:43:17 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- @test
- @bug 8081787
- @summary MalformedURLException is thrown during reading data for application/x-java-url;class=java.net.URL flavor
- @author Mikhail Cherkasov
- @run main/manual XJavaUrlDataFlavorTest
-*/
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.net.URL;
-
-public class XJavaUrlDataFlavorTest {
- private static void init() {
- String[] instructions =
- {"Test for MacOS X only:",
- "1. The aim is to test that java works fine with \"application/" +
- "x-java-url;class=java.net.URL\"falvor.",
- "2. Open finder and select any file.",
- "3. Press CMD+C or press \"Copy\" in context menu",
- "4. Focus window with \"Test\" Button.",
- "5. If you see URL for selected file, then test PASSED,",
- "otherwise test FAILED."
- };
-
- Sysout.createDialog();
- Sysout.printInstructions(instructions);
-
- final Frame frame = new Frame();
- Panel panel = new Panel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
-
- frame.add(panel);
- Button testButton = new Button("Test");
- final TextField textField = new TextField(40);
- testButton.addActionListener(new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent ae) {
- try {
- Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
- URL url = (URL)board.getData(new DataFlavor("application/x-java-url;class=java.net.URL"));
- textField.setText(url.toString());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
- panel.add(testButton);
- panel.add(textField);
- frame.setBounds(200, 200, 400, 400);
- frame.setVisible(true);
-
- }//End init()
-
-
- /*****************************************************
- * Standard Test Machinery Section
- * DO NOT modify anything in this section -- it's a
- * standard chunk of code which has all of the
- * synchronisation necessary for the test harness.
- * By keeping it the same in all tests, it is easier
- * to read and understand someone else's test, as
- * well as insuring that all tests behave correctly
- * with the test harness.
- * There is a section following this for test-defined
- * classes
- ******************************************************/
- private static boolean theTestPassed = false;
- private static boolean testGeneratedInterrupt = false;
- private static String failureMessage = "";
-
- private static Thread mainThread = null;
-
- private static int sleepTime = 300000;
-
- public static void main(String args[]) throws InterruptedException {
- mainThread = Thread.currentThread();
- try {
- init();
- } catch (TestPassedException e) {
- //The test passed, so just return from main and harness will
- // interepret this return as a pass
- return;
- }
- //At this point, neither test passed nor test failed has been
- // called -- either would have thrown an exception and ended the
- // test, so we know we have multiple threads.
-
- //Test involves other threads, so sleep and wait for them to
- // called pass() or fail()
- try {
- Thread.sleep(sleepTime);
- //Timed out, so fail the test
- throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
- } catch (InterruptedException e) {
- if (!testGeneratedInterrupt) throw e;
-
- //reset flag in case hit this code more than once for some reason (just safety)
- testGeneratedInterrupt = false;
- if (theTestPassed == false) {
- throw new RuntimeException(failureMessage);
- }
- }
-
- }//main
-
- public static synchronized void setTimeoutTo(int seconds) {
- sleepTime = seconds * 1000;
- }
-
- public static synchronized void pass() {
- Sysout.println("The test passed.");
- Sysout.println("The test is over, hit Ctl-C to stop Java VM");
- //first check if this is executing in main thread
- if (mainThread == Thread.currentThread()) {
- //Still in the main thread, so set the flag just for kicks,
- // and throw a test passed exception which will be caught
- // and end the test.
- theTestPassed = true;
- throw new TestPassedException();
- }
- //pass was called from a different thread, so set the flag and interrupt
- // the main thead.
- theTestPassed = true;
- testGeneratedInterrupt = true;
- if (mainThread != null) {
- mainThread.interrupt();
- }
- }//pass()
-
- public static synchronized void fail() {
- //test writer didn't specify why test failed, so give generic
- fail("it just plain failed! :-)");
- }
-
- public static synchronized void fail(String whyFailed) {
- Sysout.println("The test failed: " + whyFailed);
- Sysout.println("The test is over, hit Ctl-C to stop Java VM");
- //check if this called from main thread
- if (mainThread == Thread.currentThread()) {
- //If main thread, fail now 'cause not sleeping
- throw new RuntimeException(whyFailed);
- }
- theTestPassed = false;
- testGeneratedInterrupt = true;
- failureMessage = whyFailed;
- mainThread.interrupt();
- }//fail()
-
-}// class ManualMainTest
-
-//This exception is used to exit from any level of call nesting
-// when it's determined that the test has passed, and immediately
-// end the test.
-class TestPassedException extends RuntimeException {
-}
-
-//*********** End Standard Test Machinery Section **********
-
-
-/****************************************************
- * Standard Test Machinery
- * DO NOT modify anything below -- it's a standard
- * chunk of code whose purpose is to make user
- * interaction uniform, and thereby make it simpler
- * to read and understand someone else's test.
- ****************************************************/
-
-/**
- This is part of the standard test machinery.
- It creates a dialog (with the instructions), and is the interface
- for sending text messages to the user.
- To print the instructions, send an array of strings to Sysout.createDialog
- WithInstructions method. Put one line of instructions per array entry.
- To display a message for the tester to see, simply call Sysout.println
- with the string to be displayed.
- This mimics System.out.println but works within the test harness as well
- as standalone.
- */
-
-class Sysout {
- private static TestDialog dialog;
- private static boolean numbering = false;
- private static int messageNumber = 0;
-
- public static void createDialogWithInstructions(String[] instructions) {
- dialog = new TestDialog(new Frame(), "Instructions");
- dialog.printInstructions(instructions);
- dialog.setVisible(true);
- println("Any messages for the tester will display here.");
- }
-
- public static void createDialog() {
- dialog = new TestDialog(new Frame(), "Instructions");
- String[] defInstr = {"Instructions will appear here. ", ""};
- dialog.printInstructions(defInstr);
- dialog.setVisible(true);
- println("Any messages for the tester will display here.");
- }
-
-
- /* Enables message counting for the tester. */
- public static void enableNumbering(boolean enable) {
- numbering = enable;
- }
-
- public static void printInstructions(String[] instructions) {
- dialog.printInstructions(instructions);
- }
-
-
- public static void println(String messageIn) {
- if (numbering) {
- messageIn = "" + messageNumber + " " + messageIn;
- messageNumber++;
- }
- dialog.displayMessage(messageIn);
- }
-
-}// Sysout class
-
-/**
- This is part of the standard test machinery. It provides a place for the
- test instructions to be displayed, and a place for interactive messages
- to the user to be displayed.
- To have the test instructions displayed, see Sysout.
- To have a message to the user be displayed, see Sysout.
- Do not call anything in this dialog directly.
- */
-class TestDialog extends Dialog implements ActionListener {
-
- TextArea instructionsText;
- TextArea messageText;
- int maxStringLength = 80;
- Panel buttonP = new Panel();
- Button passB = new Button("pass");
- Button failB = new Button("fail");
-
- //DO NOT call this directly, go through Sysout
- public TestDialog(Frame frame, String name) {
- super(frame, name);
- int scrollBoth = TextArea.SCROLLBARS_BOTH;
- instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
- add("North", instructionsText);
-
- messageText = new TextArea("", 5, maxStringLength, scrollBoth);
- add("Center", messageText);
-
- passB = new Button("pass");
- passB.setActionCommand("pass");
- passB.addActionListener(this);
- buttonP.add("East", passB);
-
- failB = new Button("fail");
- failB.setActionCommand("fail");
- failB.addActionListener(this);
- buttonP.add("West", failB);
-
- add("South", buttonP);
- pack();
-
- setVisible(true);
- }// TestDialog()
-
- //DO NOT call this directly, go through Sysout
- public void printInstructions(String[] instructions) {
- //Clear out any current instructions
- instructionsText.setText("");
-
- //Go down array of instruction strings
-
- String printStr, remainingStr;
- for (int i = 0; i < instructions.length; i++) {
- //chop up each into pieces maxSringLength long
- remainingStr = instructions[i];
- while (remainingStr.length() > 0) {
- //if longer than max then chop off first max chars to print
- if (remainingStr.length() >= maxStringLength) {
- //Try to chop on a word boundary
- int posOfSpace = remainingStr.
- lastIndexOf(' ', maxStringLength - 1);
-
- if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
-
- printStr = remainingStr.substring(0, posOfSpace + 1);
- remainingStr = remainingStr.substring(posOfSpace + 1);
- }
- //else just print
- else {
- printStr = remainingStr;
- remainingStr = "";
- }
-
- instructionsText.append(printStr + "\n");
-
- }// while
-
- }// for
-
- }//printInstructions()
-
- //DO NOT call this directly, go through Sysout
- public void displayMessage(String messageIn) {
- messageText.append(messageIn + "\n");
- System.out.println(messageIn);
- }
-
- //catch presses of the passed and failed buttons.
- //simply call the standard pass() or fail() static methods of
- //ManualMainTest
- public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand() == "pass") {
- XJavaUrlDataFlavorTest.pass();
- } else {
- XJavaUrlDataFlavorTest.fail();
- }
- }
-
-}// TestDialog class
--- a/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6425068 7157659
+ * @bug 6425068 7157659 8132890
* @summary Confirm that text prints where we expect to the length we expect.
* @run main/manual=yesno PrintTextTest
*/
@@ -113,6 +113,32 @@
book.append(ptt, portrait);
book.append(ptt, landscape);
+ font = new Font("Dialog", Font.PLAIN, 18);
+ AffineTransform scaleTx = AffineTransform.getScaleInstance(1.25, 1.25);
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, font, scaleTx, false);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
+ font = new Font("Dialog", Font.PLAIN, 18);
+ scaleTx = AffineTransform.getScaleInstance(-1.25, 1.25);
+ scaleTx.translate(-preferredSize/1.25, 0);
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, font, scaleTx, false);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
+ font = new Font("Dialog", Font.PLAIN, 18);
+ scaleTx = AffineTransform.getScaleInstance(1.25, -1.25);
+ scaleTx.translate(0, -preferredSize/1.25);
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, font, scaleTx, false);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
font = font.deriveFont(rotTx);
name = "Page " + new Integer(page++);
ptt = new PrintTextTest(name, font, null, false);
@@ -121,6 +147,30 @@
book.append(ptt, portrait);
book.append(ptt, landscape);
+ font = new Font("Monospaced", Font.PLAIN, 12);
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, font, null, false);
+ p.add(ptt, BorderLayout.CENTER);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
+ Font xfont = font.deriveFont(AffineTransform.getScaleInstance(1.5, 1));
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, xfont, null, false);
+ p.add(ptt, BorderLayout.CENTER);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
+ Font yfont = font.deriveFont(AffineTransform.getScaleInstance(1, 1.5));
+ name = "Page " + new Integer(page++);
+ ptt = new PrintTextTest(name, yfont, null, false);
+ p.add(ptt, BorderLayout.CENTER);
+ p.add(name, ptt);
+ book.append(ptt, portrait);
+ book.append(ptt, landscape);
+
if (System.getProperty("os.name").startsWith("Windows")) {
font = new Font("MS Gothic", Font.PLAIN, 12);
name = "Page " + new Integer(page++);
--- a/jdk/test/java/lang/Class/IsEnum.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/java/lang/Class/IsEnum.java Wed Jul 05 20:59:18 2017 +0200
@@ -32,8 +32,8 @@
public class IsEnum {
- static int test(Class clazz, boolean expected) {
- int status = (clazz.isEnum() == expected)?0:1;
+ static int test(Class<?> clazz, boolean expected) {
+ int status = (clazz.isEnum() == expected) ? 0 : 1;
if (status == 1) {
System.err.println("Unexpected enum status for " + clazz);
@@ -41,23 +41,23 @@
return status;
}
- public static void main(String argv[]) {
+ public static void main(String... argv) {
int failures = 0;
failures += test(IsEnum.class, false);
failures += test(String.class, false);
failures += test(Enum.class, false);
+ failures += test(EnumPoseur.class, false);
failures += test(java.math.RoundingMode.class, true);
- // Classes in java.lang.annoation
+ // Classes in java.lang.annotation
failures += test(Annotation.class, false);
failures += test(ElementType.class, true);
failures += test(Retention.class, false);
failures += test(RetentionPolicy.class, true);
failures += test(Target.class, false);
- failures += test(EnumPoseur.class, false);
- // Classes for specialized enum constants aren't enum's
+ // A class for a specialized enum constant isn't itself an enum
failures += test(SpecialEnum.class, true);
failures += test(SpecialEnum.RED.getClass(), false);
failures += test(SpecialEnum.GREEN.getClass(), true);
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -27,9 +27,11 @@
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -44,6 +46,7 @@
* @library /lib/testlibrary
* Test counting and JavaChild.spawning and counting of Processes.
* @run testng/othervm InfoTest
+ * @key intermittent
* @author Roger Riggs
*/
public class TreeTest extends ProcessUtil {
@@ -195,7 +198,7 @@
allChildren.stream().map(p -> p.getPid())
.collect(Collectors.toList()));
- // Verify that all spawned children show up in the allChildrenList
+ // Verify that all spawned children show up in the allChildren List
processes.forEach((p, parent) -> {
Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p);
@@ -241,6 +244,7 @@
printf(" p1: %s%n", p1.getPid());
int newChildren = 3;
+ CountDownLatch spawnCount = new CountDownLatch(newChildren);
// Spawn children and have them wait
p1.sendAction("spawn", newChildren, "stdin");
@@ -251,11 +255,26 @@
Long child = Long.valueOf(split[2]);
Long parent = Long.valueOf(split[0].split(":")[0]);
processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
+ spawnCount.countDown();
}
});
- // Wait for the new processes and save the list
- List<ProcessHandle> allChildren = waitForAllChildren(p1Handle, newChildren);
+ // Wait for all the subprocesses to be listed as started
+ Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
+ "Timeout waiting for processes to start");
+
+ // Debugging; list allChildren that are not expected in processes
+ List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle);
+ long count = allChildren.stream()
+ .filter(ph -> !processes.containsKey(ph))
+ .count();
+ if (count > 0) {
+ allChildren.stream()
+ .filter(ph -> !processes.containsKey(ph))
+ .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
+ ProcessUtil.logTaskList();
+ Assert.assertEquals(0, count, "Extra processes in allChildren");
+ }
// Verify that all spawned children are alive, show up in the allChildren list
// then destroy them
@@ -266,6 +285,7 @@
});
Assert.assertEquals(processes.size(), newChildren, "Wrong number of children");
+ // Wait for each of the processes to exit
processes.forEach((p, parent) -> {
for (long retries = Utils.adjustTimeout(100L); retries > 0 ; retries--) {
if (!p.isAlive()) {
@@ -285,8 +305,10 @@
p1.destroyForcibly();
p1.waitFor();
+ // Verify that none of the spawned children are still listed by allChildren
List<ProcessHandle> remaining = getAllChildren(self);
- remaining = remaining.stream().filter(processes::contains).collect(Collectors.toList());
+ Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited");
+ remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList());
Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining);
} catch (IOException ioe) {
@@ -354,6 +376,8 @@
*/
@Test
public static void test5() {
+ ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();
+
int factor = 2;
JavaChild p1 = null;
Instant start = Instant.now();
@@ -374,11 +398,39 @@
p1.sendAction("child", "child", "spawn", factor, "stdin");
int newChildren = factor * (1 + factor * (1 + factor));
- List<ProcessHandle> children = ProcessUtil.waitForAllChildren(p1Handle, newChildren);
+ CountDownLatch spawnCount = new CountDownLatch(newChildren);
+
+ // Gather the PIDs from the output of the spawning process
+ p1.forEachOutputLine((s) -> {
+ String[] split = s.trim().split(" ");
+ if (split.length == 3 && split[1].equals("spawn")) {
+ Long child = Long.valueOf(split[2]);
+ Long parent = Long.valueOf(split[0].split(":")[0]);
+ processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
+ spawnCount.countDown();
+ }
+ });
+
+ // Wait for all the subprocesses to be listed as started
+ Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
+ "Timeout waiting for processes to start");
+
+ // Debugging; list allChildren that are not expected in processes
+ List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle);
+ long count = allChildren.stream()
+ .filter(ph -> !processes.containsKey(ph))
+ .count();
+ if (count > 0) {
+ allChildren.stream()
+ .filter(ph -> !processes.containsKey(ph))
+ .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
+ ProcessUtil.logTaskList();
+ Assert.assertEquals(0, count, "Extra processes in allChildren");
+ }
Assert.assertEquals(getChildren(p1Handle).size(),
factor, "expected direct children");
- long count = getAllChildren(p1Handle).size();
+ count = getAllChildren(p1Handle).size();
long totalChildren = factor * factor * factor + factor * factor + factor;
Assert.assertTrue(count >= totalChildren,
"expected at least " + totalChildren + ", actual: " + count);
@@ -397,6 +449,12 @@
if (p1 != null) {
p1.destroyForcibly();
}
+ processes.forEach((p, parent) -> {
+ if (p.isAlive()) {
+ ProcessUtil.printProcess(p, "Process Cleanup: ");
+ p.destroyForcibly();
+ }
+ });
}
}
--- a/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -23,6 +23,7 @@
/*
* @test LFSingleThreadCachingTest
+ * @ignore 8129523
* @bug 8046703
* @key randomness
* @summary Test verifies that lambda forms are cached when run with single thread
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8033148
+ * @summary tests for array equals and compare
+ * @run testng ArraysEqCmpTest
+*/
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.LongFunction;
+import java.util.stream.IntStream;
+
+public class ArraysEqCmpTest {
+
+ // Maximum width in bits
+ static final int MAX_WIDTH = 512;
+
+ static final Map<Class, Integer> typeToWidth;
+
+ static {
+ typeToWidth = new HashMap<>();
+ typeToWidth.put(boolean.class, Byte.SIZE);
+ typeToWidth.put(byte.class, Byte.SIZE);
+ typeToWidth.put(short.class, Short.SIZE);
+ typeToWidth.put(char.class, Character.SIZE);
+ typeToWidth.put(int.class, Integer.SIZE);
+ typeToWidth.put(long.class, Long.SIZE);
+ typeToWidth.put(float.class, Float.SIZE);
+ typeToWidth.put(double.class, Double.SIZE);
+ typeToWidth.put(Object.class, Integer.SIZE); // @@@ 32 or 64?
+ }
+
+ static int arraySizeFor(Class<?> type) {
+ type = type.isPrimitive() ? type : Object.class;
+ return 4 * MAX_WIDTH / typeToWidth.get(type);
+ }
+
+ static abstract class ArrayType<T> {
+ final Class<?> arrayType;
+ final Class<?> componentType;
+ final boolean unsigned;
+
+ final MethodHandle cpy;
+
+ final MethodHandle eq;
+ final MethodHandle eqr;
+ final MethodHandle cmp;
+ final MethodHandle cmpr;
+ final MethodHandle mm;
+ final MethodHandle mmr;
+
+ final MethodHandle getter;
+
+ final MethodHandle toString;
+
+ public ArrayType(Class<T> arrayType) {
+ this(arrayType, false);
+ }
+
+ public ArrayType(Class<T> arrayType, boolean unsigned) {
+ this.arrayType = arrayType;
+ this.componentType = arrayType.getComponentType();
+ this.unsigned = unsigned;
+
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+
+ getter = MethodHandles.arrayElementGetter(arrayType);
+
+ if (componentType.isPrimitive()) {
+ cpy = l.findStatic(Arrays.class, "copyOfRange",
+ MethodType.methodType(arrayType, arrayType, int.class, int.class));
+
+ MethodType eqt = MethodType.methodType(
+ boolean.class, arrayType, arrayType);
+ MethodType eqrt = MethodType.methodType(
+ boolean.class, arrayType, int.class, int.class, arrayType, int.class, int.class);
+
+ eq = l.findStatic(Arrays.class, "equals", eqt);
+ eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+ String compareName = unsigned ? "compareUnsigned" : "compare";
+ cmp = l.findStatic(Arrays.class, compareName,
+ eqt.changeReturnType(int.class));
+ cmpr = l.findStatic(Arrays.class, compareName,
+ eqrt.changeReturnType(int.class));
+
+ mm = l.findStatic(Arrays.class, "mismatch",
+ eqt.changeReturnType(int.class));
+ mmr = l.findStatic(Arrays.class, "mismatch",
+ eqrt.changeReturnType(int.class));
+
+ toString = l.findStatic(Arrays.class, "toString",
+ MethodType.methodType(String.class, arrayType));
+ }
+ else {
+ cpy = l.findStatic(Arrays.class, "copyOfRange",
+ MethodType.methodType(Object[].class, Object[].class, int.class, int.class));
+
+ MethodType eqt = MethodType.methodType(
+ boolean.class, Object[].class, Object[].class);
+ MethodType eqrt = MethodType.methodType(
+ boolean.class, Object[].class, int.class, int.class, Object[].class, int.class, int.class);
+
+ eq = l.findStatic(Arrays.class, "equals", eqt);
+ eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+ MethodType cmpt = MethodType.methodType(
+ int.class, Comparable[].class, Comparable[].class);
+ MethodType cmprt = MethodType.methodType(
+ int.class, Comparable[].class, int.class, int.class, Comparable[].class, int.class, int.class);
+
+ cmp = l.findStatic(Arrays.class, "compare", cmpt);
+ cmpr = l.findStatic(Arrays.class, "compare", cmprt);
+
+ mm = l.findStatic(Arrays.class, "mismatch",
+ eqt.changeReturnType(int.class));
+ mmr = l.findStatic(Arrays.class, "mismatch",
+ eqrt.changeReturnType(int.class));
+
+ toString = l.findStatic(Arrays.class, "toString",
+ MethodType.methodType(String.class, Object[].class));
+ }
+
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String s = arrayType.getCanonicalName();
+ return unsigned ? "unsigned " + s : s;
+ }
+
+ Object construct(int length) {
+ return Array.newInstance(componentType, length);
+ }
+
+ Object copyOf(Object a) {
+ return copyOf(a, 0, Array.getLength(a));
+ }
+
+ Object copyOf(Object a, int from, int to) {
+ try {
+ return (Object) cpy.invoke(a, from, to);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ Object get(Object a, int i) {
+ try {
+ return (Object) getter.invoke(a, i);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ abstract void set(Object a, int i, Object v);
+
+ boolean equals(Object a, Object b) {
+ try {
+ return (boolean) eq.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ boolean equals(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (boolean) eqr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int compare(Object a, Object b) {
+ try {
+ return (int) cmp.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int compare(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) cmpr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int mismatch(Object a, Object b) {
+ try {
+ return (int) mm.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int mismatch(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) mmr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ String toString(Object a) {
+ try {
+ return (String) toString.invoke(a);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ static class BoxedIntegers extends ArrayType<Integer[]> {
+ public BoxedIntegers() {
+ super(Integer[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ // Ensure unique reference
+ ((Integer[]) a)[i] = v != null ? new Integer((Integer) v) : null;
+ }
+ }
+
+ static class BoxedIntegersWithReverseComparator extends BoxedIntegers {
+ final Comparator<Integer> c = (a, b) -> {
+ // Nulls sort after non-nulls
+ if (a == null || b == null)
+ return a == null ? b == null ? 0 : 1 : -1;
+
+ return Integer.compare(b, a);
+ };
+
+ final MethodHandle cmpc;
+ final MethodHandle cmpcr;
+ final MethodHandle mismatchc;
+ final MethodHandle mismatchcr;
+
+ public BoxedIntegersWithReverseComparator() {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+
+ MethodType cmpt = MethodType.methodType(
+ int.class, Object[].class, Object[].class, Comparator.class);
+ MethodType cmprt = MethodType.methodType(
+ int.class, Object[].class, int.class, int.class,
+ Object[].class, int.class, int.class, Comparator.class);
+
+ cmpc = l.findStatic(Arrays.class, "compare", cmpt);
+ cmpcr = l.findStatic(Arrays.class, "compare", cmprt);
+ mismatchc = l.findStatic(Arrays.class, "mismatch", cmpt);
+ mismatchcr = l.findStatic(Arrays.class, "mismatch", cmprt);
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ @Override
+ int compare(Object a, Object b) {
+ try {
+ return (int) cmpc.invoke(a, b, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int compare(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) cmpcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int mismatch(Object a, Object b) {
+ try {
+ return (int) mismatchc.invoke(a, b, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int mismatch(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) mismatchcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return arrayType.getCanonicalName() + " with Comparator";
+ }
+ }
+
+ static class Booleans extends ArrayType<boolean[]> {
+ public Booleans() {
+ super(boolean[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ boolean pv;
+ if (v instanceof Boolean) {
+ pv = (Boolean) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v) >= 0;
+ }
+ else throw new IllegalStateException();
+
+ ((boolean[]) a)[i] = pv;
+ }
+ }
+
+ static class Bytes extends ArrayType<byte[]> {
+ public Bytes(boolean unsigned) {
+ super(byte[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ byte pv;
+ if (v instanceof Byte) {
+ pv = (Byte) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).byteValue();
+ }
+ else throw new IllegalStateException();
+
+ ((byte[]) a)[i] = pv;
+ }
+ }
+
+ static class Characters extends ArrayType<char[]> {
+ public Characters() {
+ super(char[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ char pv;
+ if (v instanceof Character) {
+ pv = (Character) v;
+ }
+ else if (v instanceof Integer) {
+ pv = (char) ((Integer) v).intValue();
+ }
+ else throw new IllegalStateException();
+
+ ((char[]) a)[i] = pv;
+ }
+ }
+
+ static class Shorts extends ArrayType<short[]> {
+ public Shorts(boolean unsigned) {
+ super(short[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ short pv;
+ if (v instanceof Short) {
+ pv = (Short) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).shortValue();
+ }
+ else throw new IllegalStateException();
+
+ ((short[]) a)[i] = pv;
+ }
+ }
+
+ static class Integers extends ArrayType<int[]> {
+ public Integers(boolean unsigned) {
+ super(int[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ int pv;
+ if (v instanceof Integer) {
+ pv = ((Integer) v).shortValue();
+ }
+ else throw new IllegalStateException();
+
+ ((int[]) a)[i] = pv;
+ }
+ }
+
+ static class Longs extends ArrayType<long[]> {
+ public Longs(boolean unsigned) {
+ super(long[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ long pv;
+ if (v instanceof Long) {
+ pv = (Long) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).longValue();
+ }
+ else throw new IllegalStateException();
+
+ ((long[]) a)[i] = pv;
+ }
+ }
+
+ static class Floats extends ArrayType<float[]> {
+ public Floats() {
+ super(float[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ float pv;
+ if (v instanceof Float) {
+ pv = (Float) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).floatValue();
+ }
+ else throw new IllegalStateException();
+
+ ((float[]) a)[i] = pv;
+ }
+ }
+
+ static class Doubles extends ArrayType<double[]> {
+ public Doubles() {
+ super(double[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ double pv;
+ if (v instanceof Double) {
+ pv = (Double) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).doubleValue();
+ }
+ else throw new IllegalStateException();
+
+ ((double[]) a)[i] = pv;
+ }
+ }
+ }
+
+ static Object[][] arrayTypes;
+
+ @DataProvider
+ public static Object[][] arrayTypesProvider() {
+ if (arrayTypes == null) {
+ arrayTypes = new Object[][]{
+ new Object[]{new ArrayType.BoxedIntegers()},
+ new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+ new Object[]{new ArrayType.Booleans()},
+ new Object[]{new ArrayType.Bytes(false)},
+ new Object[]{new ArrayType.Bytes(true)},
+ new Object[]{new ArrayType.Characters()},
+ new Object[]{new ArrayType.Shorts(false)},
+ new Object[]{new ArrayType.Shorts(true)},
+ new Object[]{new ArrayType.Integers(false)},
+ new Object[]{new ArrayType.Integers(true)},
+ new Object[]{new ArrayType.Longs(false)},
+ new Object[]{new ArrayType.Longs(true)},
+ new Object[]{new ArrayType.Floats()},
+ new Object[]{new ArrayType.Doubles()},
+ };
+ }
+ return arrayTypes;
+ }
+
+ static Object[][] floatArrayTypes;
+
+ @DataProvider
+ public static Object[][] floatArrayTypesProvider() {
+ if (floatArrayTypes == null) {
+ LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+ LongFunction<Object> bToD = Double::longBitsToDouble;
+
+ floatArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.Floats(), 0x7fc00000L, 0x7f800001L, bTof},
+ new Object[]{new ArrayType.Doubles(), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
+ };
+ }
+ return floatArrayTypes;
+ }
+
+ static Object[][] objectArrayTypes;
+
+ @DataProvider
+ public static Object[][] objectArrayTypesProvider() {
+ if (objectArrayTypes == null) {
+ LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+ LongFunction<Object> bToD = Double::longBitsToDouble;
+
+ objectArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.BoxedIntegers()},
+ new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+ };
+ }
+ return objectArrayTypes;
+ }
+
+
+ static Object[][] signedUnsignedArrayTypes;
+
+ @DataProvider
+ public static Object[][] signedUnsignedArrayTypes() {
+ if (signedUnsignedArrayTypes == null) {
+ signedUnsignedArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.Bytes(false), new ArrayType.Bytes(true)},
+ new Object[]{new ArrayType.Shorts(false), new ArrayType.Shorts(true)},
+ new Object[]{new ArrayType.Integers(false), new ArrayType.Integers(true)},
+ new Object[]{new ArrayType.Longs(false), new ArrayType.Longs(true)},
+ };
+ }
+ return signedUnsignedArrayTypes;
+ }
+
+ // Equality and comparison tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, x % 8);
+ }
+ return a;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> cloner = (at, a) ->
+ constructor.apply(at, Array.getLength(a));
+
+ testArrayType(arrayType, constructor, cloner);
+ }
+
+ @Test(dataProvider = "floatArrayTypesProvider")
+ public void testPrimitiveFloatArray(
+ ArrayType<?> arrayType,
+ long canonicalNanRawBits, long nonCanonicalNanRawBits,
+ LongFunction<Object> bitsToFloat) {
+ Object canonicalNan = bitsToFloat.apply(canonicalNanRawBits);
+ // If conversion is a signalling NaN it may be subject to conversion to a
+ // quiet NaN on some processors, even if a copy is performed
+ // The tests assume that if conversion occurs it does not convert to the
+ // canonical NaN
+ Object nonCanonicalNan = bitsToFloat.apply(nonCanonicalNanRawBits);
+
+ BiFunction<ArrayType<?>, Integer, Object> canonicalNaNs = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, canonicalNan);
+ }
+ return a;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> nonCanonicalNaNs = (at, a) -> {
+ int s = Array.getLength(a);
+ Object ac = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(ac, x, nonCanonicalNan);
+ }
+ return ac;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> halfNonCanonicalNaNs = (at, a) -> {
+ int s = Array.getLength(a);
+ Object ac = at.construct(s);
+ for (int x = 0; x < s / 2; x++) {
+ at.set(ac, x, nonCanonicalNan);
+ }
+ for (int x = s / 2; x < s; x++) {
+ at.set(ac, x, 1);
+ }
+ return ac;
+ };
+
+ testArrayType(arrayType, canonicalNaNs, nonCanonicalNaNs);
+ testArrayType(arrayType, canonicalNaNs, halfNonCanonicalNaNs);
+ }
+
+ @Test(dataProvider = "objectArrayTypesProvider")
+ public void testNullElementsInObjectArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+ // All nulls
+ testArrayType(arrayType,
+ (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, null);
+ }
+ return a;
+ },
+ cloner);
+
+
+ // Some nulls
+ testArrayType(arrayType,
+ (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ int v = x % 8;
+ at.set(a, x, v == 0 ? null : v);
+ }
+ return a;
+ },
+ cloner);
+
+ Integer[] a = new Integer[]{null, 0};
+ Integer[] b = new Integer[]{0, 0};
+ Assert.assertTrue(Arrays.compare(a, b) < 0);
+ Assert.assertTrue(Arrays.compare(b, a) > 0);
+ }
+
+ @Test(dataProvider = "objectArrayTypesProvider")
+ public void testSameRefElementsInObjectArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+ // One ref
+ Integer one = 1;
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ a[x] = one;
+ }
+ return a;
+ },
+ cloner);
+
+ // All ref
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ a[x] = Integer.valueOf(s);
+ }
+ return a;
+ },
+ cloner);
+
+ // Some same ref
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ int v = x % 8;
+ a[x] = v == 1 ? one : new Integer(v);
+ }
+ return a;
+ },
+ cloner);
+ }
+
+ @Test(dataProvider = "signedUnsignedArrayTypes")
+ public void testSignedUnsignedArray(ArrayType<?> sat, ArrayType<?> uat) {
+ BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, 1);
+ }
+ return a;
+ };
+
+ int n = arraySizeFor(sat.componentType);
+
+ for (int s : ranges(0, n)) {
+ Object a = constructor.apply(sat, s);
+
+ for (int aFrom : ranges(0, s)) {
+ for (int aTo : ranges(aFrom, s)) {
+ int aLength = aTo - aFrom;
+
+ if (aLength > 0) {
+ for (int i = aFrom; i < aTo; i++) {
+ Object ac = sat.copyOf(a);
+ // Create common prefix with a length of i - aFrom
+ sat.set(ac, i, -1);
+
+ int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+ int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+
+ Assert.assertTrue(sc < 0);
+ Assert.assertTrue(uc > 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void testArrayType(ArrayType<?> at,
+ BiFunction<ArrayType<?>, Integer, Object> constructor,
+ BiFunction<ArrayType<?>, Object, Object> cloner) {
+ int n = arraySizeFor(at.componentType);
+
+ for (int s : ranges(0, n)) {
+ Object a = constructor.apply(at, s);
+ Object b = cloner.apply(at, a);
+
+ for (int aFrom : ranges(0, s)) {
+ for (int aTo : ranges(aFrom, s)) {
+ int aLength = aTo - aFrom;
+
+ for (int bFrom : ranges(0, s)) {
+ for (int bTo : ranges(bFrom, s)) {
+ int bLength = bTo - bFrom;
+
+ Object anr = at.copyOf(a, aFrom, aTo);
+ Object bnr = at.copyOf(b, bFrom, bTo);
+
+ boolean eq = isEqual(at, a, aFrom, aTo, b, bFrom, bTo);
+ Assert.assertEquals(at.equals(a, aFrom, aTo, b, bFrom, bTo), eq);
+ Assert.assertEquals(at.equals(b, bFrom, bTo, a, aFrom, aTo), eq);
+ Assert.assertEquals(at.equals(anr, bnr), eq);
+ Assert.assertEquals(at.equals(bnr, anr), eq);
+ if (eq) {
+ Assert.assertEquals(at.compare(a, aFrom, aTo, b, bFrom, bTo), 0);
+ Assert.assertEquals(at.compare(b, bFrom, bTo, a, aFrom, aTo), 0);
+ Assert.assertEquals(at.compare(anr, bnr), 0);
+ Assert.assertEquals(at.compare(bnr, anr), 0);
+
+ Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1);
+ Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1);
+ Assert.assertEquals(at.mismatch(anr, bnr), -1);
+ Assert.assertEquals(at.mismatch(bnr, anr), -1);
+ }
+ else {
+ int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo);
+ int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo);
+ int v = Integer.signum(aCb) * Integer.signum(bCa);
+ Assert.assertTrue(v == -1);
+
+ int anrCbnr = at.compare(anr, bnr);
+ int bnrCanr = at.compare(bnr, anr);
+ Assert.assertEquals(anrCbnr, aCb);
+ Assert.assertEquals(bnrCanr, bCa);
+
+
+ int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo);
+ int bMa = at.mismatch(b, bFrom, bTo, a, aFrom, aTo);
+ int anrMbnr = at.mismatch(anr, bnr);
+ int bnrManr = at.mismatch(bnr, anr);
+
+ Assert.assertNotEquals(aMb, -1);
+ Assert.assertEquals(aMb, bMa);
+ Assert.assertNotEquals(anrMbnr, -1);
+ Assert.assertEquals(anrMbnr, bnrManr);
+ Assert.assertEquals(aMb, anrMbnr);
+ Assert.assertEquals(bMa, bnrManr);
+
+ // Common or proper prefix
+ Assert.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb));
+ if (aMb < Math.min(aLength, bLength)) {
+ // Common prefix
+ Assert.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb));
+ }
+ }
+ }
+ }
+
+ if (aLength > 0) {
+ for (int i = aFrom; i < aTo; i++) {
+ Object ac = at.copyOf(a);
+ // Create common prefix with a length of i - aFrom
+ at.set(ac, i, -1);
+
+ Object acnr = at.copyOf(ac, aFrom, aTo);
+ Object anr = at.copyOf(a, aFrom, aTo);
+
+ Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo));
+ Assert.assertFalse(at.equals(acnr, anr));
+
+ int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo);
+ int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo);
+ int v = Integer.signum(acCa) * Integer.signum(aCac);
+ Assert.assertTrue(v == -1);
+
+ int acnrCanr = at.compare(acnr, anr);
+ int anrCacnr = at.compare(anr, acnr);
+ Assert.assertEquals(acnrCanr, acCa);
+ Assert.assertEquals(anrCacnr, aCac);
+
+
+ int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo);
+ int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo);
+ Assert.assertEquals(acMa, aMac);
+ Assert.assertEquals(acMa, i - aFrom);
+
+ int acnrManr = at.mismatch(acnr, anr);
+ int anrMacnr = at.mismatch(anr, acnr);
+ Assert.assertEquals(acnrManr, anrMacnr);
+ Assert.assertEquals(acnrManr, i - aFrom);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static boolean isEqual(ArrayType<?> at, Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++) {
+ Object av = at.get(a, aFromIndex++);
+ Object bv = at.get(b, bFromIndex++);
+ if (!Objects.equals(av, bv)) return false;
+ }
+
+ return true;
+ }
+
+ static boolean isEqual(ArrayType<?> at, Object a, int aFrom, Object b, int bFrom) {
+ Object av = at.get(a, aFrom);
+ Object bv = at.get(b, bFrom);
+
+ return Objects.equals(av, bv);
+ }
+
+ static int[] ranges(int from, int to) {
+ int width = to - from;
+ switch (width) {
+ case 0:
+ return new int[]{};
+ case 1:
+ return new int[]{from, to};
+ case 2:
+ return new int[]{from, from + 1, to};
+ case 3:
+ return new int[]{from, from + 1, from + 2, to};
+ default:
+ return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
+ .filter(i -> i >= from && i <= to)
+ .distinct().toArray();
+ }
+ }
+
+
+ // Null array reference tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testNullArrayRefs(ArrayType<?> arrayType) {
+ Object n = null;
+ Object a = arrayType.construct(0);
+
+ Assert.assertTrue(arrayType.equals(n, n));
+ Assert.assertFalse(arrayType.equals(n, a));
+ Assert.assertFalse(arrayType.equals(a, n));
+
+ Assert.assertEquals(arrayType.compare(n, n), 0);
+ Assert.assertTrue(arrayType.compare(n, a) < 0);
+ Assert.assertTrue(arrayType.compare(a, n) > 0);
+ }
+
+
+ // Exception throwing tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testNPEs(ArrayType<?> arrayType) {
+ Object[] values = new Object[]{null, arrayType.construct(0)};
+
+ for (Object o1 : values) {
+ for (Object o2 : values) {
+ if (o1 != null && o2 != null)
+ continue;
+
+ testNPE(() -> arrayType.equals(o1, 0, 0, o2, 0, 0));
+ testNPE(() -> arrayType.compare(o1, 0, 0, o2, 0, 0));
+ testNPE(() -> arrayType.mismatch(o1, o2));
+ testNPE(() -> arrayType.mismatch(o1, 0, 0, o2, 0, 0));
+ }
+ }
+ }
+
+ @Test
+ public void testObjectNPEs() {
+ String[][] values = new String[][]{null, new String[0]};
+ Comparator<String> c = String::compareTo;
+ Comparator[] cs = new Comparator[]{null, c};
+
+ for (String[] o1 : values) {
+ for (String[] o2 : values) {
+ for (Comparator o3 : cs) {
+ if (o1 != null && o2 != null && o3 != null)
+ continue;
+
+ if (o3 == null) {
+ testNPE(() -> Arrays.compare(o1, o2, o3));
+ testNPE(() -> Arrays.mismatch(o1, o2, o3));
+ }
+
+ testNPE(() -> Arrays.compare(o1, 0, 0, o2, 0, 0, o3));
+ testNPE(() -> Arrays.mismatch(o1, 0, 0, o2, 0, 0, o3));
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testIAEs(ArrayType<?> arrayType) {
+ List<Integer> values = Arrays.asList(0, 1);
+
+ for (int s : values) {
+ Object a = arrayType.construct(s);
+
+ for (int o1 : values) {
+ for (int o2 : values) {
+ if (o1 <= o2) continue;
+
+ testIAE(() -> arrayType.equals(a, o1, 0, a, o2, 0));
+ testIAE(() -> arrayType.compare(a, o1, 0, a, o2, 0));
+ testIAE(() -> arrayType.mismatch(a, o1, 0, a, o2, 0));
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testAIOBEs(ArrayType<?> arrayType) {
+ List<Integer> froms = Arrays.asList(-1, 0);
+
+ for (int s : Arrays.asList(0, 1)) {
+ List<Integer> tos = Arrays.asList(s, s + 1);
+ Object a = arrayType.construct(s);
+
+ for (int aFrom : froms) {
+ for (int aTo : tos) {
+ for (int bFrom : froms) {
+ for (int bTo : tos) {
+ if (aFrom >= 0 && aTo <= s &&
+ bFrom >= 0 && bTo <= s) continue;
+
+ testAIOBE(() -> arrayType.equals(a, aFrom, aTo, a, bFrom, bTo));
+ testAIOBE(() -> arrayType.compare(a, aFrom, aTo, a, bFrom, bTo));
+ testAIOBE(() -> arrayType.mismatch(a, aFrom, aTo, a, bFrom, bTo));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static void testNPE(Runnable r) {
+ testThrowable(r, NullPointerException.class);
+ }
+
+ static void testIAE(Runnable r) {
+ testThrowable(r, IllegalArgumentException.class);
+ }
+
+ static void testAIOBE(Runnable r) {
+ testThrowable(r, ArrayIndexOutOfBoundsException.class);
+ }
+
+ static void testThrowable(Runnable r, Class<? extends Throwable> expected) {
+ Throwable caught = null;
+ try {
+ r.run();
+ }
+ catch (Throwable t) {
+ caught = t;
+ }
+ Assert.assertNotNull(caught);
+ Assert.assertTrue(expected.isInstance(caught));
+ }
+}
\ No newline at end of file
--- a/jdk/test/java/util/Locale/LocaleProviders.sh Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/java/util/Locale/LocaleProviders.sh Wed Jul 05 20:59:18 2017 +0200
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
#
# @test
# @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577
-# 8010666 8013086 8013233 8013903 8015960 8028771
+# 8010666 8013086 8013233 8013903 8015960 8028771 8062006
# @summary tests for "java.locale.providers" system property
# @compile -XDignore.symbol.file LocaleProviders.java
# @run shell/timeout=600 LocaleProviders.sh
@@ -182,7 +182,7 @@
if [ "${DEFLANG}" != "en" ] && [ "${DEFFMTLANG}" != "en" ]; then
PARAM2=en
PARAM3=US
-elif [ "${DEFLANG}" != "ja" ] && [ "${DEFFMTLANG}" != "ja" ]; then
+elif [ "${DEFLANG}" != "ja" ] && [ "${DEFFMTLANG}" != "ja" ]; then
PARAM2=ja
PARAM3=JP
else
@@ -200,6 +200,8 @@
PARAM3=US
SPICLASSES=
runTest
+PREFLIST=SPI,COMPAT
+runTest
# testing the order, variaton #1. This assumes en_GB DateFormat data are available both in JRE & CLDR
METHODNAME=adapterTest
@@ -209,6 +211,8 @@
PARAM3=GB
SPICLASSES=
runTest
+PREFLIST=CLDR,COMPAT
+runTest
# testing the order, variaton #2. This assumes en_GB DateFormat data are available both in JRE & CLDR
METHODNAME=adapterTest
@@ -218,6 +222,8 @@
PARAM3=GB
SPICLASSES=
runTest
+PREFLIST=COMPAT,CLDR
+runTest
# testing the order, variaton #3 for non-existent locale in JRE assuming "haw" is not in JRE.
METHODNAME=adapterTest
@@ -227,6 +233,8 @@
PARAM3=
SPICLASSES=
runTest
+PREFLIST=COMPAT,CLDR
+runTest
# testing the order, variaton #4 for the bug 7196799. CLDR's "zh" data should be used in "zh_CN"
METHODNAME=adapterTest
@@ -275,6 +283,8 @@
PARAM3=
SPICLASSES=${SPIDIR}
runTest
+PREFLIST=COMPAT
+runTest
# testing 8000615 fix.
METHODNAME=tzNameTest
@@ -284,6 +294,8 @@
PARAM3=
SPICLASSES=${SPIDIR}
runTest
+PREFLIST=COMPAT
+runTest
# testing 8001440 fix.
METHODNAME=bug8001440Test
@@ -314,6 +326,8 @@
PARAM3=
SPICLASSES=${SPIDIR}
runTest
+PREFLIST=COMPAT,SPI
+runTest
# testing 8013903 fix. (Windows only)
METHODNAME=bug8013903Test
@@ -323,12 +337,9 @@
PARAM3=
SPICLASSES=
runTest
-METHODNAME=bug8013903Test
PREFLIST=HOST
-PARAM1=
-PARAM2=
-PARAM3=
-SPICLASSES=
+runTest
+PREFLIST=HOST,COMPAT
runTest
# testing 8027289 fix, if the platform format default is zh_CN
@@ -342,12 +353,10 @@
PARAM3=
SPICLASSES=
runTest
- METHODNAME=bug8027289Test
+ PREFLIST=COMPAT,HOST
+ runTest
PREFLIST=HOST
PARAM1=00A5
- PARAM2=
- PARAM3=
- SPICLASSES=
runTest
fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/bmp/BMPPixelSpacingTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7182758
+ * @summary Test verifies whether we are getting correct Horizontal
+ * & Vertical Physical pixel spacing for active BMP image
+ * through stored metadata or not.
+ * @run main BMPPixelSpacingTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class BMPPixelSpacingTest {
+
+ public static void main(String[] args) throws Exception {
+ // Header contaning X & Y pixels-per-meter more than value 1
+ byte[] bmpHeaderData = { (byte) 0x42, (byte) 0x4d, (byte) 0x7e,
+ (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x3e, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x28, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff };
+
+ ImageInputStream imageInput = ImageIO.
+ createImageInputStream(new ByteArrayInputStream(bmpHeaderData));
+
+ for (Iterator<ImageReader> it = ImageIO.getImageReaders(imageInput);
+ it.hasNext(); ) {
+ ImageReader reader = it.next();
+ reader.setInput(imageInput);
+ IIOMetadata metadata = reader.getImageMetadata(0);
+
+ Node rootNode = metadata.getAsTree("javax_imageio_1.0");
+ NodeList nl = rootNode.getChildNodes();
+
+ //Parse until you get Dimension child node
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node node = nl.item(i);
+ if ((node.getNodeName()).equals("Dimension")) {
+ //get childnode list under Dimension node
+ NodeList cl = node.getChildNodes();
+ //Corresponding node indices under Dimension node
+ int horizontalNodeIndex = 1;
+ int verticalNodeIndex = 2;
+ Node horizontalNode = cl.item(horizontalNodeIndex);
+ Node verticalNode = cl.item(verticalNodeIndex);
+
+ //get attributes for horizontal and vertical nodes
+ NamedNodeMap horizontalAttr = horizontalNode.
+ getAttributes();
+ NamedNodeMap verticalAttr = verticalNode.getAttributes();
+
+ //since they have only one attribute index is 0
+ int attributeIndex = 0;
+ Node horizontalValue = horizontalAttr.item(attributeIndex);
+ Node verticalValue = verticalAttr.item(attributeIndex);
+ float horizontalNodeValue = Float.
+ parseFloat((horizontalValue.getNodeValue()));
+ float verticalNodeValue = Float.
+ parseFloat((verticalValue.getNodeValue()));
+
+ float expectedHorizontalValue, expectedVerticalValue;
+ // in test metadata xPixelsPerMeter & yPixelsPerMeter is 2
+ expectedHorizontalValue = expectedVerticalValue =
+ 1000.0F / 2;
+ //expected and returned values should be same
+ if ((Float.compare(horizontalNodeValue,
+ expectedHorizontalValue) != 0) ||
+ (Float.compare(verticalNodeValue,
+ expectedVerticalValue) != 0)) {
+ throw new RuntimeException("Invalid pixel spacing");
+ }
+ }
+ }
+ }
+ }
+}
--- a/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -27,8 +27,7 @@
* @summary Test that having a security manager doesn't trigger a
* NotCompliantMBeanException
* @author Daniel Fuchs, Yves Joan
- * @modules java.desktop
- * java.management
+ * @modules java.management
* @run clean AnnotationSecurityTest Described UnDescribed DescribedMBean
* UnDescribedMBean SqeDescriptorKey DescribedMX DescribedMXBean
* @run build AnnotationSecurityTest Described UnDescribed DescribedMBean
@@ -40,13 +39,8 @@
import java.io.File;
import java.io.IOException;
-import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
-import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
-import java.lang.reflect.UndeclaredThrowableException;
-
-import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
/**
--- a/jdk/test/javax/management/Introspector/Described.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/Introspector/Described.java Wed Jul 05 20:59:18 2017 +0200
@@ -25,7 +25,7 @@
*
* Used by AnnotationSecurityTest.java
**/
-import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
/**
* An MBean used by AnnotationSecurityTest.java
@@ -37,7 +37,7 @@
public Described() {}
@SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR Described")
- @ConstructorProperties({"name", "unused"})
+ @ConstructorParameters({"name", "unused"})
public Described(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
@SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
this.name = name ;
--- a/jdk/test/javax/management/Introspector/DescribedMX.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/Introspector/DescribedMX.java Wed Jul 05 20:59:18 2017 +0200
@@ -25,7 +25,7 @@
*
* Used by AnnotationSecurityTest.java
**/
-import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
/**
* An MXBean used by AnnotationSecurityTest.java
@@ -37,7 +37,7 @@
public DescribedMX() {}
@SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR DescribedMX")
- @ConstructorProperties({"name", "unused"})
+ @ConstructorParameters({"name", "unused"})
public DescribedMX(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
@SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
this.name = name ;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,106 @@
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+
+/*
+ * @test
+ * @bug 7199353
+ * @summary Asserts that 'java.beans.ConstructorProperties' annotation is still
+ * recognized and properly handled for custom types mapped to open types.
+ * Also, makes sure that if the same constructor is annotated by both
+ * j.b.ConstructorProperties and j.m.ConstructorProperties annotations
+ * only j.m.ConstructorProperties annotation is considered.
+ * @author Jaroslav Bachorik
+ * @modules java.management
+ * java.desktop
+ * @run main LegacyConstructorPropertiesTest
+ */
+
+public class LegacyConstructorPropertiesTest {
+ public static class CustomType {
+ private String name;
+ private int value;
+ @ConstructorProperties({"name", "value"})
+ public CustomType(String name, int value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ // if @java.beans.ConstructorProperties would be used
+ // the introspector would choke on this
+ @ConstructorProperties("noname")
+ @ConstructorParameters("name")
+ public CustomType(String name) {
+ this.name = name;
+ this.value = -1;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+ }
+
+ public static interface CustomMXBean {
+ public CustomType getProp();
+ public void setProp(CustomType prop);
+ }
+
+ public static final class Custom implements CustomMXBean {
+ private CustomType prop;
+
+ @Override
+ public CustomType getProp() {
+ return prop;
+ }
+
+ @Override
+ public void setProp(CustomType prop) {
+ this.prop = prop;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ CustomMXBean mbean = new Custom();
+
+ mbs.registerMBean(mbean, ObjectName.getInstance("test:type=Custom"));
+ }
+}
--- a/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -26,15 +26,13 @@
* @bug 6175517 6278707
* @summary Test that ambiguous ConstructorProperties annotations are detected.
* @author Eamonn McManus
- * @modules java.desktop
- * java.management
+ * @modules java.management
* @run clean AmbiguousConstructorTest
* @run build AmbiguousConstructorTest
* @run main AmbiguousConstructorTest
*/
-import java.beans.ConstructorProperties;
-import java.io.InvalidObjectException;
+import javax.management.ConstructorParameters;
import javax.management.*;
public class AmbiguousConstructorTest {
@@ -76,13 +74,13 @@
public int getC() {return 0;}
public long getD() {return 0;}
- @ConstructorProperties({"a", "b"})
+ @ConstructorParameters({"a", "b"})
public Unambiguous(byte a, short b) {}
- @ConstructorProperties({"b", "c"})
+ @ConstructorParameters({"b", "c"})
public Unambiguous(short b, int c) {}
- @ConstructorProperties({"a", "b", "c"})
+ @ConstructorParameters({"a", "b", "c"})
public Unambiguous(byte a, short b, int c) {}
}
@@ -92,13 +90,13 @@
public int getC() {return 0;}
public long getD() {return 0;}
- @ConstructorProperties({"a", "b"})
+ @ConstructorParameters({"a", "b"})
public Ambiguous(byte a, short b) {}
- @ConstructorProperties({"b", "c"})
+ @ConstructorParameters({"b", "c"})
public Ambiguous(short b, int c) {}
- @ConstructorProperties({"a", "b", "c", "d"})
+ @ConstructorParameters({"a", "b", "c", "d"})
public Ambiguous(byte a, short b, int c, long d) {}
}
--- a/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -26,11 +26,10 @@
* @bug 6713777
* @summary Test that exception messages include all relevant information
* @author Eamonn McManus
- * @modules java.desktop
- * java.management
+ * @modules java.management
*/
-import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -131,7 +130,7 @@
}
public static class CaseProb {
- @ConstructorProperties({"urlPath"})
+ @ConstructorParameters({"urlPath"})
public CaseProb(String urlPath) {}
public String getURLPath() {return null;}
--- a/jdk/test/javax/management/mxbean/LeakTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/LeakTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -25,8 +25,7 @@
* @bug 6482247
* @summary Test that creating MXBeans does not introduce memory leaks.
* @author Eamonn McManus
- * @modules java.desktop
- * java.management
+ * @modules java.management
* @run build LeakTest RandomMXBeanTest MerlinMXBean TigerMXBean
* @run main LeakTest
*/
--- a/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -27,8 +27,7 @@
* @summary General MXBean test.
* @author Eamonn McManus
* @author Jaroslav Bachorik
- * @modules java.desktop
- * java.management
+ * @modules java.management
* @run clean MXBeanTest MerlinMXBean TigerMXBean
* @run build MXBeanTest MerlinMXBean TigerMXBean
* @run main MXBeanTest
--- a/jdk/test/javax/management/mxbean/PropertyNamesTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/PropertyNamesTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -26,14 +26,13 @@
* @bug 6175517
* @summary Test the PropertyNames annotation with MXBeans
* @author Eamonn McManus
- * @modules java.desktop
- * java.management
+ * @modules java.management
* @run clean PropertyNamesTest
* @run build PropertyNamesTest
* @run main PropertyNamesTest
*/
-import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
import java.util.Collections;
import java.util.List;
import javax.management.JMX;
@@ -95,7 +94,7 @@
}
public static class Point {
- @ConstructorProperties({"x", "y"})
+ @ConstructorParameters({"x", "y"})
public Point(int x, int y) {
this.x = x;
this.y = y;
@@ -123,17 +122,17 @@
}
public static class Evolve {
- @ConstructorProperties({"oldInt"})
+ @ConstructorParameters({"oldInt"})
public Evolve(int oldInt) {
this(oldInt, "defaultString");
}
- @ConstructorProperties({"oldInt", "newString"})
+ @ConstructorParameters({"oldInt", "newString"})
public Evolve(int oldInt, String newString) {
this(oldInt, newString, Collections.<String>emptyList());
}
- @ConstructorProperties({"oldInt", "newString", "newerList"})
+ @ConstructorParameters({"oldInt", "newString", "newerList"})
public Evolve(int oldInt, String newString, List<String> newerList) {
this.oldInt = oldInt;
this.newString = newString;
--- a/jdk/test/javax/management/mxbean/TigerMXBean.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/javax/management/mxbean/TigerMXBean.java Wed Jul 05 20:59:18 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,7 +21,7 @@
* questions.
*/
-import java.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -42,7 +42,7 @@
public interface TigerMXBean {
class Point {
- @ConstructorProperties({"x", "y"})
+ @ConstructorParameters({"x", "y"})
public Point(double x, double y) {
this.x = x;
this.y = y;
--- a/jdk/test/jdk/internal/jimage/JImageReadTest.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/jdk/internal/jimage/JImageReadTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -22,7 +22,9 @@
*/
/*
+ * @test
* @modules java.base/jdk.internal.jimage
+ * @run testng JImageReadTest
* @summary Unit test for libjimage JIMAGE_Open/Read/Close
*/
@@ -57,8 +59,7 @@
{"java.base", "java/lang/String.class"},
{"java.base", "java/lang/Object.class"},
{"java.base", "sun/reflect/generics/tree/TypeArgument.class"},
- {"jdk.jdeps", "com/sun/tools/javap/StackMapWriter$StackMapBuilder.class"},
- {"jdk.hotspot.agent", "sa.properties"},
+ {"java.base", "sun/net/www/content-types.properties"},
{"java.logging", "java/util/logging/Logger.class"},
{"java.base", "java/NOSUCHCLASS/yyy.class"}, // non-existent
{"NOSUCHMODULE", "java/lang/Class.class"}, // non-existent
@@ -165,8 +166,10 @@
int count = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle,
names);
System.out.printf(" count: %d, a class: %s\n", count, names[0]);
- Assert.assertTrue(max > 31000,
- "missing entries, should be more than 31000, reported: " + count);
+ int minEntryCount = 16000;
+ Assert.assertTrue(max > minEntryCount,
+ "missing entries, should be more than " + minEntryCount +
+ ", reported: " + count);
Assert.assertTrue(count == max,
"unexpected count of entries, count: " + count
+ ", max: " + max);
@@ -310,6 +313,7 @@
static boolean isMetaName(String name) {
return name.startsWith("/modules")
|| name.startsWith("/packages")
+ || name.startsWith("META-INF/services")
|| name.equals("bootmodules.jdata");
}
@@ -362,6 +366,24 @@
System.out.printf(" %s: %d names%n", fname, names.length);
}
+ @Test
+ static void test5_nameTooLong() throws IOException {
+ long[] size = new long[1];
+ String moduleName = "FictiousModuleName";
+ String className = String.format("A%09999d", 1);
+
+ long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
+ Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+
+ long locationHandle =
+ ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle,
+ moduleName, "9.0", className, size);
+
+ Assert.assertEquals(0, locationHandle, "Too long name should have failed");
+
+ ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+ }
+
// main method to run standalone from jtreg
@Test(enabled=false)
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java Thu Nov 05 13:43:17 2015 -0800
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java Wed Jul 05 20:59:18 2017 +0200
@@ -539,6 +539,7 @@
osMap.put("Linux-amd64-64", new String[]{
"/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/",
"/usr/lib64/"});
+ osMap.put("Linux-ppc64-64", new String[]{"/usr/lib64/"});
osMap.put("Windows-x86-32", new String[]{
PKCS11_BASE + "/nss/lib/windows-i586/".replace('/', SEP)});
osMap.put("Windows-amd64-64", new String[]{
--- a/make/Images.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/Images.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -40,7 +40,7 @@
MAIN_MODULES += java.se java.smartcardio jdk.httpserver jdk.sctp \
jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \
jdk.accessibility jdk.internal.le jdk.scripting.nashorn.shell \
- jdk.vm.ci
+ jdk.vm.ci jdk.management
# providers
PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk.localedata \
@@ -435,7 +435,7 @@
# directories will always trigger the rule for recompile since
# _the.list_of_packages files are touched.
ifneq ($(findstring images, $(MAKECMDGOALS)), )
- $(JDK_IMAGE_DIR)/demo/%: $(SUPPORT_OUTPUTDIR)/demo/image/%
+ $(JDK_IMAGE_DIR)/demo/%: $(SUPPORT_OUTPUTDIR)/demos/image/%
if [ ! -d "$@" ]; then \
$(ECHO) $(LOG_INFO) Copying '$(patsubst $(OUTPUT_ROOT)/%,%,$@)'; \
$(MKDIR) -p $(@D); \
@@ -443,9 +443,9 @@
fi
# Find all files including directories
- JDK_DEMO_TARGETS := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demo/image), \
- $(patsubst $(SUPPORT_OUTPUTDIR)/demo/image/%, $(JDK_IMAGE_DIR)/demo/%, \
- $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demo/image \
+ JDK_DEMO_TARGETS := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demos/image), \
+ $(patsubst $(SUPPORT_OUTPUTDIR)/demos/image/%, $(JDK_IMAGE_DIR)/demo/%, \
+ $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \
! \( -name "_the*" -o -name "javac_state" \) )))
JDK_TARGETS += $(JDK_DEMO_TARGETS)
--- a/make/JrtfsJar.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/JrtfsJar.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -27,7 +27,7 @@
include $(SPEC)
include MakeBase.gmk
-include JavaCompilation.gmk
+include JarArchive.gmk
include TextFileProcessing.gmk
# This rule will be depended on due to the MANIFEST line
@@ -39,9 +39,10 @@
@@COMPANY_NAME@@ => $(COMPANY_NAME) , \
))
-$(eval $(call SetupArchive,JRTFS_JAR, , \
+$(eval $(call SetupJarArchive, JRTFS_JAR, \
SRCS := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \
JAR := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar, \
- MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf))
+ MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+))
all: $(JRTFS_JAR)
--- a/make/Main.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/Main.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -452,6 +452,8 @@
test-make: clean-test-make
+ build-test-lib: java
+
build-test-hotspot-jtreg-native: buildtools-jdk
build-test-jdk-jtreg-native: buildtools-jdk
@@ -558,6 +560,8 @@
CLEAN_DIRS += hotspot jdk bootcycle-build test buildtools support \
images make-support test-make bundles
CLEAN_DIR_TARGETS := $(addprefix clean-, $(CLEAN_DIRS))
+CLEAN_SUPPORT_DIRS += demos
+CLEAN_SUPPORT_DIR_TARGETS := $(addprefix clean-, $(CLEAN_SUPPORT_DIRS))
CLEAN_TESTS += hotspot-jtreg-native jdk-jtreg-native lib
CLEAN_TEST_TARGETS += $(addprefix clean-test-, $(CLEAN_TESTS))
CLEAN_PHASES := gensrc java native include docs
@@ -575,6 +579,9 @@
$(CLEAN_DIR_TARGETS):
$(call CleanDir,$(patsubst clean-%, %, $@))
+$(CLEAN_SUPPORT_DIR_TARGETS):
+ $(call CleanSupportDir,$(patsubst clean-%, %, $@))
+
$(CLEAN_TEST_TARGETS):
$(call CleanTest,$(patsubst clean-test-%, %, $@))
@@ -608,8 +615,9 @@
)
$(ECHO) Cleaned everything, you will have to re-run configure.
-ALL_TARGETS += clean dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_TEST_TARGETS) \
- $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) $(CLEAN_MODULE_PHASE_TARGETS)
+ALL_TARGETS += clean dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_SUPPORT_DIR_TARGETS) \
+ $(CLEAN_TEST_TARGETS) $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) \
+ $(CLEAN_MODULE_PHASE_TARGETS)
################################################################################
# Declare *-only targets for each normal target
--- a/make/MainSupport.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/MainSupport.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -46,6 +46,13 @@
@$(PRINTF) " done\n"
endef
+define CleanSupportDir
+ @$(PRINTF) "Cleaning $(strip $1) build artifacts ..."
+ @$(PRINTF) "\n" $(LOG_DEBUG)
+ $(RM) -r $(SUPPORT_OUTPUTDIR)/$(strip $1)
+ @$(PRINTF) " done\n"
+endef
+
define CleanTest
@$(PRINTF) "Cleaning test $(strip $1) ..."
@$(PRINTF) "\n" $(LOG_DEBUG)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/common/JarArchive.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,276 @@
+#
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. 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.
+#
+
+ifndef _JAR_ARCHIVE_GMK
+_JAR_ARCHIVE_GMK := 1
+
+ifeq (,$(_MAKEBASE_GMK))
+ $(error You must include MakeBase.gmk prior to including JarArchive.gmk)
+endif
+
+FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST
+
+# Setup make rules for creating a jar archive.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+# DEPENDENCIES:=List of dependencies for the jar target. If left empty,
+# dependencies are calculated automatically from the source files found.
+# For this to work, the source files must exist when the makefile is
+# parsed.
+# SRCS:=List of directories in where to find files to add to archive
+# SUFFIXES:=File suffixes to include in jar
+# INCLUDES:=List of directories/packages in SRCS that should be included
+# EXCLUDES:=List of directories/packages in SRCS that should be excluded
+# EXCLUDE_FILES:=List of files in SRCS that should be excluded
+# EXTRA_FILES:=List of files in SRCS that should be included regardless of suffix match.
+# JAR:=Jar file to create
+# MANIFEST:=Optional manifest file template.
+# JARMAIN:=Optional main class to add to manifest
+# JARINDEX:=true means generate the index in the jar file.
+# SKIP_METAINF:=Set to prevent contents of an META-INF directory to be automatically
+# added to the archive.
+# EXTRA_MANIFEST_ATTR:=Extra attribute to add to manifest.
+# CHECK_COMPRESS_JAR Check the COMPRESS_JAR variable
+SetupJarArchive = $(NamedParamsMacroTemplate)
+define SetupJarArchiveBody
+
+ $1_JARMAIN:=$(strip $$($1_JARMAIN))
+ $1_JARNAME:=$$(notdir $$($1_JAR))
+ $1_MANIFEST_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_manifest
+ $1_DELETESS_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletess
+ $1_DELETES_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletes
+ $1_BIN:=$$(dir $$($1_JAR))
+
+ ifeq (,$$($1_SUFFIXES))
+ # No suffix was set, default to classes.
+ $1_SUFFIXES:=.class
+ endif
+ # Convert suffixes to a find expression
+ $1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
+ # On windows, a lot of includes/excludes risk making the command line too long, so
+ # writing the grep patterns to files.
+ # Grep returns 1 if nothing is matched. Do not fail the build for this.
+ ifneq (,$$($1_INCLUDES))
+ $1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
+ $$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
+ # If there are a lot of include patterns, output to file to shorten command lines
+ ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
+ $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
+ || test "$$$$?" = "1" )
+ else
+ $1_GREP_INCLUDE_OUTPUT = \
+ $$(eval $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS, \
+ $$($1_BIN)/_the.$$($1_JARNAME)_include))
+ $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
+ || test "$$$$?" = "1" )
+ endif
+ endif
+ ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
+ $1_GREP_EXCLUDE_PATTERNS:=$$(call EscapeDollar, \
+ $$(foreach src,$$($1_SRCS),$$(addprefix $$(src)/, \
+ $$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
+ # If there are a lot of include patterns, output to file to shorten command lines
+ ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
+ $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
+ || test "$$$$?" = "1" )
+ else
+ $1_GREP_EXCLUDE_OUTPUT = \
+ $$(eval $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS, \
+ $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
+ $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
+ || test "$$$$?" = "1" )
+ endif
+ endif
+
+ # Check if this jar needs to have its index generated.
+ ifneq (,$$($1_JARINDEX))
+ $1_JARINDEX = (cd $$(dir $$@) && $(JAR) -i $$(notdir $$@))
+ else
+ $1_JARINDEX = true
+ endif
+ # When this macro is run in the same makefile as the java compilation, dependencies are
+ # transfered in make variables. When the macro is run in a different makefile than the
+ # java compilation, the dependencies need to be found in the filesystem.
+ $1_ORIG_DEPS := $$($1_DEPENDENCIES)
+ ifeq ($$($1_DEPENDENCIES), )
+ # Add all source roots to the find cache since we are likely going to run find
+ # on these more than once. The cache will only be updated if necessary.
+ $$(eval $$(call FillCacheFind, $$($1_FIND_LIST)))
+ $1_DEPENDENCIES:=$$(filter $$(addprefix %,$$($1_SUFFIXES)), \
+ $$(call CacheFind,$$($1_SRCS)))
+ ifneq (,$$($1_GREP_INCLUDE_PATTERNS))
+ $1_DEPENDENCIES:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
+ endif
+ ifneq (,$$($1_GREP_EXCLUDE_PATTERNS))
+ $1_DEPENDENCIES:=$$(filter-out $$(addsuffix %,$$($1_GREP_EXCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
+ endif
+ # Look for EXTRA_FILES in all SRCS dirs and as absolute paths.
+ $1_DEPENDENCIES+=$$(wildcard $$(foreach src, $$($1_SRCS), \
+ $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES))
+ ifeq (,$$($1_SKIP_METAINF))
+ $1_DEPENDENCIES+=$$(call CacheFind,$$(wildcard $$(addsuffix /META-INF,$$($1_SRCS))))
+ endif
+ endif
+ # The dependency list should never be empty
+ ifeq ($$(strip $$($1_DEPENDENCIES)), )
+ $$(warning No dependencies found for $1)
+ endif
+
+ # Utility macros, to make the shell script receipt somewhat easier to decipher.
+
+ # Capture extra files is the same for both CAPTURE_CONTENTS and SCAPTURE_CONTENTS so
+ # only define it once to avoid duplication.
+ # The list of extra files might be long, so need to use ListPathsSafely to print
+ # them out to a separte file. Then process the contents of that file to rewrite
+ # into -C <dir> <file> lines.
+ # The EXTRA_FILES_RESOLVED varible must be set in the macro so that it's evaluated
+ # in the recipe when the files are guaranteed to exist.
+ $1_CAPTURE_EXTRA_FILES=\
+ $$(eval $1_EXTRA_FILES_RESOLVED:=$$(call DoubleDollar, \
+ $$(wildcard $$(foreach src, $$($1_SRCS), \
+ $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES)))) \
+ $$(if $$($1_EXTRA_FILES_RESOLVED), \
+ $$(eval $$(call ListPathsSafely,$1_EXTRA_FILES_RESOLVED, \
+ $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra)) \
+ $(SED) $$(foreach src,$$($1_SRCS), -e 's|$$(src)/|-C $$(src) |g') \
+ $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra \
+ >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE))
+
+ # The capture contents macro finds all files (matching the patterns, typically
+ # .class and .prp) that are newer than the jar-file, ie the new content to be put into the jar.
+ # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
+ $1_CAPTURE_CONTENTS=\
+ $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
+ $$(foreach src,$$($1_SRCS), \
+ $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) -a -newer $$@ $$($1_GREP_INCLUDES) \
+ $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
+ >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
+ $$($1_CAPTURE_EXTRA_FILES)
+
+ # The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
+ # Find returns non zero if the META-INF dir does not exist, ignore this.
+ ifeq (,$$($1_SKIP_METAINF))
+ $1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
+ ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
+ | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+ $$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
+ endif
+ # The capture deletes macro finds all deleted files and concatenates them. The resulting file
+ # tells us what to remove from the jar-file.
+ $1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ \
+ -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
+ # The update contents macro updates the jar file with the previously capture contents.
+ # Use 'wc -w' to see if the contents file is empty.
+ $1_UPDATE_CONTENTS=\
+ if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
+ $(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
+ $(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
+ fi $$(NEWLINE)
+ # The s-variants of the above macros are used when the jar is created from scratch.
+ # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
+ $1_SCAPTURE_CONTENTS=\
+ $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
+ $$(foreach src,$$($1_SRCS), \
+ $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) $$($1_GREP_INCLUDES) \
+ $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
+ >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
+ $$($1_CAPTURE_EXTRA_FILES)
+
+ # Find returns non zero if the META-INF dir does not exist, ignore this.
+ ifeq (,$$($1_SKIP_METAINF))
+ $1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
+ ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
+ | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+ $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
+ endif
+ $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
+
+ # Use a slightly shorter name for logging, but with enough path to identify this jar.
+ $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_JAR))
+
+ ifneq (,$$($1_CHECK_COMPRESS_JAR))
+ $1_JAR_CREATE_OPTIONS := c0fm
+ $1_JAR_UPDATE_OPTIONS := u0f
+ ifeq ($(COMPRESS_JARS), true)
+ $1_JAR_CREATE_OPTIONS := cfm
+ $1_JAR_UPDATE_OPTIONS := uf
+ endif
+ else
+ $1_JAR_CREATE_OPTIONS := cfm
+ $1_JAR_UPDATE_OPTIONS := uf
+ endif
+
+ # Include all variables of significance in the vardeps file
+ $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
+ $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
+ $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
+
+ # Here is the rule that creates/updates the jar file.
+ $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
+ $(MKDIR) -p $$($1_BIN)
+ $$($1_GREP_INCLUDE_OUTPUT)
+ $$($1_GREP_EXCLUDE_OUTPUT)
+ # If the vardeps file is part of the newer prereq list, it means that
+ # either the jar file does not exist, or we need to recreate it from
+ # from scratch anyway since a simple update will not catch all the
+ # potential changes.
+ $$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
+ $$(if $$($1_MANIFEST), \
+ $(SED) -e '$(DOLLAR)$(DOLLAR)a\' $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ , \
+ $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $$(if $$($1_JARMAIN), \
+ $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+ $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ $$($1_SCAPTURE_CONTENTS) \
+ $$($1_SCAPTURE_METAINF) \
+ $$($1_SUPDATE_CONTENTS) \
+ $$($1_JARINDEX) && true \
+ , \
+ $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+ $$($1_CAPTURE_CONTENTS) \
+ $$($1_CAPTURE_METAINF) \
+ $(RM) $$($1_DELETES_FILE) $$(NEWLINE) \
+ $$($1_CAPTURE_DELETES) \
+ $(CAT) $$($1_DELETES_FILE) > $$($1_DELETESS_FILE) $$(NEWLINE) \
+ if [ -s $$($1_DELETESS_FILE) ]; then \
+ $(ECHO) " deleting" `$(WC) -l $$($1_DELETESS_FILE) | $(AWK) '{ print $$$$1 }'` files && \
+ $(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
+ fi $$(NEWLINE) \
+ $$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
+ $$($1_JARINDEX) && true )
+
+ # Add jar to target list
+ $1 += $$($1_JAR)
+endef
+
+endif # _JAR_ARCHIVE_GMK
--- a/make/common/JavaCompilation.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/common/JavaCompilation.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -23,14 +23,6 @@
# questions.
#
-# This makefile is much simpler now that it can use the smart javac wrapper
-# for dependency tracking between java packages and incremental compiles.
-# It could be even more simple if we added support for incremental jar updates
-# directly from the smart javac wrapper.
-
-# Cleaning/copying properties here is not a good solution. The properties
-# should be cleaned/copied by a annotation processor in sjavac.
-
# When you read this source. Remember that $(sort ...) has the side effect
# of removing duplicates. It is actually this side effect that is
# desired whenever sort is used below!
@@ -42,11 +34,11 @@
$(error You must include MakeBase.gmk prior to including JavaCompilation.gmk)
endif
-# Java compilation needs SetupZipArchive if we're generating a source zip.
+# Java compilation needs SetupJarArchive and/or SetupZipArchive, if we're
+# generating a jar file or a source zip.
+include JarArchive.gmk
include ZipArchive.gmk
-FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST
-
# Setup make rules for defining a Java compiler, which is needed to compile
# Java code. This rule generates no output.
#
@@ -72,248 +64,6 @@
endif
endef
-# Setup make rules for creating a jar archive.
-#
-# Parameter 1 is the name of the rule. This name is used as variable prefix,
-# and the targets generated are listed in a variable by that name.
-#
-# Remaining parameters are named arguments. These include:
-# DEPENDENCIES:=List of dependencies for the jar target. If left empty,
-# dependencies are calculated automatically from the source files found.
-# For this to work, the source files must exist when the makefile is
-# parsed.
-# SRCS:=List of directories in where to find files to add to archive
-# SUFFIXES:=File suffixes to include in jar
-# INCLUDES:=List of directories/packages in SRCS that should be included
-# EXCLUDES:=List of directories/packages in SRCS that should be excluded
-# EXCLUDE_FILES:=List of files in SRCS that should be excluded
-# EXTRA_FILES:=List of files in SRCS that should be included regardless of suffix match.
-# JAR:=Jar file to create
-# MANIFEST:=Optional manifest file template.
-# JARMAIN:=Optional main class to add to manifest
-# JARINDEX:=true means generate the index in the jar file.
-# SKIP_METAINF:=Set to prevent contents of an META-INF directory to be automatically
-# added to the archive.
-# EXTRA_MANIFEST_ATTR:=Extra attribute to add to manifest.
-# CHECK_COMPRESS_JAR Check the COMPRESS_JAR variable
-SetupArchive = $(NamedParamsMacroTemplate)
-define SetupArchiveBody
-
- $1_JARMAIN:=$(strip $$($1_JARMAIN))
- $1_JARNAME:=$$(notdir $$($1_JAR))
- $1_MANIFEST_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_manifest
- $1_DELETESS_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletess
- $1_DELETES_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletes
- $1_BIN:=$$(dir $$($1_JAR))
-
- ifeq (,$$($1_SUFFIXES))
- # No suffix was set, default to classes.
- $1_SUFFIXES:=.class
- endif
- # Convert suffixes to a find expression
- $1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
- # On windows, a lot of includes/excludes risk making the command line too long, so
- # writing the grep patterns to files.
- # Grep returns 1 if nothing is matched. Do not fail the build for this.
- ifneq (,$$($1_INCLUDES))
- $1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
- $$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
- # If there are a lot of include patterns, output to file to shorten command lines
- ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
- $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
- || test "$$$$?" = "1" )
- else
- $1_GREP_INCLUDE_OUTPUT = \
- $$(eval $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS, \
- $$($1_BIN)/_the.$$($1_JARNAME)_include))
- $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
- || test "$$$$?" = "1" )
- endif
- endif
- ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
- $1_GREP_EXCLUDE_PATTERNS:=$$(call EscapeDollar, \
- $$(foreach src,$$($1_SRCS),$$(addprefix $$(src)/, \
- $$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
- # If there are a lot of include patterns, output to file to shorten command lines
- ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
- $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
- || test "$$$$?" = "1" )
- else
- $1_GREP_EXCLUDE_OUTPUT = \
- $$(eval $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS, \
- $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
- $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
- || test "$$$$?" = "1" )
- endif
- endif
-
- # Check if this jar needs to have its index generated.
- ifneq (,$$($1_JARINDEX))
- $1_JARINDEX = (cd $$(dir $$@) && $(JAR) -i $$(notdir $$@))
- else
- $1_JARINDEX = true
- endif
- # When this macro is run in the same makefile as the java compilation, dependencies are
- # transfered in make variables. When the macro is run in a different makefile than the
- # java compilation, the dependencies need to be found in the filesystem.
- $1_ORIG_DEPS := $$($1_DEPENDENCIES)
- ifeq ($$($1_DEPENDENCIES), )
- # Add all source roots to the find cache since we are likely going to run find
- # on these more than once. The cache will only be updated if necessary.
- $$(eval $$(call FillCacheFind, $$($1_FIND_LIST)))
- $1_DEPENDENCIES:=$$(filter $$(addprefix %,$$($1_SUFFIXES)), \
- $$(call CacheFind,$$($1_SRCS)))
- ifneq (,$$($1_GREP_INCLUDE_PATTERNS))
- $1_DEPENDENCIES:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
- endif
- ifneq (,$$($1_GREP_EXCLUDE_PATTERNS))
- $1_DEPENDENCIES:=$$(filter-out $$(addsuffix %,$$($1_GREP_EXCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
- endif
- # Look for EXTRA_FILES in all SRCS dirs and as absolute paths.
- $1_DEPENDENCIES+=$$(wildcard $$(foreach src, $$($1_SRCS), \
- $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES))
- ifeq (,$$($1_SKIP_METAINF))
- $1_DEPENDENCIES+=$$(call CacheFind,$$(wildcard $$(addsuffix /META-INF,$$($1_SRCS))))
- endif
- endif
- # The dependency list should never be empty
- ifeq ($$(strip $$($1_DEPENDENCIES)), )
- $$(warning No dependencies found for $1)
- endif
-
- # Utility macros, to make the shell script receipt somewhat easier to decipher.
-
- # Capture extra files is the same for both CAPTURE_CONTENTS and SCAPTURE_CONTENTS so
- # only define it once to avoid duplication.
- # The list of extra files might be long, so need to use ListPathsSafely to print
- # them out to a separte file. Then process the contents of that file to rewrite
- # into -C <dir> <file> lines.
- # The EXTRA_FILES_RESOLVED varible must be set in the macro so that it's evaluated
- # in the recipe when the files are guaranteed to exist.
- $1_CAPTURE_EXTRA_FILES=\
- $$(eval $1_EXTRA_FILES_RESOLVED:=$$(call DoubleDollar, \
- $$(wildcard $$(foreach src, $$($1_SRCS), \
- $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES)))) \
- $$(if $$($1_EXTRA_FILES_RESOLVED), \
- $$(eval $$(call ListPathsSafely,$1_EXTRA_FILES_RESOLVED, \
- $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra)) \
- $(SED) $$(foreach src,$$($1_SRCS), -e 's|$$(src)/|-C $$(src) |g') \
- $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra \
- >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE))
-
- # The capture contents macro finds all files (matching the patterns, typically
- # .class and .prp) that are newer than the jar-file, ie the new content to be put into the jar.
- # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
- $1_CAPTURE_CONTENTS=\
- $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
- $$(foreach src,$$($1_SRCS), \
- $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) -a -newer $$@ $$($1_GREP_INCLUDES) \
- $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
- >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
- $$($1_CAPTURE_EXTRA_FILES)
-
- # The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
- # Find returns non zero if the META-INF dir does not exist, ignore this.
- ifeq (,$$($1_SKIP_METAINF))
- $1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
- ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
- | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
- $$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
- endif
- # The capture deletes macro finds all deleted files and concatenates them. The resulting file
- # tells us what to remove from the jar-file.
- $1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ \
- -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
- # The update contents macro updates the jar file with the previously capture contents.
- # Use 'wc -w' to see if the contents file is empty.
- $1_UPDATE_CONTENTS=\
- if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
- $(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
- $(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
- fi $$(NEWLINE)
- # The s-variants of the above macros are used when the jar is created from scratch.
- # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
- $1_SCAPTURE_CONTENTS=\
- $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
- $$(foreach src,$$($1_SRCS), \
- $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) $$($1_GREP_INCLUDES) \
- $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
- >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
- $$($1_CAPTURE_EXTRA_FILES)
-
- # Find returns non zero if the META-INF dir does not exist, ignore this.
- ifeq (,$$($1_SKIP_METAINF))
- $1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
- ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
- | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
- $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
- endif
- $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
-
- # Use a slightly shorter name for logging, but with enough path to identify this jar.
- $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_JAR))
-
- ifneq (,$$($1_CHECK_COMPRESS_JAR))
- $1_JAR_CREATE_OPTIONS := c0fm
- $1_JAR_UPDATE_OPTIONS := u0f
- ifeq ($(COMPRESS_JARS), true)
- $1_JAR_CREATE_OPTIONS := cfm
- $1_JAR_UPDATE_OPTIONS := uf
- endif
- else
- $1_JAR_CREATE_OPTIONS := cfm
- $1_JAR_UPDATE_OPTIONS := uf
- endif
-
- # Include all variables of significance in the vardeps file
- $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
- $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
- $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
- $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
-
- # Here is the rule that creates/updates the jar file.
- $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
- $(MKDIR) -p $$($1_BIN)
- $$($1_GREP_INCLUDE_OUTPUT)
- $$($1_GREP_EXCLUDE_OUTPUT)
- # If the vardeps file is part of the newer prereq list, it means that
- # either the jar file does not exist, or we need to recreate it from
- # from scratch anyway since a simple update will not catch all the
- # potential changes.
- $$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
- $$(if $$($1_MANIFEST), \
- $(SED) -e '$(DOLLAR)$(DOLLAR)a\' $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
- , \
- $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
- $$(if $$($1_JARMAIN), \
- $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
- $$(if $$($1_EXTRA_MANIFEST_ATTR), \
- $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
- $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
- $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
- $$($1_SCAPTURE_CONTENTS) \
- $$($1_SCAPTURE_METAINF) \
- $$($1_SUPDATE_CONTENTS) \
- $$($1_JARINDEX) && true \
- , \
- $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
- $$($1_CAPTURE_CONTENTS) \
- $$($1_CAPTURE_METAINF) \
- $(RM) $$($1_DELETES_FILE) $$(NEWLINE) \
- $$($1_CAPTURE_DELETES) \
- $(CAT) $$($1_DELETES_FILE) > $$($1_DELETESS_FILE) $$(NEWLINE) \
- if [ -s $$($1_DELETESS_FILE) ]; then \
- $(ECHO) " deleting" `$(WC) -l $$($1_DELETESS_FILE) | $(AWK) '{ print $$$$1 }'` files && \
- $(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
- fi $$(NEWLINE) \
- $$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
- $$($1_JARINDEX) && true )
-
- # Add jar to target list
- $1 += $$($1_JAR)
-endef
-
-
define add_file_to_copy
# param 1 = BUILD_MYPACKAGE
# parma 2 = The source file to copy.
@@ -335,7 +85,6 @@
endif
endef
-
# This macro is used only for properties files that are to be
# copied over to the classes directory in cleaned form:
# Previously this was inconsistently done in different repositories.
@@ -442,17 +191,16 @@
$1_SERVER_JVM := $$($$($1_SETUP)_SERVER_JVM)
$1_DISABLE_SJAVAC := $$($$($1_SETUP)_DISABLE_SJAVAC)
- # Handle addons and overrides.
- $1_SRC:=$$(call ADD_SRCS,$$($1_SRC))
# Make sure the dirs exist.
$$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupJavaCompilation $1 contains missing directory >$$d<)))
$$(call MakeDir,$$($1_BIN))
# Add all source roots to the find cache since we are likely going to run find
# on these more than once. The cache will only be updated if necessary.
$$(eval $$(call FillCacheFind,$$($1_SRC)))
- # Find all files in the source trees. Preserve order of source roots for overrides to
- # work correctly. CacheFind does not preserve order so need to call it for each root.
- $1_ALL_SRCS += $$(filter-out $(OVR_SRCS),$$(foreach s,$$($1_SRC),$$(call CacheFind,$$(s))))
+ # Find all files in the source trees. Preserve order of source roots so that
+ # the first version in case of multiple instances of the same file is selected.
+ # CacheFind does not preserve order so need to call it for each root.
+ $1_ALL_SRCS += $$(foreach s, $$($1_SRC), $$(call CacheFind, $$(s)))
# Extract the java files.
ifneq ($$($1_EXCLUDE_FILES),)
$1_EXCLUDE_FILES_PATTERN:=$$(addprefix %,$$($1_EXCLUDE_FILES))
@@ -665,7 +413,7 @@
$1_SUFFIXES:=.class $$($1_CLEAN) $$($1_COPY)
endif
- $$(eval $$(call SetupArchive,ARCHIVE_$1, \
+ $$(eval $$(call SetupJarArchive, ARCHIVE_$1, \
DEPENDENCIES:=$$($1), \
SRCS:=$$($1_BIN), \
SUFFIXES:=$$($1_SUFFIXES), \
@@ -678,7 +426,8 @@
EXTRA_MANIFEST_ATTR:=$$($1_EXTRA_MANIFEST_ATTR), \
JARINDEX:=$$($1_JARINDEX), \
HEADERS:=$$($1_HEADERS), \
- SETUP:=$$($1_SETUP)))
+ SETUP:=$$($1_SETUP), \
+ ))
# Add jar to target list
$1 += $$($1_JAR)
@@ -686,7 +435,7 @@
# Check if a srczip was specified, then setup the rules for the srczip.
ifneq (,$$($1_SRCZIP))
- $$(eval $$(call SetupZipArchive,ARCHIVE_$1, \
+ $$(eval $$(call SetupZipArchive, ZIP_ARCHIVE_$1, \
SRC:=$$($1_SRC), \
ZIP:=$$($1_SRCZIP), \
INCLUDES:=$$($1_INCLUDES), \
--- a/make/devkit/createMacosxDevkit.sh Thu Nov 05 13:43:17 2015 -0800
+++ b/make/devkit/createMacosxDevkit.sh Wed Jul 05 20:59:18 2017 +0200
@@ -29,7 +29,7 @@
# and the aux tools need to be available.
# erik.joelsson@oracle.com
-USAGE="$0 <Xcode.dmg> <XQuartz.dmg> [<auxtools.dmg>]"
+USAGE="$0 <Xcode.dmg> <XQuartz.dmg> <gnu make binary> [<auxtools.dmg>]"
if [ "$1" = "" ] || [ "$2" = "" ]; then
echo $USAGE
@@ -38,7 +38,8 @@
XCODE_DMG="$1"
XQUARTZ_DMG="$2"
-AUXTOOLS_DMG="$3"
+GNU_MAKE="$3"
+AUXTOOLS_DMG="$4"
SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
@@ -52,8 +53,13 @@
# Find the version of Xcode
XCODE_VERSION="$(/Volumes/Xcode/Xcode.app/Contents/Developer/usr/bin/xcodebuild -version \
| awk '/Xcode/ { print $2 }' )"
+SDK_VERSION="MacOSX10.9"
+if [ ! -e "/Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/${SDK_VERSION}.sdk" ]; then
+ echo "Expected SDK version not found: ${SDK_VERSION}"
+ exit 1
+fi
-DEVKIT_ROOT="${BUILD_DIR}/Xcode${XCODE_VERSION}-devkit"
+DEVKIT_ROOT="${BUILD_DIR}/Xcode${XCODE_VERSION}-${SDK_VERSION}"
DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz"
echo "Xcode version: $XCODE_VERSION"
@@ -71,10 +77,9 @@
rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/iPhone*
rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Documentation
rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/usr/share/man
-if [ -e $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk ]; then
- rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk
- rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/share/man
-fi
+( cd $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs \
+ && rm -rf `ls | grep -v ${SDK_VERSION}` )
+rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/${SDK_VERSION}.sdk/usr/share/man
hdiutil detach /Volumes/Xcode
@@ -91,20 +96,27 @@
rm -rf /tmp/x11
mkdir /tmp/x11
cd /tmp/x11
-cat /tmp/XQuartz-*/x11.pkg/Payload | gunzip -dc |cpio -i
+cat /tmp/XQuartz/x11.pkg/Payload | gunzip -dc | cpio -i
+mkdir -p $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
+mkdir -p $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/lib/
cp -RH opt/X11/include/freetype2 \
- $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/
+ $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
cp -RH opt/X11/include/ft2build.h \
- $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/
+ $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
cp -RH opt/X11/lib/libfreetype.* \
- $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/
+ $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/lib/
cd -
hdiutil detach /Volumes/XQuartz-*
################################################################################
+# Copy gnu make
+mkdir -p $DEVKIT_ROOT/bin
+cp $GNU_MAKE $DEVKIT_ROOT/bin
+
+################################################################################
# Optionally copy PackageMaker
if [ -e "$AUXTOOLS_DMG" ]; then
@@ -129,10 +141,12 @@
echo "Generating devkit.info..."
rm -f $DEVKIT_ROOT/devkit.info
echo-info "# This file describes to configure how to interpret the contents of this devkit"
+echo-info "# The parameters used to create this devkit were:"
+echo-info "# $*"
echo-info "DEVKIT_NAME=\"Xcode $XCODE_VERSION (devkit)\""
echo-info "DEVKIT_TOOLCHAIN_PATH=\"\$DEVKIT_ROOT/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:\$DEVKIT_ROOT/Xcode.app/Contents/Developer/usr/bin\""
echo-info "DEVKIT_SYSROOT=\"\$DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk\""
-echo-info "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/PackageMaker.app/Contents/MacOS:\$DEVKIT_TOOLCHAIN_PATH\""
+echo-info "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/bin:\$DEVKIT_ROOT/PackageMaker.app/Contents/MacOS:\$DEVKIT_TOOLCHAIN_PATH\""
################################################################################
# Copy this script
--- a/make/jprt.properties Thu Nov 05 13:43:17 2015 -0800
+++ b/make/jprt.properties Wed Jul 05 20:59:18 2017 +0200
@@ -128,13 +128,13 @@
${jprt.i586.build.configure.args}
jprt.linux_x64.build.configure.args= \
--with-devkit=$GCC492_OEL64_HOME
+jprt.macosx_x64.build.configure.args= \
+ --with-devkit=$XCODE63_MACOSX109_HOME
jprt.windows_i586.build.configure.args= \
--with-devkit=$VS2013SP4_HOME \
${jprt.i586.build.configure.args}
jprt.windows_x64.build.configure.args= \
--with-devkit=$VS2013SP4_HOME
-jprt.macosx_x64.build.configure.args= \
- --with-devkit=$XCODE_511_HOME
########
#
--- a/make/test/BuildTestLib.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/make/test/BuildTestLib.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -35,25 +35,19 @@
TEST_LIB_SOURCE_DIR := $(TOPDIR)/test/lib
TEST_LIB_SUPPORT := $(SUPPORT_OUTPUTDIR)/test/lib
-# Unfortunately, test-lib.jar does not compile properly without warnings.
-$(eval $(call SetupJavaCompiler, BOOT_JAVAC_NOWARNINGS, \
- JAVAC := $(JAVAC), \
- FLAGS := -XDignore.symbol.file=true -g, \
- DISABLE_SJAVAC := true, \
-))
-
$(eval $(call SetupJavaCompilation, BUILD_WB_JAR, \
- SETUP := BOOT_JAVAC, \
+ SETUP := GENERATE_USINGJDKBYTECODE, \
SRC := $(TEST_LIB_SOURCE_DIR)/sun, \
BIN := $(TEST_LIB_SUPPORT), \
JAR := $(TEST_LIB_SUPPORT)/wb.jar, \
+ ADD_JAVAC_FLAGS := $(JAVAC_WARNINGS), \
))
TARGETS += $(BUILD_WB_JAR)
# test-lib.jar will contain only hprof classes until JDK-8081381 is resolved
$(eval $(call SetupJavaCompilation, BUILD_TEST_LIB_JAR, \
- SETUP := BOOT_JAVAC_NOWARNINGS, \
+ SETUP := GENERATE_USINGJDKBYTECODE, \
SRC := $(TEST_LIB_SOURCE_DIR)/share/classes/jdk/test/lib/hprof, \
BIN := $(TEST_LIB_SUPPORT), \
JAR := $(TEST_LIB_SUPPORT)/test-lib.jar, \
--- a/nashorn/.hgtags Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/.hgtags Wed Jul 05 20:59:18 2017 +0200
@@ -324,3 +324,4 @@
a2aa804daac974289e20bf8f9106740732f08b34 jdk9-b88
62641244c378c17183b7208f3f1d75ba5f248a79 jdk9-b89
bc92163c4e0aa3fcca51a290c55715c54a5faa5f jdk9-b90
+fee4d2015e24ced4f28f4dcf93076a4fbd03844d jdk9-b91
--- a/nashorn/make/BuildNashorn.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/make/BuildNashorn.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -28,6 +28,7 @@
-include $(SPEC)
include MakeBase.gmk
+include JarArchive.gmk
include JavaCompilation.gmk
include SetupJavaCompilers.gmk
@@ -108,7 +109,7 @@
MANIFEST_ATTRIBUTES := Name: jdk/nashorn/\nImplementation-Title: Oracle Nashorn\nImplementation-Version: $(NASHORN_FULL_VERSION)
# Create nashorn.jar from the final classes dir
-$(eval $(call SetupArchive,BUILD_NASHORN_JAR, \
+$(eval $(call SetupJarArchive, BUILD_NASHORN_JAR, \
DEPENDENCIES := $(NASGEN_RUN_FILE) \
$(VERSION_FILE), \
SRCS := $(NASHORN_CLASSES_DIR), \
@@ -116,7 +117,8 @@
MANIFEST := $(NASHORN_TOPDIR)/src/jdk.scripting.nashorn/share/classes/META-INF/MANIFEST.MF, \
EXTRA_MANIFEST_ATTR := $(MANIFEST_ATTRIBUTES), \
SKIP_METAINF := true, \
- JAR := $(NASHORN_JAR)))
+ JAR := $(NASHORN_JAR), \
+))
compile: $(NASHORN_RUN_FILE) $(VERSION_FILE)
all: $(NASHORN_JAR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/find_underscores.js Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Usage: jjs find_underscores.js -- <directory>
+
+if (arguments.length == 0) {
+ print("Usage: jjs find_underscores.js -- <directory>");
+ exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var Trees = Java.type("com.sun.source.util.Trees");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+
+function findUnderscores() {
+ // get the system compiler tool
+ var compiler = ToolProvider.systemJavaCompiler;
+ // get standard file manager
+ var fileMgr = compiler.getStandardFileManager(null, null, null);
+ // Using Java.to convert script array (arguments) to a Java String[]
+ var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray));
+ // create a new compilation task
+ var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+ var sourcePositions = Trees.instance(task).sourcePositions;
+ // subclass SimpleTreeVisitor - to find underscore variable names
+ var UnderscoreFinder = Java.extend(TreeScanner);
+
+ var visitor = new UnderscoreFinder() {
+ // override to capture information on current compilation unit
+ visitCompilationUnit: function(compUnit, p) {
+ this.compUnit = compUnit;
+ this.lineMap = compUnit.lineMap;
+ this.fileName = compUnit.sourceFile.name;
+
+ return Java.super(visitor).visitCompilationUnit(compUnit, p);
+ },
+
+ // override to check variable name
+ visitVariable: function(node, p) {
+ if (node.name.toString() == "_") {
+ var pos = sourcePositions.getStartPosition(this.compUnit, node);
+ var line = this.lineMap.getLineNumber(pos);
+ var col = this.lineMap.getColumnNumber(pos);
+ print(node + " @ " + this.fileName + ":" + line + ":" + col);
+ }
+
+ return Java.super(visitor).visitVariable(node, p);
+ }
+ }
+
+ for each (var cu in task.parse()) {
+ cu.accept(visitor, null);
+ }
+}
+
+// for each ".java" file in directory (recursively).
+function main(dir) {
+ var totalCount = 0;
+ Files.walk(dir.toPath()).
+ forEach(function(p) {
+ var name = p.toFile().absolutePath;
+ if (name.endsWith(".java")) {
+ findUnderscores(p);
+ }
+ });
+}
+
+main(new File(arguments[0]));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java Thu Nov 05 13:43:17 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file, and Oracle licenses the original version of this file under the BSD
- * license:
- */
-/*
- Copyright 2009-2013 Attila Szegedi
-
- Licensed under both the Apache License, Version 2.0 (the "Apache License")
- and the BSD License (the "BSD License"), with licensee being free to
- choose either of the two at their discretion.
-
- You may not use this file except in compliance with either the Apache
- License or the BSD License.
-
- If you choose to use this file in compliance with the Apache License, the
- following notice applies to you:
-
- You may obtain a copy of the Apache License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied. See the License for the specific language governing
- permissions and limitations under the License.
-
- If you choose to use this file in compliance with the BSD License, the
- following notice applies to you:
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the copyright holder nor the names of
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-package jdk.internal.dynalink.support;
-
-
-/**
- * Implements the name mangling and demangling as specified by John Rose's
- * <a href="https://blogs.oracle.com/jrose/entry/symbolic_freedom_in_the_vm"
- * target="_blank">"Symbolic Freedom in the VM"</a> article. Normally, you would
- * mangle the names in the call sites as you're generating bytecode, and then
- * demangle them when you receive them in bootstrap methods.
- */
-public final class NameCodec {
- private static final char ESCAPE_CHAR = '\\';
- private static final char EMPTY_ESCAPE = '=';
- private static final String EMPTY_NAME = new String(new char[] { ESCAPE_CHAR, EMPTY_ESCAPE });
- private static final char EMPTY_CHAR = 0xFEFF;
-
- private static final int MIN_ENCODING = '$';
- private static final int MAX_ENCODING = ']';
- private static final char[] ENCODING = new char[MAX_ENCODING - MIN_ENCODING + 1];
- private static final int MIN_DECODING = '!';
- private static final int MAX_DECODING = '}';
- private static final char[] DECODING = new char[MAX_DECODING - MIN_DECODING + 1];
-
- static {
- addEncoding('/', '|');
- addEncoding('.', ',');
- addEncoding(';', '?');
- addEncoding('$', '%');
- addEncoding('<', '^');
- addEncoding('>', '_');
- addEncoding('[', '{');
- addEncoding(']', '}');
- addEncoding(':', '!');
- addEncoding('\\', '-');
- DECODING[EMPTY_ESCAPE - MIN_DECODING] = EMPTY_CHAR;
- }
-
- private NameCodec() {
- }
-
- /**
- * Encodes ("mangles") an unencoded symbolic name.
- * @param name the symbolic name to mangle
- * @return the mangled form of the symbolic name.
- */
- public static String encode(final String name) {
- final int l = name.length();
- if(l == 0) {
- return EMPTY_NAME;
- }
- StringBuilder b = null;
- int lastEscape = -1;
- for(int i = 0; i < l; ++i) {
- final int encodeIndex = name.charAt(i) - MIN_ENCODING;
- if(encodeIndex >= 0 && encodeIndex < ENCODING.length) {
- final char e = ENCODING[encodeIndex];
- if(e != 0) {
- if(b == null) {
- b = new StringBuilder(name.length() + 3);
- if(name.charAt(0) != ESCAPE_CHAR && i > 0) {
- b.append(EMPTY_NAME);
- }
- b.append(name, 0, i);
- } else {
- b.append(name, lastEscape + 1, i);
- }
- b.append(ESCAPE_CHAR).append(e);
- lastEscape = i;
- }
- }
- }
- if(b == null) {
- return name;
- }
- assert lastEscape != -1;
- b.append(name, lastEscape + 1, l);
- return b.toString();
- }
-
- /**
- * Decodes ("demangles") an encoded symbolic name.
- * @param name the symbolic name to demangle
- * @return the demangled form of the symbolic name.
- */
- public static String decode(final String name) {
- if(name.isEmpty() || name.charAt(0) != ESCAPE_CHAR) {
- return name;
- }
- final int l = name.length();
- if(l == 2 && name.charAt(1) == EMPTY_CHAR) {
- return "";
- }
- final StringBuilder b = new StringBuilder(name.length());
- int lastEscape = -2;
- int lastBackslash = -1;
- for(;;) {
- final int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
- if(nextBackslash == -1 || nextBackslash == l - 1) {
- break;
- }
- final int decodeIndex = name.charAt(nextBackslash + 1) - MIN_DECODING;
- if(decodeIndex >= 0 && decodeIndex < DECODING.length) {
- final char d = DECODING[decodeIndex];
- if(d == EMPTY_CHAR) {
- // "\=" is only valid at the beginning of a mangled string
- if(nextBackslash == 0) {
- lastEscape = 0;
- }
- } else if(d != 0) {
- b.append(name, lastEscape + 2, nextBackslash).append(d);
- lastEscape = nextBackslash;
- }
- }
- lastBackslash = nextBackslash;
- }
- b.append(name, lastEscape + 2, l);
- return b.toString();
- }
-
- private static void addEncoding(final char from, final char to) {
- ENCODING[from - MIN_ENCODING] = to;
- DECODING[to - MIN_DECODING] = from;
- }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Wed Jul 05 20:59:18 2017 +0200
@@ -49,7 +49,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.logging.Level;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.FunctionNode;
@@ -66,6 +65,7 @@
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.linker.NameCodec;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jul 05 20:59:18 2017 +0200
@@ -69,6 +69,7 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
+import static jdk.nashorn.internal.runtime.linker.NameCodec.EMPTY_NAME;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
@@ -79,7 +80,6 @@
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
@@ -107,6 +107,7 @@
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.linker.NameCodec;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.options.Options;
@@ -125,8 +126,6 @@
* including bytecode stack contents
*/
public class MethodEmitter {
- private static final String EMPTY_NAME = NameCodec.encode("");
-
/** The ASM MethodVisitor we are plugged into */
private final MethodVisitor method;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Wed Jul 05 20:59:18 2017 +0200
@@ -53,7 +53,6 @@
import java.io.IOException;
import java.io.Serializable;
import java.lang.invoke.CallSite;
-import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Collections;
@@ -246,7 +245,7 @@
* @return Nashorn type
*/
@SuppressWarnings("fallthrough")
- static Type typeFor(final jdk.internal.org.objectweb.asm.Type itype) {
+ private static Type typeFor(final jdk.internal.org.objectweb.asm.Type itype) {
switch (itype.getSort()) {
case jdk.internal.org.objectweb.asm.Type.BOOLEAN:
return BOOLEAN;
@@ -260,11 +259,13 @@
if (Context.isStructureClass(itype.getClassName())) {
return SCRIPT_OBJECT;
}
- try {
- return Type.typeFor(Class.forName(itype.getClassName()));
- } catch(final ClassNotFoundException e) {
- throw new AssertionError(e);
- }
+ return cacheByName.computeIfAbsent(itype.getClassName(), (name) -> {
+ try {
+ return Type.typeFor(Class.forName(name));
+ } catch(final ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ });
case jdk.internal.org.objectweb.asm.Type.VOID:
return null;
case jdk.internal.org.objectweb.asm.Type.ARRAY:
@@ -785,19 +786,10 @@
* @return the Type representing this class
*/
public static Type typeFor(final Class<?> clazz) {
- final Type type = cache.get(clazz);
- if(type != null) {
- return type;
- }
- assert !clazz.isPrimitive() || clazz == void.class;
- final Type newType;
- if (clazz.isArray()) {
- newType = new ArrayType(clazz);
- } else {
- newType = new ObjectType(clazz);
- }
- final Type existingType = cache.putIfAbsent(clazz, newType);
- return existingType == null ? newType : existingType;
+ return cache.computeIfAbsent(clazz, (keyClass) -> {
+ assert !keyClass.isPrimitive() || keyClass == void.class;
+ return keyClass.isArray() ? new ArrayType(keyClass) : new ObjectType(keyClass);
+ });
}
@Override
@@ -902,6 +894,7 @@
/** Mappings between java classes and their Type singletons */
private static final ConcurrentMap<Class<?>, Type> cache = new ConcurrentHashMap<>();
+ private static final ConcurrentMap<String, Type> cacheByName = new ConcurrentHashMap<>();
/**
* This is the boolean singleton, used for all boolean types
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ASTWriter.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ASTWriter.java Wed Jul 05 20:59:18 2017 +0200
@@ -55,6 +55,16 @@
* see the flags --print-ast and --print-ast-lower
*/
public final class ASTWriter {
+ private static final ClassValue<Field[]> accessibleFields = new ClassValue<Field[]>() {
+ @Override
+ protected Field[] computeValue(final Class<?> type) {
+ final Field[] fields = type.getDeclaredFields();
+ for(final Field f: fields) {
+ f.setAccessible(true);
+ }
+ return fields;
+ }
+ };
/** Root node from which to start the traversal */
private final Node root;
@@ -258,9 +268,8 @@
while (iter.hasNext()) {
final Class<?> c = iter.next();
- for (final Field f : c.getDeclaredFields()) {
+ for (final Field f : accessibleFields.get(c)) {
try {
- f.setAccessible(true);
final Object child = f.get(node);
if (child == null) {
continue;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jul 05 20:59:18 2017 +0200
@@ -39,7 +39,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.Label;
@@ -50,6 +49,7 @@
import jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.linker.NameCodec;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Jul 05 20:59:18 2017 +0200
@@ -68,8 +68,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-
-import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.AccessNode;
@@ -121,6 +119,7 @@
import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Timing;
+import jdk.nashorn.internal.runtime.linker.NameCodec;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Wed Jul 05 20:59:18 2017 +0200
@@ -64,13 +64,14 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
-import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -525,6 +526,7 @@
private static final ClassLoader myLoader = Context.class.getClassLoader();
private static final StructureLoader sharedLoader;
+ private static final ConcurrentMap<String, Class<?>> structureClasses = new ConcurrentHashMap<>();
/*package-private*/ @SuppressWarnings("static-method")
ClassLoader getSharedLoader() {
@@ -1056,7 +1058,13 @@
if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
throw new ClassNotFoundException(fullName);
}
- return (Class<? extends ScriptObject>)Class.forName(fullName, true, sharedLoader);
+ return (Class<? extends ScriptObject>)structureClasses.computeIfAbsent(fullName, (name) -> {
+ try {
+ return Class.forName(name, true, sharedLoader);
+ } catch (final ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ });
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jul 05 20:59:18 2017 +0200
@@ -44,7 +44,6 @@
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -67,6 +66,7 @@
import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.linker.NameCodec;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 05 20:59:18 2017 +0200
@@ -45,7 +45,6 @@
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
import jdk.internal.dynalink.linker.support.TypeUtilities;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NameCodec.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,432 @@
+/*
+ * 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.linker;
+
+/**
+ * <p>
+ * Implements the name mangling and demangling as specified by John Rose's
+ * <a href="https://blogs.oracle.com/jrose/entry/symbolic_freedom_in_the_vm"
+ * target="_blank">"Symbolic Freedom in the VM"</a> article. Normally, you would
+ * mangle the names in the call sites as you're generating bytecode, and then
+ * demangle them when you receive them in bootstrap methods.
+ * </p>
+ * <p>
+ * This code is derived from sun.invoke.util.BytecodeName. Apart from subsetting that
+ * class, we don't want to create dependency between non-exported package from java.base
+ * to nashorn module.
+ * </p>
+ *
+ * <h3>Comment from BytecodeName class reproduced here:</h3>
+ *
+ * Includes universal mangling rules for the JVM.
+ *
+ * <h3>Avoiding Dangerous Characters </h3>
+ *
+ * <p>
+ * The JVM defines a very small set of characters which are illegal
+ * in name spellings. We will slightly extend and regularize this set
+ * into a group of <cite>dangerous characters</cite>.
+ * These characters will then be replaced, in mangled names, by escape sequences.
+ * In addition, accidental escape sequences must be further escaped.
+ * Finally, a special prefix will be applied if and only if
+ * the mangling would otherwise fail to begin with the escape character.
+ * This happens to cover the corner case of the null string,
+ * and also clearly marks symbols which need demangling.
+ * </p>
+ * <p>
+ * Dangerous characters are the union of all characters forbidden
+ * or otherwise restricted by the JVM specification,
+ * plus their mates, if they are brackets
+ * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
+ * <code><big><b><</b></big></code> and <code><big><b>></b></big></code>),
+ * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
+ * There is no distinction between type, method, and field names.
+ * This makes it easier to convert between mangled names of different
+ * types, since they do not need to be decoded (demangled).
+ * </p>
+ * <p>
+ * The escape character is backslash <code><big><b>\</b></big></code>
+ * (also known as reverse solidus).
+ * This character is, until now, unheard of in bytecode names,
+ * but traditional in the proposed role.
+ *
+ * </p>
+ * <h3> Replacement Characters </h3>
+ *
+ *
+ * <p>
+ * Every escape sequence is two characters
+ * (in fact, two UTF8 bytes) beginning with
+ * the escape character and followed by a
+ * <cite>replacement character</cite>.
+ * (Since the replacement character is never a backslash,
+ * iterated manglings do not double in size.)
+ * </p>
+ * <p>
+ * Each dangerous character has some rough visual similarity
+ * to its corresponding replacement character.
+ * This makes mangled symbols easier to recognize by sight.
+ * </p>
+ * <p>
+ * The dangerous characters are
+ * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
+ * <code><big><b>.</b></big></code> (dot, also a package delimiter),
+ * <code><big><b>;</b></big></code> (semicolon, used in signatures),
+ * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
+ * <code><big><b><</b></big></code> (left angle),
+ * <code><big><b>></b></big></code> (right angle),
+ * <code><big><b>[</b></big></code> (left square bracket, used in array types),
+ * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
+ * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
+ * Their replacements are, respectively,
+ * <code><big><b>|</b></big></code> (vertical bar),
+ * <code><big><b>,</b></big></code> (comma),
+ * <code><big><b>?</b></big></code> (question mark),
+ * <code><big><b>%</b></big></code> (percent),
+ * <code><big><b>^</b></big></code> (caret),
+ * <code><big><b>_</b></big></code> (underscore), and
+ * <code><big><b>{</b></big></code> (left curly bracket),
+ * <code><big><b>}</b></big></code> (right curly bracket),
+ * <code><big><b>!</b></big></code> (exclamation mark).
+ * In addition, the replacement character for the escape character itself is
+ * <code><big><b>-</b></big></code> (hyphen),
+ * and the replacement character for the null prefix is
+ * <code><big><b>=</b></big></code> (equal sign).
+ * </p>
+ * <p>
+ * An escape character <code><big><b>\</b></big></code>
+ * followed by any of these replacement characters
+ * is an escape sequence, and there are no other escape sequences.
+ * An equal sign is only part of an escape sequence
+ * if it is the second character in the whole string, following a backslash.
+ * Two consecutive backslashes do <em>not</em> form an escape sequence.
+ * </p>
+ * <p>
+ * Each escape sequence replaces a so-called <cite>original character</cite>
+ * which is either one of the dangerous characters or the escape character.
+ * A null prefix replaces an initial null string, not a character.
+ * </p>
+ * <p>
+ * All this implies that escape sequences cannot overlap and may be
+ * determined all at once for a whole string. Note that a spelling
+ * string can contain <cite>accidental escapes</cite>, apparent escape
+ * sequences which must not be interpreted as manglings.
+ * These are disabled by replacing their leading backslash with an
+ * escape sequence (<code><big><b>\-</b></big></code>). To mangle a string, three logical steps
+ * are required, though they may be carried out in one pass:
+ * </p>
+ * <ol>
+ * <li>In each accidental escape, replace the backslash with an escape sequence
+ * (<code><big><b>\-</b></big></code>).</li>
+ * <li>Replace each dangerous character with an escape sequence
+ * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
+ * <li>If the first two steps introduced any change, <em>and</em>
+ * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
+ * </ol>
+ *
+ * To demangle a mangled string that begins with an escape,
+ * remove any null prefix, and then replace (in parallel)
+ * each escape sequence by its original character.
+ * <p>Spelling strings which contain accidental
+ * escapes <em>must</em> have them replaced, even if those
+ * strings do not contain dangerous characters.
+ * This restriction means that mangling a string always
+ * requires a scan of the string for escapes.
+ * But then, a scan would be required anyway,
+ * to check for dangerous characters.
+ *
+ * </p>
+ * <h3> Nice Properties </h3>
+ *
+ * <p>
+ * If a bytecode name does not contain any escape sequence,
+ * demangling is a no-op: The string demangles to itself.
+ * Such a string is called <cite>self-mangling</cite>.
+ * Almost all strings are self-mangling.
+ * In practice, to demangle almost any name “found in nature”,
+ * simply verify that it does not begin with a backslash.
+ * </p>
+ * <p>
+ * Mangling is a one-to-one function, while demangling
+ * is a many-to-one function.
+ * A mangled string is defined as <cite>validly mangled</cite> if
+ * it is in fact the unique mangling of its spelling string.
+ * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
+ * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
+ * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
+ * If a language back-end or runtime is using mangled names,
+ * it should never present an invalidly mangled bytecode
+ * name to the JVM. If the runtime encounters one,
+ * it should also report an error, since such an occurrence
+ * probably indicates a bug in name encoding which
+ * will lead to errors in linkage.
+ * However, this note does not propose that the JVM verifier
+ * detect invalidly mangled names.
+ * </p>
+ * <p>
+ * As a result of these rules, it is a simple matter to
+ * compute validly mangled substrings and concatenations
+ * of validly mangled strings, and (with a little care)
+ * these correspond to corresponding operations on their
+ * spelling strings.
+ * </p>
+ * <ul>
+ * <li>Any prefix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be removed.</li>
+ * <li>Any suffix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be added.</li>
+ * <li>Two validly mangled strings, when concatenated,
+ * are also validly mangled, although any null prefix
+ * must be removed from the second string,
+ * and a trailing backslash on the first string may need escaping,
+ * if it would participate in an accidental escape when followed
+ * by the first character of the second string.</li>
+ * </ul>
+ * <p>If languages that include non-Java symbol spellings use this
+ * mangling convention, they will enjoy the following advantages:
+ * </p>
+ * <ul>
+ * <li>They can interoperate via symbols they share in common.</li>
+ * <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
+ * <li>Future JVM and language extensions can safely use the dangerous characters
+ * for structuring symbols, but will never interfere with valid spellings.</li>
+ * <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
+ * <li>Occasional transliterations and name composition will be simple and regular,
+ * for classes, methods, and fields.</li>
+ * <li>Bytecode names will continue to be compact.
+ * When mangled, spellings will at most double in length, either in
+ * UTF8 or UTF16 format, and most will not change at all.</li>
+ * </ul>
+ *
+ *
+ * <h3> Suggestions for Human Readable Presentations </h3>
+ *
+ *
+ * <p>
+ * For human readable displays of symbols,
+ * it will be better to present a string-like quoted
+ * representation of the spelling, because JVM users
+ * are generally familiar with such tokens.
+ * We suggest using single or double quotes before and after
+ * mangled symbols which are not valid Java identifiers,
+ * with quotes, backslashes, and non-printing characters
+ * escaped as if for literals in the Java language.
+ * </p>
+ * <p>
+ * For example, an HTML-like spelling
+ * <code><big><b><pre></b></big></code> mangles to
+ * <code><big><b>\^pre\_</b></big></code> and could
+ * display more cleanly as
+ * <code><big><b>'<pre>'</b></big></code>,
+ * with the quotes included.
+ * Such string-like conventions are <em>not</em> suitable
+ * for mangled bytecode names, in part because
+ * dangerous characters must be eliminated, rather
+ * than just quoted. Otherwise internally structured
+ * strings like package prefixes and method signatures
+ * could not be reliably parsed.
+ * </p>
+ * <p>
+ * In such human-readable displays, invalidly mangled
+ * names should <em>not</em> be demangled and quoted,
+ * for this would be misleading. Likewise, JVM symbols
+ * which contain dangerous characters (like dots in field
+ * names or brackets in method names) should not be
+ * simply quoted. The bytecode names
+ * <code><big><b>\=phase\,1</b></big></code> and
+ * <code><big><b>phase.1</b></big></code> are distinct,
+ * and in demangled displays they should be presented as
+ * <code><big><b>'phase.1'</b></big></code> and something like
+ * <code><big><b>'phase'.1</b></big></code>, respectively.
+ * </p>
+ */
+public final class NameCodec {
+ private NameCodec() {
+ }
+
+ private static final char ESCAPE_C = '\\';
+ // empty escape sequence to avoid a null name or illegal prefix
+ private static final char NULL_ESCAPE_C = '=';
+ private static final String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
+
+ /**
+ * Canonical encoding for the empty name.
+ */
+ public static final String EMPTY_NAME = new String(new char[] { ESCAPE_C, NULL_ESCAPE_C });
+
+ /**
+ * Encodes ("mangles") an unencoded symbolic name.
+ * @param name the symbolic name to mangle
+ * @return the mangled form of the symbolic name.
+ */
+ public static String encode(final String name) {
+ String bn = mangle(name);
+ assert((Object)bn == name || looksMangled(bn)) : bn;
+ assert(name.equals(decode(bn))) : name;
+ return bn;
+ }
+
+ /**
+ * Decodes ("demangles") an encoded symbolic name.
+ * @param name the symbolic name to demangle
+ * @return the demangled form of the symbolic name.
+ */
+ public static String decode(final String name) {
+ String sn = name;
+ if (!sn.isEmpty() && looksMangled(name)) {
+ sn = demangle(name);
+ assert(name.equals(mangle(sn))) : name+" => "+sn+" => "+mangle(sn);
+ }
+ return sn;
+ }
+
+ private static boolean looksMangled(String s) {
+ return s.charAt(0) == ESCAPE_C;
+ }
+
+ private static String mangle(String s) {
+ if (s.length() == 0)
+ return NULL_ESCAPE;
+
+ // build this lazily, when we first need an escape:
+ StringBuilder sb = null;
+
+ for (int i = 0, slen = s.length(); i < slen; i++) {
+ char c = s.charAt(i);
+
+ boolean needEscape = false;
+ if (c == ESCAPE_C) {
+ if (i+1 < slen) {
+ char c1 = s.charAt(i+1);
+ if ((i == 0 && c1 == NULL_ESCAPE_C)
+ || c1 != originalOfReplacement(c1)) {
+ // an accidental escape
+ needEscape = true;
+ }
+ }
+ } else {
+ needEscape = isDangerous(c);
+ }
+
+ if (!needEscape) {
+ if (sb != null) sb.append(c);
+ continue;
+ }
+
+ // build sb if this is the first escape
+ if (sb == null) {
+ sb = new StringBuilder(s.length()+10);
+ // mangled names must begin with a backslash:
+ if (s.charAt(0) != ESCAPE_C && i > 0)
+ sb.append(NULL_ESCAPE);
+ // append the string so far, which is unremarkable:
+ sb.append(s, 0, i);
+ }
+
+ // rewrite \ to \-, / to \|, etc.
+ sb.append(ESCAPE_C);
+ sb.append(replacementOf(c));
+ }
+
+ if (sb != null) return sb.toString();
+
+ return s;
+ }
+
+ private static String demangle(String s) {
+ // build this lazily, when we first meet an escape:
+ StringBuilder sb = null;
+
+ int stringStart = 0;
+ if (s.startsWith(NULL_ESCAPE))
+ stringStart = 2;
+
+ for (int i = stringStart, slen = s.length(); i < slen; i++) {
+ char c = s.charAt(i);
+
+ if (c == ESCAPE_C && i+1 < slen) {
+ // might be an escape sequence
+ char rc = s.charAt(i+1);
+ char oc = originalOfReplacement(rc);
+ if (oc != rc) {
+ // build sb if this is the first escape
+ if (sb == null) {
+ sb = new StringBuilder(s.length());
+ // append the string so far, which is unremarkable:
+ sb.append(s, stringStart, i);
+ }
+ ++i; // skip both characters
+ c = oc;
+ }
+ }
+
+ if (sb != null)
+ sb.append(c);
+ }
+
+ if (sb != null) return sb.toString();
+
+ return s.substring(stringStart);
+ }
+
+ private static final String DANGEROUS_CHARS = "\\/.;:$[]<>"; // \\ must be first
+ private static final String REPLACEMENT_CHARS = "-|,?!%{}^_";
+ private static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
+
+ private static final long[] SPECIAL_BITMAP = new long[2]; // 128 bits
+ static {
+ String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
+ for (char c : SPECIAL.toCharArray()) {
+ SPECIAL_BITMAP[c >>> 6] |= 1L << c;
+ }
+ }
+
+ private static boolean isSpecial(char c) {
+ if ((c >>> 6) < SPECIAL_BITMAP.length)
+ return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
+ else
+ return false;
+ }
+
+ private static char replacementOf(char c) {
+ if (!isSpecial(c)) return c;
+ int i = DANGEROUS_CHARS.indexOf(c);
+ if (i < 0) return c;
+ return REPLACEMENT_CHARS.charAt(i);
+ }
+
+ private static char originalOfReplacement(char c) {
+ if (!isSpecial(c)) return c;
+ int i = REPLACEMENT_CHARS.indexOf(c);
+ if (i < 0) return c;
+ return DANGEROUS_CHARS.charAt(i);
+ }
+
+ private static boolean isDangerous(char c) {
+ if (!isSpecial(c)) return false;
+ return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Nov 05 13:43:17 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jul 05 20:59:18 2017 +0200
@@ -28,17 +28,22 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Stream;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.CompositeOperation;
import jdk.internal.dynalink.NamedOperation;
import jdk.internal.dynalink.Operation;
import jdk.internal.dynalink.StandardOperation;
-import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.ir.debug.NashornTextifier;
import jdk.nashorn.internal.runtime.AccessControlContextFactory;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -158,6 +163,11 @@
private static final AccessControlContext GET_LOOKUP_PERMISSION_CONTEXT =
AccessControlContextFactory.createAccessControlContext(CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME);
+ @SuppressWarnings("unchecked")
+ private static final Map<String, Reference<NamedOperation>>[] NAMED_OPERATIONS =
+ Stream.generate(() -> Collections.synchronizedMap(new WeakHashMap<>()))
+ .limit(OPERATIONS.length).toArray(Map[]::new);
+
private final int flags;
/**
@@ -218,19 +228,36 @@
*/
public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
final MethodType methodType, final int flags) {
- final Operation baseOp = OPERATIONS[flags & OPERATION_MASK];
+ final int opIndex = flags & OPERATION_MASK;
+ final Operation baseOp = OPERATIONS[opIndex];
final String decodedName = NameCodec.decode(name);
- // TODO: introduce caching of NamedOperation
- final Operation op = decodedName.isEmpty() ? baseOp : new NamedOperation(baseOp, decodedName);
+ final Operation op = decodedName.isEmpty() ? baseOp : getNamedOperation(decodedName, opIndex, baseOp);
return get(lookup, op, methodType, flags);
}
+ private static NamedOperation getNamedOperation(final String name, final int opIndex, final Operation baseOp) {
+ final Map<String, Reference<NamedOperation>> namedOps = NAMED_OPERATIONS[opIndex];
+ final Reference<NamedOperation> ref = namedOps.get(name);
+ if (ref != null) {
+ final NamedOperation existing = ref.get();
+ if (existing != null) {
+ return existing;
+ }
+ }
+ final NamedOperation newOp = new NamedOperation(baseOp, name);
+ namedOps.put(name, new WeakReference<>(newOp));
+ return newOp;
+ }
+
private static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final Operation operation, final MethodType methodType, final int flags) {
final NashornCallSiteDescriptor csd = new NashornCallSiteDescriptor(lookup, operation, methodType, flags);
// Many of these call site descriptors are identical (e.g. every getter for a property color will be
- // "GET_PROPERTY:color(Object)Object", so it makes sense canonicalizing them.
- final ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> classCanonicals = canonicals.get(lookup.lookupClass());
- final NashornCallSiteDescriptor canonical = classCanonicals.putIfAbsent(csd, csd);
+ // "GET_PROPERTY:color(Object)Object", so it makes sense canonicalizing them. Make an exception for
+ // optimistic call site descriptors, as they also carry a program point making them unique.
+ if (csd.isOptimistic()) {
+ return csd;
+ }
+ final NashornCallSiteDescriptor canonical = canonicals.get(lookup.lookupClass()).putIfAbsent(csd, csd);
return canonical != null ? canonical : csd;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/linker/test/NameCodecTest.java Wed Jul 05 20:59:18 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.linker.test;
+
+import static org.testng.Assert.assertEquals;
+
+import jdk.nashorn.internal.runtime.linker.NameCodec;
+import org.testng.annotations.Test;
+
+/**
+ * Test for jdk.nashorn.intenal.runtime.linker.NameCodec.java. This test is
+ * derived from BytecodeNameTest.java from (older) mlvm code @
+ * http://hg.openjdk.java.net/mlvm/mlvm/file/tip/netbeans/meth/test/sun/invoke/util/BytecodeNameTest.java
+ *
+ * @bug 8141285: NameCode should pass tests from BytecodeNameTest.java
+ */
+public class NameCodecTest {
+
+ static String[][] SAMPLES = {
+ // mangled, source
+ {"foo", "foo"},
+ {"ba\\r", "ba\\r"},
+ {"\\=ba\\-%z", "ba\\%z"},
+ {"\\=ba\\--z", "ba\\-z"},
+ {"=\\=", "=\\="},
+ {"\\==\\|\\=", "=/\\="},
+ {"\\|\\=", "/\\="},
+ {"\\=ba\\!", "ba:"},
+ {"\\|", "/"},
+ {"\\", "\\"},
+ {"\\\\%", "\\$"},
+ {"\\\\", "\\\\"},
+ {"\\=", ""}
+
+ };
+
+ static final String DANGEROUS_CHARS = "\\/.;:$[]<>";
+ static final String REPLACEMENT_CHARS = "-|,?!%{}^_";
+
+ static String[][] canonicalSamples() {
+ int ndc = DANGEROUS_CHARS.length();
+ String[][] res = new String[2 * ndc][];
+ for (int i = 0; i < ndc; i++) {
+ char dc = DANGEROUS_CHARS.charAt(i);
+ char rc = REPLACEMENT_CHARS.charAt(i);
+ if (dc == '\\') {
+ res[2 * i + 0] = new String[]{"\\-%", "\\%"};
+ } else {
+ res[2 * i + 0] = new String[]{"\\" + rc, "" + dc};
+ }
+ res[2 * i + 1] = new String[]{"" + rc, "" + rc};
+ }
+ return res;
+ }
+
+ @Test
+ public void testEncode() {
+ System.out.println("testEncode");
+ testEncode(SAMPLES);
+ testEncode(canonicalSamples());
+ }
+
+ private void testEncode(String[][] samples) {
+ for (String[] sample : samples) {
+ String s = sample[1];
+ String expResult = sample[0];
+ String result = NameCodec.encode(s);
+ if (!result.equals(expResult)) {
+ System.out.println(s + " => " + result + " != " + expResult);
+ }
+ assertEquals(expResult, result);
+ }
+ }
+
+ @Test
+ public void testDecode() {
+ System.out.println("testDecode");
+ testDecode(SAMPLES);
+ testDecode(canonicalSamples());
+ }
+
+ private void testDecode(String[][] samples) {
+ for (String[] sample : samples) {
+ String s = sample[0];
+ String expResult = sample[1];
+ String result = NameCodec.decode(s);
+ assertEquals(expResult, result);
+ }
+ }
+}
--- a/test/lib/sun/hotspot/WhiteBox.java Thu Nov 05 13:43:17 2015 -0800
+++ b/test/lib/sun/hotspot/WhiteBox.java Wed Jul 05 20:59:18 2017 +0200
@@ -166,6 +166,8 @@
// Compiler
public native int matchesMethod(Executable method, String pattern);
+ public native int matchesInline(Executable method, String pattern);
+ public native boolean shouldPrintAssembly(Executable method);
public native int deoptimizeFrames(boolean makeNotEntrant);
public native void deoptimizeAll();
public boolean isMethodCompiled(Executable method) {
--- a/test/make/TestJavaCompilation.gmk Thu Nov 05 13:43:17 2015 -0800
+++ b/test/make/TestJavaCompilation.gmk Wed Jul 05 20:59:18 2017 +0200
@@ -27,6 +27,7 @@
include $(SPEC)
include MakeBase.gmk
+include JarArchive.gmk
include JavaCompilation.gmk
THIS_FILE := $(SRC_ROOT)/test/make/TestJavaCompilation.gmk
@@ -66,11 +67,12 @@
$(TOUCH) $(JAR1_SRC_ROOT)/META-INF/metafile
$(TOUCH) $@
-$(eval $(call SetupArchive,BUILD_JAR1, \
+$(eval $(call SetupJarArchive, BUILD_JAR1, \
DEPENDENCIES := $(OUTPUT_DIR)/_jar1_created, \
SRCS := $(JAR1_SRC_ROOT), \
MANIFEST := $(JAR1_MANIFEST), \
- JAR := $(JAR1_FILE)))
+ JAR := $(JAR1_FILE), \
+))
$(OUTPUT_DIR)/_jar1_verified: $(BUILD_JAR1)
$(RM) -r $(JAR1_UNZIP)
@@ -142,10 +144,11 @@
$(TOUCH) $(JAR2_SRC_ROOT2)/dir2/file2.class
$(TOUCH) $@
-$(eval $(call SetupArchive,BUILD_JAR2, \
+$(eval $(call SetupJarArchive, BUILD_JAR2, \
DEPENDENCIES := $(OUTPUT_DIR)/_jar2_created, \
SRCS := $(JAR2_SRC_ROOT1) $(JAR2_SRC_ROOT2), \
- JAR := $(JAR2_FILE)))
+ JAR := $(JAR2_FILE), \
+))
$(OUTPUT_DIR)/_jar2_verified: $(BUILD_JAR2)
$(RM) -r $(JAR2_UNZIP)
@@ -195,14 +198,15 @@
$(TOUCH) $(JAR3_SRC_ROOT2)/dir2/file\$$foo.dollar
$(TOUCH) $@
-$(eval $(call SetupArchive,BUILD_JAR3, \
+$(eval $(call SetupJarArchive, BUILD_JAR3, \
DEPENDENCIES := $(OUTPUT_DIR)/_jar3_created, \
SRCS := $(JAR3_SRC_ROOT1) $(JAR3_SRC_ROOT2), \
EXTRA_FILES := extra-file \
dir2/file$$$$foo.dollar \
$(JAR3_SRC_ROOT2)/extra-file-abs, \
EXCLUDE_FILES := dir1/file1$$$$foo.class, \
- JAR := $(JAR3_FILE)))
+ JAR := $(JAR3_FILE), \
+))
$(OUTPUT_DIR)/_jar3_verified: $(BUILD_JAR3)
$(RM) -r $(JAR3_UNZIP)