# HG changeset patch # User duke # Date 1499281163 -7200 # Node ID fd0807825b823594eadd22e8f59d6221cd267d91 # Parent 27b563ba49e8756982c31ef632fcd23eb261bf79# Parent 5b9a259327ecb7678946aa268a4b1e3db8f8e4ed Merge diff -r 27b563ba49e8 -r fd0807825b82 .hgtags-top-repo --- a/.hgtags-top-repo Thu Nov 05 13:42:20 2015 -0800 +++ b/.hgtags-top-repo Wed Jul 05 20:59:23 2017 +0200 @@ -333,3 +333,4 @@ 0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88 895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89 cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90 +122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91 diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/compare.sh.in --- a/common/autoconf/compare.sh.in Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/compare.sh.in Wed Jul 05 20:59:23 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" "$@" diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/flags.m4 --- a/common/autoconf/flags.m4 Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/flags.m4 Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/generated-configure.sh Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/hotspot-spec.gmk.in --- a/common/autoconf/hotspot-spec.gmk.in Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/hotspot-spec.gmk.in Wed Jul 05 20:59:23 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@ diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/source-dirs.m4 --- a/common/autoconf/source-dirs.m4 Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/source-dirs.m4 Wed Jul 05 20:59:23 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], diff -r 27b563ba49e8 -r fd0807825b82 common/autoconf/spec.gmk.in --- a/common/autoconf/spec.gmk.in Thu Nov 05 13:42:20 2015 -0800 +++ b/common/autoconf/spec.gmk.in Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 common/bin/compare.sh --- a/common/bin/compare.sh Thu Nov 05 13:42:20 2015 -0800 +++ b/common/bin/compare.sh Wed Jul 05 20:59:23 2017 +0200 @@ -989,7 +989,7 @@ fi fi -THIS="$( cd "$( dirname "$0" )" > /dev/null && pwd )" +THIS="$SCRIPT_DIR" echo "$THIS" THIS_SCRIPT="$0" diff -r 27b563ba49e8 -r fd0807825b82 corba/.hgtags --- a/corba/.hgtags Thu Nov 05 13:42:20 2015 -0800 +++ b/corba/.hgtags Wed Jul 05 20:59:23 2017 +0200 @@ -333,3 +333,4 @@ 00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88 c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89 29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90 +75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/.hgtags --- a/hotspot/.hgtags Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/.hgtags Wed Jul 05 20:59:23 2017 +0200 @@ -493,3 +493,4 @@ bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88 20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89 7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90 +3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/make/bsd/makefiles/gcc.make --- a/hotspot/make/bsd/makefiles/gcc.make Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/make/bsd/makefiles/gcc.make Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk --- a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk Wed Jul 05 20:59:23 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) $@ diff -r 27b563ba49e8 -r fd0807825b82 hotspot/make/linux/makefiles/gcc.make --- a/hotspot/make/linux/makefiles/gcc.make Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/make/linux/makefiles/gcc.make Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/make/solaris/makefiles/gcc.make --- a/hotspot/make/solaris/makefiles/gcc.make Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/make/solaris/makefiles/gcc.make Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 20:59:23 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) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 20:59:23 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. diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Jul 05 20:59:23 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); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Wed Jul 05 20:59:23 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(); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Jul 05 20:59:23 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(); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jul 05 20:59:23 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(); } } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jul 05 20:59:23 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() { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/x86.ad --- a/hotspot/src/cpu/x86/vm/x86.ad Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/x86.ad Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/zero/vm/compiledIC_zero.cpp --- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/zero/vm/relocInfo_zero.cpp --- a/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp Wed Jul 05 20:59:23 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(); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/cpu/zero/vm/vm_version_zero.cpp --- a/hotspot/src/cpu/zero/vm/vm_version_zero.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/cpu/zero/vm/vm_version_zero.cpp Wed Jul 05 20:59:23 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); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/adlc/formssel.cpp --- a/hotspot/src/share/vm/adlc/formssel.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Jul 05 20:59:23 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", diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_Compilation.cpp --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Jul 05 20:59:23 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) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_Compilation.hpp --- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_Compiler.cpp --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Wed Jul 05 20:59:23 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); } } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_Compiler.hpp --- a/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp Wed Jul 05 20:59:23 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(); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_LIR.cpp --- a/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_LIR.hpp --- a/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Jul 05 20:59:23 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)); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_LIRGenerator.hpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 20:59:23 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: diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp --- a/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/c1/c1_Runtime1.cpp --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 20:59:23 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); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/ci/ciEnv.hpp --- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/ci/ciField.cpp --- a/hotspot/src/share/vm/ci/ciField.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/ci/ciField.cpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 20:59:23 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 -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(const char* option, intx& value); -template bool ciMethod::has_option_value(const char* option, uintx& value); -template bool ciMethod::has_option_value(const char* option, bool& value); -template bool ciMethod::has_option_value(const char* option, ccstr& value); -template bool ciMethod::has_option_value(const char* option, double& value); - // ------------------------------------------------------------------ // ciMethod::can_be_compiled // diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/ci/ciMethod.hpp --- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 05 20:59:23 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 - 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/classfile/vmSymbols.cpp --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Jul 05 20:59:23 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) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/abstractCompiler.hpp --- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Wed Jul 05 20:59:23 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(); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compileBroker.cpp --- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:59:23 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 } + diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compileBroker.hpp --- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compileTask.cpp --- a/hotspot/src/share/vm/compiler/compileTask.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/compileTask.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compilerDirectives.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp Wed Jul 05 20:59:23 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); +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compilerDirectives.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp Wed Jul 05 20:59:23 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 { +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 { +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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compilerOracle.cpp --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jul 05 20:59:23 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(), option_list); matcher->set_value(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(methodHandle method, const char* option, intx& value); template bool CompilerOracle::has_option_value(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); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/compilerOracle.hpp --- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Wed Jul 05 20:59:23 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 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*)); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/directivesParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/compiler/directivesParser.cpp Wed Jul 05 20:59:23 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 + +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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/directivesParser.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/compiler/directivesParser.hpp Wed Jul 05 20:59:23 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 : 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/methodMatcher.cpp --- a/hotspot/src/share/vm/compiler/methodMatcher.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp Wed Jul 05 20:59:23 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; +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/compiler/methodMatcher.hpp --- a/hotspot/src/share/vm/compiler/methodMatcher.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/jvmci/jvmciCompiler.cpp --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp Wed Jul 05 20:59:23 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(); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/jvmci/jvmciCompiler.hpp --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp Wed Jul 05 20:59:23 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); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/oops/symbol.cpp --- a/hotspot/src/share/vm/oops/symbol.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/oops/symbol.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/oops/symbol.hpp --- a/hotspot/src/share/vm/oops/symbol.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/oops/symbol.hpp Wed Jul 05 20:59:23 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. diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/block.cpp --- a/hotspot/src/share/vm/opto/block.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/block.cpp Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/block.hpp --- a/hotspot/src/share/vm/opto/block.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/block.hpp Wed Jul 05 20:59:23 2017 +0200 @@ -368,7 +368,6 @@ class PhaseCFG : public Phase { friend class VMStructs; private: - // Root of whole program RootNode* _root; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/bytecodeInfo.cpp --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/c2_globals.hpp --- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Jul 05 20:59:23 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, \ diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/c2compiler.cpp --- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/c2compiler.cpp Wed Jul 05 20:59:23 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) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/c2compiler.hpp --- a/hotspot/src/share/vm/opto/c2compiler.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/c2compiler.hpp Wed Jul 05 20:59:23 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(); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Wed Jul 05 20:59:23 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]); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/classes.hpp --- a/hotspot/src/share/vm/opto/classes.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/classes.hpp Wed Jul 05 20:59:23 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) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 20:59:23 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* _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 - 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/graphKit.cpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/graphKit.hpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/idealGraphPrinter.cpp --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Wed Jul 05 20:59:23 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[]; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/idealGraphPrinter.hpp --- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/idealKit.cpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/idealKit.hpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:59:23 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"); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/loopnode.hpp --- a/hotspot/src/share/vm/opto/loopnode.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 20:59:23 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. diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 20:59:23 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. diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/memnode.cpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/memnode.hpp diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/output.cpp Wed Jul 05 20:59:23 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()) diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/parse2.cpp --- a/hotspot/src/share/vm/opto/parse2.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:59:23 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(); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/subnode.cpp --- a/hotspot/src/share/vm/opto/subnode.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/subnode.cpp Wed Jul 05 20:59:23 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) ); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/subnode.hpp --- a/hotspot/src/share/vm/opto/subnode.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/subnode.hpp Wed Jul 05 20:59:23 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 { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:59:23 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); } } } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/superword.hpp --- a/hotspot/src/share/vm/opto/superword.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/superword.hpp Wed Jul 05 20:59:23 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 _iteration_first; // nodes in the generation that has deps from phi GrowableArray _iteration_last; // nodes in the generation that has deps to phi GrowableArray _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 _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 _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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/vectornode.cpp --- a/hotspot/src/share/vm/opto/vectornode.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/vectornode.cpp Wed Jul 05 20:59:23 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/opto/vectornode.hpp --- a/hotspot/src/share/vm/opto/vectornode.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/opto/vectornode.hpp Wed Jul 05 20:59:23 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 { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 20:59:23 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}, diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:59:23 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.") \ \ @@ -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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/init.cpp --- a/hotspot/src/share/vm/runtime/init.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/init.cpp Wed Jul 05 20:59:23 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()) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:59:23 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; diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:59:23 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) { diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/runtime/vm_operations.cpp --- a/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 20:59:23 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" diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/services/diagnosticCommand.cpp --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:59:23 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(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(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), diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/services/diagnosticCommand.hpp --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:59:23 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 _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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/shark/sharkCompiler.cpp --- a/hotspot/src/share/vm/shark/sharkCompiler.cpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Jul 05 20:59:23 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); } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/shark/sharkCompiler.hpp --- a/hotspot/src/share/vm/shark/sharkCompiler.hpp Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Jul 05 20:59:23 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(); diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/utilities/json.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/json.cpp Wed Jul 05 20:59:23 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 + +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(""); + 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(""); + 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, "%" PRId64 ",\n", v->int_value); + prev = JSON_NONE; + return true; + + case JSON_NUMBER_FLOAT: + log(rlevel, "%lf,\n", v->double_value); + prev = JSON_NONE; + return true; + + case JSON_TRUE: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + case JSON_FALSE: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + case JSON_NULL: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + default: + error(INTERNAL_ERROR, "unknown JSON type"); + return false; + } +} +#endif diff -r 27b563ba49e8 -r fd0807825b82 hotspot/src/share/vm/utilities/json.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/json.hpp Wed Jul 05 20:59:23 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 diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/InlineMatcherTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java Wed Jul 05 20:59:23 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 { + private static final long serialVersionUID = 1L; + + public boolean add(Method testTarget, String pattern, int expectedResult) { + return super.add(new TestCase(testTarget, pattern, expectedResult)); + } + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Jul 05 20:59:23 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); + } + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Jul 05 20:59:23 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)); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Jul 05 20:59:23 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)); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Jul 05 20:59:23 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)); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commandfile/LogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commands/LogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commands/LogTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/commands/PrintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/control_off.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/control_off.txt Wed Jul 05 20:59:23 2017 +0200 @@ -0,0 +1,7 @@ +[ + { + match: "*.helper", + PrintAssembly: false, + DisableIntrinsic:"x" + } +] diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/control_on.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/control_on.txt Wed Jul 05 20:59:23 2017 +0200 @@ -0,0 +1,7 @@ +[ + { + match: "*.helper", + PrintAssembly: true, + DisableIntrinsic:"_dsin" + } +] diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/directives/LogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/directives/LogTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/directives/PrintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java Wed Jul 05 20:59:23 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; + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Wed Jul 05 20:59:23 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>> 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; + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/JSONFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/JSONFile.java Wed Jul 05 20:59:23 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 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/MultiCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java Wed Jul 05 20:59:23 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 testCases; + + public MultiCommand(List 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 commands = cmdGen.generateCommands(); + List 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/SingleCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/SingleCommand.java Wed Jul 05 20:59:23 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(); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java Wed Jul 05 20:59:23 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>> METHODS; + private static final Map 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 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 decodeMap(List lines) { + if (lines == null || lines.size() == 0) { + throw new Error("TESTBUG: unexpected lines list"); + } + Map stateMap = new HashMap<>(); + int startIndex = 0; + ListIterator 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 methodStates) { + // Check each method from the pool + METHODS.forEach(pair -> { + Executable x = pair.first; + CompileAction.checkCompiled(x, methodStates.get(x)); + }); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/actions/CompileAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/actions/CompileAction.java Wed Jul 05 20:59:23 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>> 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> pair : METHODS) { + if (pair.first == executable) { + return pair.second; + } + } + throw new Error("TESTBUG: wrong executable: " + executable); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java --- a/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java Wed Jul 05 20:59:23 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 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; } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/method/SignatureType.java --- a/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java Thu Nov 05 13:42:20 2015 -0800 +++ b/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java Wed Jul 05 20:59:23 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); + } } diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java Wed Jul 05 20:59:23 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 { + protected final List commands; + + public CommandProcessor(List 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)"); + } + } + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java Wed Jul 05 20:59:23 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 { + public static final String LOG_FILE = "compilation.log"; + private static final String TASK_ELEMENT = "]*>"; + private static final String TASK_DONE_ELEMENT = "]*>"; + private static final String TASK_END_ELEMENT = ""; + private static final String ANY_ELEMENT = "<[^>]*>"; + private static final Pattern METHOD_PATTERN = Pattern.compile( + "method='([^']+)'"); + private final List loggedMethods; + private final List testMethods; + private Scanner scanner = null; + + public LogProcessor(Map 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 and + except 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(">", ">"); + } +} diff -r 27b563ba49e8 -r fd0807825b82 hotspot/test/compiler/compilercontrol/share/processors/PrintProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/processors/PrintProcessor.java Wed Jul 05 20:59:23 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 { + /** + * 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 (?\\(.*\\))[ ]+" + + "(?