Merge
authorduke
Wed, 05 Jul 2017 20:58:59 +0200
changeset 33529 d8b2864e0ec4
parent 33528 ff95a3cea444 (current diff)
parent 33490 77273343c131 (diff)
child 33531 7485b48d6b2e
Merge
--- a/.hgtags-top-repo	Thu Nov 05 13:42:47 2015 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 20:58:59 2017 +0200
@@ -333,3 +333,4 @@
 0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
 895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89
 cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90
+122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91
--- a/common/autoconf/compare.sh.in	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/compare.sh.in	Wed Jul 05 20:58:59 2017 +0200
@@ -86,4 +86,6 @@
 $RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
 $MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
 
+export SCRIPT_DIR="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
+
 $BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
--- a/common/autoconf/flags.m4	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/flags.m4	Wed Jul 05 20:58:59 2017 +0200
@@ -831,8 +831,6 @@
     JDKLIB_LIBS="-ljava -ljvm"
     if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
       JDKLIB_LIBS="$JDKLIB_LIBS -lc"
-    elif test "x$TOOLCHAIN_TYPE" = xxlc; then
-      JDKLIB_LIBS="$JDKLIB_LIBS -liconv"
     fi
   fi
 
@@ -944,7 +942,16 @@
   else
     AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
   fi
+
+  if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
+    # Set legacy hotspot variable
+    HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
+  else
+    HOTSPOT_SET_WARNINGS_AS_ERRORS=""
+  fi
+
   AC_SUBST(WARNINGS_AS_ERRORS)
+  AC_SUBST(HOTSPOT_SET_WARNINGS_AS_ERRORS)
 
   case "${TOOLCHAIN_TYPE}" in
     microsoft)
--- a/common/autoconf/generated-configure.sh	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 20:58:59 2017 +0200
@@ -685,6 +685,7 @@
 ENABLE_DEBUG_SYMBOLS
 CFLAGS_WARNINGS_ARE_ERRORS
 DISABLE_WARNING_PREFIX
+HOTSPOT_SET_WARNINGS_AS_ERRORS
 WARNINGS_AS_ERRORS
 COMPILER_SUPPORTS_TARGET_BITS_FLAG
 ZERO_ARCHFLAG
@@ -805,8 +806,6 @@
 BUILD_HOTSPOT
 HOTSPOT_DIST
 BUILD_OUTPUT
-OVERRIDE_SRC_ROOT
-ADD_SRC_ROOT
 JDK_TOPDIR
 NASHORN_TOPDIR
 HOTSPOT_TOPDIR
@@ -1912,26 +1911,29 @@
   --with-build-number     Set build number value for build [b00]
   --with-copyright-year   Set copyright year value for build [current year]
   --with-boot-jdk         path to Boot JDK (used to bootstrap build) [probed]
-  --with-add-source-root  for each and every source directory, look in this
-                          additional source root for the same directory; if it
-                          exists and have files in it, include it in the build
+  --with-add-source-root  Deprecated. Option is kept for backwards
+                          compatibility and is ignored
   --with-override-source-root
-                          for each and every source directory, look in this
-                          override source root for the same directory; if it
-                          exists, use that directory instead and ignore the
-                          directory in the original source root
+                          Deprecated. Option is kept for backwards
+                          compatibility and is ignored
   --with-adds-and-overrides
-                          use the subdirs 'adds' and 'overrides' in the
-                          specified directory as add-source-root and
-                          override-source-root
+                          Deprecated. Option is kept for backwards
+                          compatibility and is ignored
   --with-override-langtools
-                          use this langtools dir for the build
-  --with-override-corba   use this corba dir for the build
-  --with-override-jaxp    use this jaxp dir for the build
-  --with-override-jaxws   use this jaxws dir for the build
-  --with-override-hotspot use this hotspot dir for the build
-  --with-override-nashorn use this nashorn dir for the build
-  --with-override-jdk     use this jdk dir for the build
+                          Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-corba   Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-jaxp    Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-jaxws   Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-hotspot Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-nashorn Deprecated. Option is kept for backwards
+                          compatibility and is ignored
+  --with-override-jdk     Deprecated. Option is kept for backwards
+                          compatibility and is ignored
   --with-import-hotspot   import hotspot binaries from this jdk image or
                           hotspot build dist dir instead of building from
                           source
@@ -4354,7 +4356,7 @@
 
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -4384,7 +4386,6 @@
 
 
 
-
 #
 # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4597,7 +4598,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1446135203
+DATE_WHEN_GENERATED=1446762265
 
 ###############################################################################
 #
@@ -28868,8 +28869,7 @@
 ###############################################################################
 
 
-  # Where are the sources. Any of these can be overridden
-  # using --with-override-corba and the likes.
+  # Where are the sources.
   LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
   CORBA_TOPDIR="$SRC_ROOT/corba"
   JAXP_TOPDIR="$SRC_ROOT/jaxp"
@@ -28886,263 +28886,98 @@
 
 
 
-
-  ###############################################################################
-  #
-  # Pickup additional source for a component from outside of the source root
-  # or override source for a component.
-  #
+  # This feature is no longer supported.
+
+
 
 # Check whether --with-add-source-root was given.
 if test "${with_add_source_root+set}" = set; then :
-  withval=$with_add_source_root;
-fi
+  withval=$with_add_source_root; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-add-source-root is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-add-source-root is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-source-root was given.
 if test "${with_override_source_root+set}" = set; then :
-  withval=$with_override_source_root;
-fi
+  withval=$with_override_source_root; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-source-root is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-source-root is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-adds-and-overrides was given.
 if test "${with_adds_and_overrides+set}" = set; then :
-  withval=$with_adds_and_overrides;
-fi
-
-
-  if test "x$with_adds_and_overrides" != x; then
-    with_add_source_root="$with_adds_and_overrides/adds"
-    with_override_source_root="$with_adds_and_overrides/overrides"
-  fi
-
-  if test "x$with_add_source_root" != x; then
-    if ! test -d $with_add_source_root; then
-      as_fn_error $? "Trying to use a non-existant add-source-root $with_add_source_root" "$LINENO" 5
-    fi
-    CURDIR="$PWD"
-    cd "$with_add_source_root"
-    ADD_SRC_ROOT="`pwd`"
-    cd "$CURDIR"
-    # Verify that the addon source root does not have any root makefiles.
-    # If it does, then it is usually an error, prevent this.
-    if test -f $with_add_source_root/langtools/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full langtools repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/corba/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full corba repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/jaxp/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full jaxp repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/jaxws/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full jaxws repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/hotspot/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/nashorn/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-    if test -f $with_add_source_root/jdk/make/Makefile; then
-      as_fn_error $? "Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources." "$LINENO" 5
-    fi
-  fi
-
-
-  if test "x$with_override_source_root" != x; then
-    if ! test -d $with_override_source_root; then
-      as_fn_error $? "Trying to use a non-existant override-source-root $with_override_source_root" "$LINENO" 5
-    fi
-    CURDIR="$PWD"
-    cd "$with_override_source_root"
-    OVERRIDE_SRC_ROOT="`pwd`"
-    cd "$CURDIR"
-    if test -f $with_override_source_root/langtools/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full langtools repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/corba/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full corba repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/jaxp/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full jaxp repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/jaxws/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full jaxws repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/hotspot/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/nashorn/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-    if test -f $with_override_source_root/jdk/make/Makefile; then
-      as_fn_error $? "Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override." "$LINENO" 5
-    fi
-  fi
-
-
-  ###############################################################################
-  #
-  # Override a repo completely, this is used for example when you have 3 small
-  # development sandboxes of the langtools sources and want to avoid having 3 full
-  # OpenJDK sources checked out on disk.
-  #
-  # Assuming that the 3 langtools sandboxes are located here:
-  # /home/fredrik/sandbox1/langtools
-  # /home/fredrik/sandbox2/langtools
-  # /home/fredrik/sandbox3/langtools
-  #
-  # From the source root you create build subdirs manually:
-  #     mkdir -p build1 build2 build3
-  # in each build directory run:
-  #     (cd build1 && ../configure --with-override-langtools=/home/fredrik/sandbox1 && make)
-  #     (cd build2 && ../configure --with-override-langtools=/home/fredrik/sandbox2 && make)
-  #     (cd build3 && ../configure --with-override-langtools=/home/fredrik/sandbox3 && make)
-  #
+  withval=$with_adds_and_overrides; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-adds-and-overrides is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-adds-and-overrides is deprecated and will be ignored." >&2;}
+fi
+
+
 
 
 # Check whether --with-override-langtools was given.
 if test "${with_override_langtools+set}" = set; then :
-  withval=$with_override_langtools;
-fi
+  withval=$with_override_langtools; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-langtools is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-langtools is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-corba was given.
 if test "${with_override_corba+set}" = set; then :
-  withval=$with_override_corba;
-fi
+  withval=$with_override_corba; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-corba is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-corba is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-jaxp was given.
 if test "${with_override_jaxp+set}" = set; then :
-  withval=$with_override_jaxp;
-fi
+  withval=$with_override_jaxp; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jaxp is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jaxp is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-jaxws was given.
 if test "${with_override_jaxws+set}" = set; then :
-  withval=$with_override_jaxws;
-fi
+  withval=$with_override_jaxws; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jaxws is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jaxws is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-hotspot was given.
 if test "${with_override_hotspot+set}" = set; then :
-  withval=$with_override_hotspot;
-fi
+  withval=$with_override_hotspot; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-hotspot is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-hotspot is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-nashorn was given.
 if test "${with_override_nashorn+set}" = set; then :
-  withval=$with_override_nashorn;
-fi
+  withval=$with_override_nashorn; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-nashorn is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-nashorn is deprecated and will be ignored." >&2;}
+fi
+
 
 
 
 # Check whether --with-override-jdk was given.
 if test "${with_override_jdk+set}" = set; then :
-  withval=$with_override_jdk;
-fi
-
-
-  if test "x$with_override_langtools" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_langtools"
-    LANGTOOLS_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $LANGTOOLS_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override langtools with a full langtools repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if langtools should be overridden" >&5
-$as_echo_n "checking if langtools should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $LANGTOOLS_TOPDIR" >&5
-$as_echo "yes with $LANGTOOLS_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_corba" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_corba"
-    CORBA_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $CORBA_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override corba with a full corba repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if corba should be overridden" >&5
-$as_echo_n "checking if corba should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $CORBA_TOPDIR" >&5
-$as_echo "yes with $CORBA_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_jaxp" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jaxp"
-    JAXP_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JAXP_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override jaxp with a full jaxp repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if jaxp should be overridden" >&5
-$as_echo_n "checking if jaxp should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JAXP_TOPDIR" >&5
-$as_echo "yes with $JAXP_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_jaxws" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jaxws"
-    JAXWS_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JAXWS_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override jaxws with a full jaxws repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if jaxws should be overridden" >&5
-$as_echo_n "checking if jaxws should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JAXWS_TOPDIR" >&5
-$as_echo "yes with $JAXWS_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_hotspot" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_hotspot"
-    HOTSPOT_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $HOTSPOT_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override hotspot with a full hotspot repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if hotspot should be overridden" >&5
-$as_echo_n "checking if hotspot should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $HOTSPOT_TOPDIR" >&5
-$as_echo "yes with $HOTSPOT_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_nashorn" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_nashorn"
-    NASHORN_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $NASHORN_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override nashorn with a full nashorn repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if nashorn should be overridden" >&5
-$as_echo_n "checking if nashorn should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $NASHORN_TOPDIR" >&5
-$as_echo "yes with $NASHORN_TOPDIR" >&6; }
-  fi
-  if test "x$with_override_jdk" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jdk"
-    JDK_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JDK_TOPDIR/make/Makefile; then
-      as_fn_error $? "You have to override JDK with a full JDK repo!" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if JDK should be overridden" >&5
-$as_echo_n "checking if JDK should be overridden... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes with $JDK_TOPDIR" >&5
-$as_echo "yes with $JDK_TOPDIR" >&6; }
-  fi
+  withval=$with_override_jdk; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-override-jdk is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-override-jdk is deprecated and will be ignored." >&2;}
+fi
+
+
 
 
   BUILD_OUTPUT="$OUTPUT_ROOT"
@@ -45118,8 +44953,6 @@
     JDKLIB_LIBS="-ljava -ljvm"
     if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
       JDKLIB_LIBS="$JDKLIB_LIBS -lc"
-    elif test "x$TOOLCHAIN_TYPE" = xxlc; then
-      JDKLIB_LIBS="$JDKLIB_LIBS -liconv"
     fi
   fi
 
@@ -45305,6 +45138,15 @@
     as_fn_error $? "--enable-warnings-as-errors accepts no argument" "$LINENO" 5
   fi
 
+  if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
+    # Set legacy hotspot variable
+    HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
+  else
+    HOTSPOT_SET_WARNINGS_AS_ERRORS=""
+  fi
+
+
+
 
   case "${TOOLCHAIN_TYPE}" in
     microsoft)
--- a/common/autoconf/hotspot-spec.gmk.in	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/hotspot-spec.gmk.in	Wed Jul 05 20:58:59 2017 +0200
@@ -33,6 +33,7 @@
 # Additional legacy variables defined for Hotspot
 
 @SET_OPENJDK@
+@HOTSPOT_SET_WARNINGS_AS_ERRORS@
 
 # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
 @BUILD_HEADLESS@
--- a/common/autoconf/source-dirs.m4	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/source-dirs.m4	Wed Jul 05 20:58:59 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,7 @@
 
 AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
 [
-  # Where are the sources. Any of these can be overridden
-  # using --with-override-corba and the likes.
+  # Where are the sources.
   LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
   CORBA_TOPDIR="$SRC_ROOT/corba"
   JAXP_TOPDIR="$SRC_ROOT/jaxp"
@@ -43,216 +42,20 @@
   AC_SUBST(JDK_TOPDIR)
 ])
 
-
 AC_DEFUN_ONCE([SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS],
 [
-
-  ###############################################################################
-  #
-  # Pickup additional source for a component from outside of the source root
-  # or override source for a component.
-  #
-  AC_ARG_WITH(add-source-root, [AS_HELP_STRING([--with-add-source-root],
-      [for each and every source directory, look in this additional source root for
-      the same directory; if it exists and have files in it, include it in the build])])
-
-  AC_ARG_WITH(override-source-root, [AS_HELP_STRING([--with-override-source-root],
-      [for each and every source directory, look in this override source root for
-      the same directory; if it exists, use that directory instead and
-      ignore the directory in the original source root])])
-
-  AC_ARG_WITH(adds-and-overrides, [AS_HELP_STRING([--with-adds-and-overrides],
-      [use the subdirs 'adds' and 'overrides' in the specified directory as
-      add-source-root and override-source-root])])
-
-  if test "x$with_adds_and_overrides" != x; then
-    with_add_source_root="$with_adds_and_overrides/adds"
-    with_override_source_root="$with_adds_and_overrides/overrides"
-  fi
-
-  if test "x$with_add_source_root" != x; then
-    if ! test -d $with_add_source_root; then
-      AC_MSG_ERROR([Trying to use a non-existant add-source-root $with_add_source_root])
-    fi
-    CURDIR="$PWD"
-    cd "$with_add_source_root"
-    ADD_SRC_ROOT="`pwd`"
-    cd "$CURDIR"
-    # Verify that the addon source root does not have any root makefiles.
-    # If it does, then it is usually an error, prevent this.
-    if test -f $with_add_source_root/langtools/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full langtools repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/corba/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full corba repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/jaxp/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full jaxp repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/jaxws/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full jaxws repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/hotspot/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/nashorn/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources.])
-    fi
-    if test -f $with_add_source_root/jdk/make/Makefile; then
-      AC_MSG_ERROR([Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources.])
-    fi
-  fi
-  AC_SUBST(ADD_SRC_ROOT)
-
-  if test "x$with_override_source_root" != x; then
-    if ! test -d $with_override_source_root; then
-      AC_MSG_ERROR([Trying to use a non-existant override-source-root $with_override_source_root])
-    fi
-    CURDIR="$PWD"
-    cd "$with_override_source_root"
-    OVERRIDE_SRC_ROOT="`pwd`"
-    cd "$CURDIR"
-    if test -f $with_override_source_root/langtools/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full langtools repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/corba/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full corba repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/jaxp/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full jaxp repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/jaxws/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full jaxws repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/hotspot/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/nashorn/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override.])
-    fi
-    if test -f $with_override_source_root/jdk/make/Makefile; then
-      AC_MSG_ERROR([Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override.])
-    fi
-  fi
-  AC_SUBST(OVERRIDE_SRC_ROOT)
+  # This feature is no longer supported.
 
-  ###############################################################################
-  #
-  # Override a repo completely, this is used for example when you have 3 small
-  # development sandboxes of the langtools sources and want to avoid having 3 full
-  # OpenJDK sources checked out on disk.
-  #
-  # Assuming that the 3 langtools sandboxes are located here:
-  # /home/fredrik/sandbox1/langtools
-  # /home/fredrik/sandbox2/langtools
-  # /home/fredrik/sandbox3/langtools
-  #
-  # From the source root you create build subdirs manually:
-  #     mkdir -p build1 build2 build3
-  # in each build directory run:
-  #     (cd build1 && ../configure --with-override-langtools=/home/fredrik/sandbox1 && make)
-  #     (cd build2 && ../configure --with-override-langtools=/home/fredrik/sandbox2 && make)
-  #     (cd build3 && ../configure --with-override-langtools=/home/fredrik/sandbox3 && make)
-  #
-
-  AC_ARG_WITH(override-langtools, [AS_HELP_STRING([--with-override-langtools],
-      [use this langtools dir for the build])])
-
-  AC_ARG_WITH(override-corba, [AS_HELP_STRING([--with-override-corba],
-      [use this corba dir for the build])])
-
-  AC_ARG_WITH(override-jaxp, [AS_HELP_STRING([--with-override-jaxp],
-      [use this jaxp dir for the build])])
-
-  AC_ARG_WITH(override-jaxws, [AS_HELP_STRING([--with-override-jaxws],
-      [use this jaxws dir for the build])])
-
-  AC_ARG_WITH(override-hotspot, [AS_HELP_STRING([--with-override-hotspot],
-      [use this hotspot dir for the build])])
-
-  AC_ARG_WITH(override-nashorn, [AS_HELP_STRING([--with-override-nashorn],
-      [use this nashorn dir for the build])])
-
-  AC_ARG_WITH(override-jdk, [AS_HELP_STRING([--with-override-jdk],
-      [use this jdk dir for the build])])
-
-  if test "x$with_override_langtools" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_langtools"
-    LANGTOOLS_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $LANGTOOLS_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override langtools with a full langtools repo!])
-    fi
-    AC_MSG_CHECKING([if langtools should be overridden])
-    AC_MSG_RESULT([yes with $LANGTOOLS_TOPDIR])
-  fi
-  if test "x$with_override_corba" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_corba"
-    CORBA_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $CORBA_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override corba with a full corba repo!])
-    fi
-    AC_MSG_CHECKING([if corba should be overridden])
-    AC_MSG_RESULT([yes with $CORBA_TOPDIR])
-  fi
-  if test "x$with_override_jaxp" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jaxp"
-    JAXP_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JAXP_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override jaxp with a full jaxp repo!])
-    fi
-    AC_MSG_CHECKING([if jaxp should be overridden])
-    AC_MSG_RESULT([yes with $JAXP_TOPDIR])
-  fi
-  if test "x$with_override_jaxws" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jaxws"
-    JAXWS_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JAXWS_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override jaxws with a full jaxws repo!])
-    fi
-    AC_MSG_CHECKING([if jaxws should be overridden])
-    AC_MSG_RESULT([yes with $JAXWS_TOPDIR])
-  fi
-  if test "x$with_override_hotspot" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_hotspot"
-    HOTSPOT_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $HOTSPOT_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override hotspot with a full hotspot repo!])
-    fi
-    AC_MSG_CHECKING([if hotspot should be overridden])
-    AC_MSG_RESULT([yes with $HOTSPOT_TOPDIR])
-  fi
-  if test "x$with_override_nashorn" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_nashorn"
-    NASHORN_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $NASHORN_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override nashorn with a full nashorn repo!])
-    fi
-    AC_MSG_CHECKING([if nashorn should be overridden])
-    AC_MSG_RESULT([yes with $NASHORN_TOPDIR])
-  fi
-  if test "x$with_override_jdk" != x; then
-    CURDIR="$PWD"
-    cd "$with_override_jdk"
-    JDK_TOPDIR="`pwd`"
-    cd "$CURDIR"
-    if ! test -f $JDK_TOPDIR/make/Makefile; then
-      AC_MSG_ERROR([You have to override JDK with a full JDK repo!])
-    fi
-    AC_MSG_CHECKING([if JDK should be overridden])
-    AC_MSG_RESULT([yes with $JDK_TOPDIR])
-  fi
+  BASIC_DEPRECATED_ARG_WITH(add-source-root)
+  BASIC_DEPRECATED_ARG_WITH(override-source-root)
+  BASIC_DEPRECATED_ARG_WITH(adds-and-overrides)
+  BASIC_DEPRECATED_ARG_WITH(override-langtools)
+  BASIC_DEPRECATED_ARG_WITH(override-corba)
+  BASIC_DEPRECATED_ARG_WITH(override-jaxp)
+  BASIC_DEPRECATED_ARG_WITH(override-jaxws)
+  BASIC_DEPRECATED_ARG_WITH(override-hotspot)
+  BASIC_DEPRECATED_ARG_WITH(override-nashorn)
+  BASIC_DEPRECATED_ARG_WITH(override-jdk)
 ])
 
 AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
--- a/common/autoconf/spec.gmk.in	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 20:58:59 2017 +0200
@@ -113,10 +113,6 @@
 SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
 SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
 
-# Paths to the source code
-ADD_SRC_ROOT:=@ADD_SRC_ROOT@
-OVERRIDE_SRC_ROOT:=@OVERRIDE_SRC_ROOT@
-
 # The top-level directory of the forest (SRC_ROOT is a traditional alias)
 TOPDIR:=@TOPDIR@
 # These two versions of TOPDIR are used in string comparisons
@@ -548,34 +544,6 @@
 MSVCR_DLL:=@MSVCR_DLL@
 MSVCP_DLL:=@MSVCP_DLL@
 
-
-# ADD_SRCS takes a single argument with source roots
-# and appends any corresponding source roots found
-# below --with-add-source-root and below
-# --with-override-source-root. It is the responsibility
-# of the next macro to get rid of superfluous files.
-ADD_SRCS=$1
-ifneq (,$(ADD_SRC_ROOT))
-  # Append wildcard rule to pickup any matching source roots found below ADD_SRC_ROOT
-  ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(ADD_SRC_ROOT),$1))
-endif
-ifneq (,$(OVERRIDE_SRC_ROOT))
-  # Append wildcard rule to pickup any matching source roots found below OVERRIDE_SRC_ROOT
-  ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(OVERRIDE_SRC_ROOT),$1))
-endif
-
-# OVR_SRCS creates a filter expression to filter out sources in
-# the original source directory that lie inside directories below
-# --with-override-source-root.
-# Use := here since we want to scan for these files here. To avoid recomputation later.
-# We cannot do the scan in configure, since that would force us to rerun configure when
-# we add overridden sources.
-ifneq (,$(OVERRIDE_SRC_ROOT))
-  OVR_SRCS:=$(addsuffix %,$(subst $(OVERRIDE_SRC_ROOT),$(SRC_ROOT),$(sort $(dir $(shell $(FIND) $(OVERRIDE_SRC_ROOT) -type f)))))
-else
-  OVR_SRCS:=
-endif
-
 ####################################################
 #
 # INSTALLATION
--- a/common/bin/compare.sh	Thu Nov 05 13:42:47 2015 -0800
+++ b/common/bin/compare.sh	Wed Jul 05 20:58:59 2017 +0200
@@ -989,7 +989,7 @@
     fi
 fi
 
-THIS="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
+THIS="$SCRIPT_DIR"
 echo "$THIS"
 THIS_SCRIPT="$0"
 
--- a/hotspot/.hgtags	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 20:58:59 2017 +0200
@@ -493,3 +493,4 @@
 bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
 20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89
 7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90
+3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91
--- a/hotspot/make/bsd/makefiles/gcc.make	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/make/bsd/makefiles/gcc.make	Wed Jul 05 20:58:59 2017 +0200
@@ -97,6 +97,7 @@
   # prints the numbers (e.g. "2.95", "3.2.1")
   CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
   CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+  CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
 endif
 
 ifeq ($(USE_CLANG), true)
@@ -326,6 +327,10 @@
     $(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
   endif
 else
+  # Do not allow GCC 4.1.1
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+    $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+  endif
   # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
     OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -109,7 +109,11 @@
 	($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
 	    for i in $$($(LS)); do \
 	      c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
-	      $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \
+	      $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c.tmp; \
+	    done)
+	($(CD) $(GENSRC_DIR)/META-INF/services && \
+	    for i in $$($(LS) *.tmp); do \
+	      $(MV) $$i $${i%.tmp}; \
 	    done)
 	$(TOUCH) $@
 
--- a/hotspot/make/linux/makefiles/gcc.make	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/make/linux/makefiles/gcc.make	Wed Jul 05 20:58:59 2017 +0200
@@ -60,6 +60,7 @@
   # prints the numbers (e.g. "2.95", "3.2.1")
   CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
   CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+  CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
 endif
 
 ifeq ($(USE_CLANG), true)
@@ -264,6 +265,10 @@
     OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
   endif
 else
+  # Do not allow GCC 4.1.1
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+    $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+  endif
   # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
     OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/make/solaris/makefiles/gcc.make	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/make/solaris/makefiles/gcc.make	Wed Jul 05 20:58:59 2017 +0200
@@ -39,6 +39,7 @@
 # prints the numbers (e.g. "2.95", "3.2.1")
 CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
 CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
 
 # Check for the versions of C++ and C compilers ($CXX and $CC) used.
 
@@ -160,6 +161,10 @@
     OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
   endif
 else
+  # Do not allow GCC 4.1.1
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
+    $(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
+  endif
   # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
     OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -59,9 +59,9 @@
 #define DEFAULT_STACK_RED_PAGES (1)
 #define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
 
-#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
-#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
-#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+#define MIN_STACK_YELLOW_PAGES 1
+#define MIN_STACK_RED_PAGES    1
+#define MIN_STACK_SHADOW_PAGES 1
 
 define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
 define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -1777,7 +1777,7 @@
   const Register obj_reg  = r19;  // Will contain the oop
   const Register lock_reg = r13;  // Address of compiler lock object (BasicLock)
   const Register old_hdr  = r13;  // value of old header at unlock time
-  const Register tmp = c_rarg3;
+  const Register tmp = lr;
 
   Label slow_path_lock;
   Label lock_done;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -1539,7 +1539,6 @@
   emit_arith(0x3B, 0xC0, dst, src);
 }
 
-
 void Assembler::cmpl(Register dst, Address  src) {
   InstructionMark im(this);
   prefix(src, dst);
@@ -2125,6 +2124,16 @@
   emit_operand(dst, src);
 }
 
+void Assembler::movddup(XMMRegister dst, XMMRegister src) {
+  _instruction_uses_vl = true;
+  NOT_LP64(assert(VM_Version::supports_sse3(), ""));
+  int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false, VEX_OPCODE_0F,
+                                      /* rex_w */ VM_Version::supports_evex(), AVX_128bit, /* legacy_mode */ false);
+  emit_int8(0x12);
+  emit_int8(0xC0 | encode);
+
+}
+
 void Assembler::kmovql(KRegister dst, KRegister src) {
   NOT_LP64(assert(VM_Version::supports_evex(), ""));
   int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
@@ -3403,6 +3412,20 @@
   }
 }
 
+void Assembler::rcpps(XMMRegister dst, XMMRegister src) {
+  NOT_LP64(assert(VM_Version::supports_sse(), ""));
+  int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
+  emit_int8(0x53);
+  emit_int8(0xC0 | encode);
+}
+
+void Assembler::rcpss(XMMRegister dst, XMMRegister src) {
+  NOT_LP64(assert(VM_Version::supports_sse(), ""));
+  int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
+  emit_int8(0x53);
+  emit_int8(0xC0 | encode);
+}
+
 void Assembler::rdtsc() {
   emit_int8((unsigned char)0x0F);
   emit_int8((unsigned char)0x31);
@@ -6326,6 +6349,26 @@
   emit_int8((unsigned char)(0xC0 | encode));
 }
 
+void Assembler::cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) {
+  assert(VM_Version::supports_avx(), "");
+  assert(!VM_Version::supports_evex(), "");
+  int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F, /* no_mask_reg */ false);
+  emit_int8((unsigned char)0xC2);
+  emit_int8((unsigned char)(0xC0 | encode));
+  emit_int8((unsigned char)(0xF & cop));
+}
+
+void Assembler::vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len) {
+  assert(VM_Version::supports_avx(), "");
+  assert(!VM_Version::supports_evex(), "");
+  int encode = vex_prefix_and_encode(dst, nds, src1, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* no_mask_reg */ false);
+  emit_int8((unsigned char)0x4B);
+  emit_int8((unsigned char)(0xC0 | encode));
+  int src2_enc = src2->encoding();
+  emit_int8((unsigned char)(0xF0 & src2_enc<<4));
+}
+
+
 #ifndef _LP64
 
 void Assembler::incl(Register dst) {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -1504,6 +1504,8 @@
   void movb(Address dst, int imm8);
   void movb(Register dst, Address src);
 
+  void movddup(XMMRegister dst, XMMRegister src);
+
   void kmovql(KRegister dst, KRegister src);
   void kmovql(KRegister dst, Register src);
   void kmovdl(KRegister dst, Register src);
@@ -1768,6 +1770,10 @@
 
   void rcrq(Register dst, int imm8);
 
+  void rcpps(XMMRegister dst, XMMRegister src);
+
+  void rcpss(XMMRegister dst, XMMRegister src);
+
   void rdtsc();
 
   void ret(int imm16);
@@ -2141,6 +2147,11 @@
   // runtime code and native libraries.
   void vzeroupper();
 
+  // AVX support for vectorized conditional move (double). The following two instructions used only coupled.
+  void cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len);
+  void vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len);
+
+
  protected:
   // Next instructions require address alignment 16 bytes SSE mode.
   // They should be called only from corresponding MacroAssembler instructions.
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2440,7 +2440,6 @@
   } else if (value->is_double_fpu()) {
     assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
     switch(code) {
-      case lir_log   : __ flog() ; break;
       case lir_log10 : __ flog10() ; break;
       case lir_abs   : __ fabs() ; break;
       case lir_sqrt  : __ fsqrt(); break;
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -809,8 +809,8 @@
 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
   assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
 
-  if (x->id() == vmIntrinsics::_dexp) {
-    do_ExpIntrinsic(x);
+  if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog) {
+    do_LibmIntrinsic(x);
     return;
   }
 
@@ -822,7 +822,6 @@
       case vmIntrinsics::_dsin:
       case vmIntrinsics::_dcos:
       case vmIntrinsics::_dtan:
-      case vmIntrinsics::_dlog:
       case vmIntrinsics::_dlog10:
       case vmIntrinsics::_dpow:
         use_fpu = true;
@@ -873,7 +872,6 @@
     case vmIntrinsics::_dsin:   __ sin  (calc_input, calc_result, tmp1, tmp2);              break;
     case vmIntrinsics::_dcos:   __ cos  (calc_input, calc_result, tmp1, tmp2);              break;
     case vmIntrinsics::_dtan:   __ tan  (calc_input, calc_result, tmp1, tmp2);              break;
-    case vmIntrinsics::_dlog:   __ log  (calc_input, calc_result, tmp1);                    break;
     case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1);                    break;
     case vmIntrinsics::_dpow:   __ pow  (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
     default:                    ShouldNotReachHere();
@@ -884,7 +882,7 @@
   }
 }
 
-void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
+void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
   LIRItem value(x->argument_at(0), this);
   value.set_destroys_register();
 
@@ -900,13 +898,33 @@
 #ifndef _LP64
   LIR_Opr tmp = FrameMap::fpu0_double_opr;
   result_reg = tmp;
-  if (VM_Version::supports_sse2()) {
-    __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
-  } else {
-    __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+  switch(x->id()) {
+    case vmIntrinsics::_dexp:
+      if (VM_Version::supports_sse2()) {
+        __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+      } else {
+        __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+      }
+      break;
+    case vmIntrinsics::_dlog:
+      if (VM_Version::supports_sse2()) {
+        __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
+      }
+      else {
+        __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
+      }
+      break;
+    default:  ShouldNotReachHere();
   }
 #else
-  __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+  switch (x->id()) {
+    case vmIntrinsics::_dexp:
+      __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+      break;
+    case vmIntrinsics::_dlog:
+      __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
+      break;
+  }
 #endif
   __ move(result_reg, calc_result);
 }
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -786,7 +786,6 @@
       break;
     }
 
-    case lir_log:
     case lir_log10: {
       // log and log10 need one temporary fpu stack slot, so
       // there is one temporary registers stored in temp of the
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -132,10 +132,15 @@
         __ fabs();
         break;
     case Interpreter::java_lang_math_log:
-        __ flog();
-        // Store to stack to convert 80bit precision back to 64bits
-        __ push_fTOS();
-        __ pop_fTOS();
+        __ subptr(rsp, 2 * wordSize);
+        __ fstp_d(Address(rsp, 0));
+        if (VM_Version::supports_sse2()) {
+          __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
+        }
+        else {
+          __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
+        }
+        __ addptr(rsp, 2 * wordSize);
         break;
     case Interpreter::java_lang_math_log10:
         __ flog10();
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -253,6 +253,9 @@
   } else if (kind == Interpreter::java_lang_math_exp) {
     __ movdbl(xmm0, Address(rsp, wordSize));
     __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
+  } else if (kind == Interpreter::java_lang_math_log) {
+    __ movdbl(xmm0, Address(rsp, wordSize));
+    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
   } else {
     __ fld_d(Address(rsp, wordSize));
     switch (kind) {
@@ -268,9 +271,6 @@
       case Interpreter::java_lang_math_abs:
           __ fabs();
           break;
-      case Interpreter::java_lang_math_log:
-          __ flog();
-          break;
       case Interpreter::java_lang_math_log10:
           __ flog10();
           break;
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -56,6 +56,8 @@
   #define VIRTUAL virtual
 #endif
 
+#define COMMA ,
+
   VIRTUAL void call_VM_leaf_base(
     address entry_point,               // the entry point
     int     number_of_arguments        // the number of arguments to pop after the call
@@ -910,6 +912,11 @@
   void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
                 XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
                 Register rax, Register rcx, Register rdx, Register tmp);
+
+  void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+                XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+                Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2));
+
   void increase_precision();
   void restore_precision();
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -24,8 +24,19 @@
  *
  */
 
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "macroAssembler_x86.hpp"
+
+#ifdef _MSC_VER
+#define ALIGNED_(x) __declspec(align(x))
+#else
+#define ALIGNED_(x) __attribute__ ((aligned(x)))
+#endif
+
 /******************************************************************************/
-//                     ALGORITHM DESCRIPTION
+//                     ALGORITHM DESCRIPTION - EXP()
 //                     ---------------------
 //
 // Description:
@@ -58,18 +69,6 @@
 //
 /******************************************************************************/
 
-
-#include "precompiled.hpp"
-#include "asm/assembler.hpp"
-#include "asm/assembler.inline.hpp"
-#include "macroAssembler_x86.hpp"
-
-#ifdef _MSC_VER
-#define ALIGNED_(x) __declspec(align(x))
-#else
-#define ALIGNED_(x) __attribute__ ((aligned(x)))
-#endif
-
 #ifdef _LP64
 
 ALIGNED_(16) juint _cv[] =
@@ -409,6 +408,7 @@
   bind(B1_5);
   addq(rsp, 24);
 }
+
 #endif
 
 #ifndef _LP64
@@ -675,3 +675,614 @@
 }
 
 #endif
+
+/******************************************************************************/
+//                     ALGORITHM DESCRIPTION - LOG()
+//                     ---------------------
+//
+//    x=2^k * mx, mx in [1,2)
+//
+//    Get B~1/mx based on the output of rcpss instruction (B0)
+//    B = int((B0*2^7+0.5))/2^7
+//
+//    Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
+//
+//    Result:  k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6)  and
+//             p(r) is a degree 7 polynomial
+//             -log(B) read from data table (high, low parts)
+//             Result is formed from high and low parts
+//
+// Special cases:
+//  log(NaN) = quiet NaN, and raise invalid exception
+//  log(+INF) = that INF
+//  log(0) = -INF with divide-by-zero exception raised
+//  log(1) = +0
+//  log(x) = NaN with invalid exception raised if x < -0, including -INF
+//
+/******************************************************************************/
+
+#ifdef _LP64
+
+ALIGNED_(16) juint _L_tbl[] =
+{
+  0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
+  0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
+  0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
+  0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
+  0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
+  0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
+  0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
+  0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
+  0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
+  0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
+  0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
+  0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
+  0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
+  0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
+  0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
+  0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
+  0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
+  0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
+  0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
+  0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
+  0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
+  0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
+  0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
+  0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
+  0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
+  0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
+  0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
+  0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
+  0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
+  0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
+  0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
+  0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
+  0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
+  0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
+  0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
+  0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
+  0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
+  0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
+  0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
+  0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
+  0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
+  0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
+  0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
+  0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
+  0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
+  0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
+  0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
+  0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
+  0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
+  0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
+  0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
+  0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
+  0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
+  0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
+  0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
+  0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
+  0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
+  0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
+  0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
+  0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
+  0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
+  0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
+  0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
+  0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
+  0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
+  0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
+  0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
+  0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
+  0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
+  0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
+  0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
+  0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
+  0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
+  0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
+  0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
+  0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
+  0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
+  0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
+  0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
+  0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
+  0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
+  0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
+  0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
+  0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
+  0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
+  0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
+  0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
+  0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
+  0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
+  0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
+  0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
+  0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
+  0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
+  0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
+  0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
+  0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
+  0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
+  0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
+  0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
+  0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
+  0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
+  0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
+  0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+  0x80000000UL
+};
+
+ALIGNED_(16) juint _log2[] =
+{
+  0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
+};
+
+ALIGNED_(16) juint _coeff[] =
+{
+  0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
+  0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
+  0x00000000UL, 0xbfe00000UL
+};
+
+//registers,
+// input: xmm0
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+//          rax, rdx, rcx, r8, r11
+
+void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp1, Register tmp2) {
+  Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+  Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+  Label L_2TAG_PACKET_8_0_2;
+  Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
+
+  assert_different_registers(tmp1, tmp2, eax, ecx, edx);
+  jmp(start);
+  address L_tbl = (address)_L_tbl;
+  address log2 = (address)_log2;
+  address coeff = (address)_coeff;
+
+  bind(start);
+  subq(rsp, 24);
+  movsd(Address(rsp, 0), xmm0);
+  mov64(rax, 0x3ff0000000000000);
+  movdq(xmm2, rax);
+  mov64(rdx, 0x77f0000000000000);
+  movdq(xmm3, rdx);
+  movl(ecx, 32768);
+  movdl(xmm4, rcx);
+  mov64(tmp1, 0xffffe00000000000);
+  movdq(xmm5, tmp1);
+  movdqu(xmm1, xmm0);
+  pextrw(eax, xmm0, 3);
+  por(xmm0, xmm2);
+  movl(ecx, 16352);
+  psrlq(xmm0, 27);
+  lea(tmp2, ExternalAddress(L_tbl));
+  psrld(xmm0, 2);
+  rcpps(xmm0, xmm0);
+  psllq(xmm1, 12);
+  pshufd(xmm6, xmm5, 228);
+  psrlq(xmm1, 12);
+  subl(eax, 16);
+  cmpl(eax, 32736);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+
+  bind(L_2TAG_PACKET_1_0_2);
+  paddd(xmm0, xmm4);
+  por(xmm1, xmm3);
+  movdl(edx, xmm0);
+  psllq(xmm0, 29);
+  pand(xmm5, xmm1);
+  pand(xmm0, xmm6);
+  subsd(xmm1, xmm5);
+  mulpd(xmm5, xmm0);
+  andl(eax, 32752);
+  subl(eax, ecx);
+  cvtsi2sdl(xmm7, eax);
+  mulsd(xmm1, xmm0);
+  movq(xmm6, ExternalAddress(log2));       // 0xfefa3800UL, 0x3fa62e42UL
+  movdqu(xmm3, ExternalAddress(coeff));    // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
+  subsd(xmm5, xmm2);
+  andl(edx, 16711680);
+  shrl(edx, 12);
+  movdqu(xmm0, Address(tmp2, edx));
+  movdqu(xmm4, ExternalAddress(16 + coeff)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
+  addsd(xmm1, xmm5);
+  movdqu(xmm2, ExternalAddress(32 + coeff)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
+  mulsd(xmm6, xmm7);
+  movddup(xmm5, xmm1);
+  mulsd(xmm7, ExternalAddress(8 + log2));    // 0x93c76730UL, 0x3ceef357UL
+  mulsd(xmm3, xmm1);
+  addsd(xmm0, xmm6);
+  mulpd(xmm4, xmm5);
+  mulpd(xmm5, xmm5);
+  movddup(xmm6, xmm0);
+  addsd(xmm0, xmm1);
+  addpd(xmm4, xmm2);
+  mulpd(xmm3, xmm5);
+  subsd(xmm6, xmm0);
+  mulsd(xmm4, xmm1);
+  pshufd(xmm2, xmm0, 238);
+  addsd(xmm1, xmm6);
+  mulsd(xmm5, xmm5);
+  addsd(xmm7, xmm2);
+  addpd(xmm4, xmm3);
+  addsd(xmm1, xmm7);
+  mulpd(xmm4, xmm5);
+  addsd(xmm1, xmm4);
+  pshufd(xmm5, xmm4, 238);
+  addsd(xmm1, xmm5);
+  addsd(xmm0, xmm1);
+  jmp(B1_5);
+
+  bind(L_2TAG_PACKET_0_0_2);
+  movq(xmm0, Address(rsp, 0));
+  movq(xmm1, Address(rsp, 0));
+  addl(eax, 16);
+  cmpl(eax, 32768);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_2);
+  cmpl(eax, 16);
+  jcc(Assembler::below, L_2TAG_PACKET_3_0_2);
+
+  bind(L_2TAG_PACKET_4_0_2);
+  addsd(xmm0, xmm0);
+  jmp(B1_5);
+
+  bind(L_2TAG_PACKET_5_0_2);
+  jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
+  cmpl(edx, 0);
+  jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
+  jmp(L_2TAG_PACKET_6_0_2);
+
+  bind(L_2TAG_PACKET_3_0_2);
+  xorpd(xmm1, xmm1);
+  addsd(xmm1, xmm0);
+  movdl(edx, xmm1);
+  psrlq(xmm1, 32);
+  movdl(ecx, xmm1);
+  orl(edx, ecx);
+  cmpl(edx, 0);
+  jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
+  xorpd(xmm1, xmm1);
+  movl(eax, 18416);
+  pinsrw(xmm1, eax, 3);
+  mulsd(xmm0, xmm1);
+  movdqu(xmm1, xmm0);
+  pextrw(eax, xmm0, 3);
+  por(xmm0, xmm2);
+  psrlq(xmm0, 27);
+  movl(ecx, 18416);
+  psrld(xmm0, 2);
+  rcpps(xmm0, xmm0);
+  psllq(xmm1, 12);
+  pshufd(xmm6, xmm5, 228);
+  psrlq(xmm1, 12);
+  jmp(L_2TAG_PACKET_1_0_2);
+
+  bind(L_2TAG_PACKET_2_0_2);
+  movdl(edx, xmm1);
+  psrlq(xmm1, 32);
+  movdl(ecx, xmm1);
+  addl(ecx, ecx);
+  cmpl(ecx, -2097152);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_5_0_2);
+  orl(edx, ecx);
+  cmpl(edx, 0);
+  jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
+
+  bind(L_2TAG_PACKET_6_0_2);
+  xorpd(xmm1, xmm1);
+  xorpd(xmm0, xmm0);
+  movl(eax, 32752);
+  pinsrw(xmm1, eax, 3);
+  mulsd(xmm0, xmm1);
+  movl(Address(rsp, 16), 3);
+  jmp(L_2TAG_PACKET_8_0_2);
+  bind(L_2TAG_PACKET_7_0_2);
+  xorpd(xmm1, xmm1);
+  xorpd(xmm0, xmm0);
+  movl(eax, 49136);
+  pinsrw(xmm0, eax, 3);
+  divsd(xmm0, xmm1);
+  movl(Address(rsp, 16), 2);
+
+  bind(L_2TAG_PACKET_8_0_2);
+  movq(Address(rsp, 8), xmm0);
+
+  bind(B1_3);
+  movq(xmm0, Address(rsp, 8));
+
+  bind(B1_5);
+  addq(rsp, 24);
+}
+
+#endif
+
+#ifndef _LP64
+
+ALIGNED_(16) juint _static_const_table_log[] =
+{
+  0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
+  0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
+  0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
+  0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
+  0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
+  0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
+  0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
+  0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
+  0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
+  0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
+  0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
+  0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
+  0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
+  0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
+  0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
+  0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
+  0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
+  0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
+  0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
+  0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
+  0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
+  0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
+  0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
+  0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
+  0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
+  0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
+  0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
+  0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
+  0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
+  0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
+  0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
+  0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
+  0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
+  0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
+  0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
+  0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
+  0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
+  0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
+  0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
+  0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
+  0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
+  0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
+  0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
+  0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
+  0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
+  0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
+  0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
+  0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
+  0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
+  0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
+  0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
+  0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
+  0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
+  0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
+  0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
+  0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
+  0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
+  0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
+  0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
+  0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
+  0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
+  0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
+  0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
+  0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
+  0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
+  0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
+  0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
+  0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
+  0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
+  0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
+  0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
+  0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
+  0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
+  0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
+  0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
+  0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
+  0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
+  0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
+  0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
+  0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
+  0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
+  0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
+  0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
+  0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
+  0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
+  0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
+  0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
+  0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
+  0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
+  0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
+  0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
+  0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
+  0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
+  0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
+  0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
+  0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
+  0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
+  0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
+  0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
+  0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
+  0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
+  0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
+  0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+  0x80000000UL, 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL,
+  0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
+  0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
+  0x00000000UL, 0xbfe00000UL, 0x00000000UL, 0xffffe000UL, 0x00000000UL,
+  0xffffe000UL
+};
+//registers,
+// input: xmm0
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+//          rax, rdx, rcx, rbx (tmp)
+
+void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
+  Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+  Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+  Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2;
+  Label L_2TAG_PACKET_10_0_2, start;
+
+  assert_different_registers(tmp, eax, ecx, edx);
+  jmp(start);
+  address static_const_table = (address)_static_const_table_log;
+
+  bind(start);
+  subl(rsp, 104);
+  movl(Address(rsp, 40), tmp);
+  lea(tmp, ExternalAddress(static_const_table));
+  xorpd(xmm2, xmm2);
+  movl(eax, 16368);
+  pinsrw(xmm2, eax, 3);
+  xorpd(xmm3, xmm3);
+  movl(edx, 30704);
+  pinsrw(xmm3, edx, 3);
+  movsd(xmm0, Address(rsp, 112));
+  movapd(xmm1, xmm0);
+  movl(ecx, 32768);
+  movdl(xmm4, ecx);
+  movsd(xmm5, Address(tmp, 2128));         // 0x00000000UL, 0xffffe000UL
+  pextrw(eax, xmm0, 3);
+  por(xmm0, xmm2);
+  psllq(xmm0, 5);
+  movl(ecx, 16352);
+  psrlq(xmm0, 34);
+  rcpss(xmm0, xmm0);
+  psllq(xmm1, 12);
+  pshufd(xmm6, xmm5, 228);
+  psrlq(xmm1, 12);
+  subl(eax, 16);
+  cmpl(eax, 32736);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+
+  bind(L_2TAG_PACKET_1_0_2);
+  paddd(xmm0, xmm4);
+  por(xmm1, xmm3);
+  movdl(edx, xmm0);
+  psllq(xmm0, 29);
+  pand(xmm5, xmm1);
+  pand(xmm0, xmm6);
+  subsd(xmm1, xmm5);
+  mulpd(xmm5, xmm0);
+  andl(eax, 32752);
+  subl(eax, ecx);
+  cvtsi2sdl(xmm7, eax);
+  mulsd(xmm1, xmm0);
+  movsd(xmm6, Address(tmp, 2064));         // 0xfefa3800UL, 0x3fa62e42UL
+  movdqu(xmm3, Address(tmp, 2080));        // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
+  subsd(xmm5, xmm2);
+  andl(edx, 16711680);
+  shrl(edx, 12);
+  movdqu(xmm0, Address(tmp, edx));
+  movdqu(xmm4, Address(tmp, 2096));        // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
+  addsd(xmm1, xmm5);
+  movdqu(xmm2, Address(tmp, 2112));        // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
+  mulsd(xmm6, xmm7);
+  pshufd(xmm5, xmm1, 68);
+  mulsd(xmm7, Address(tmp, 2072));         // 0x93c76730UL, 0x3ceef357UL, 0x92492492UL, 0x3fc24924UL
+  mulsd(xmm3, xmm1);
+  addsd(xmm0, xmm6);
+  mulpd(xmm4, xmm5);
+  mulpd(xmm5, xmm5);
+  pshufd(xmm6, xmm0, 228);
+  addsd(xmm0, xmm1);
+  addpd(xmm4, xmm2);
+  mulpd(xmm3, xmm5);
+  subsd(xmm6, xmm0);
+  mulsd(xmm4, xmm1);
+  pshufd(xmm2, xmm0, 238);
+  addsd(xmm1, xmm6);
+  mulsd(xmm5, xmm5);
+  addsd(xmm7, xmm2);
+  addpd(xmm4, xmm3);
+  addsd(xmm1, xmm7);
+  mulpd(xmm4, xmm5);
+  addsd(xmm1, xmm4);
+  pshufd(xmm5, xmm4, 238);
+  addsd(xmm1, xmm5);
+  addsd(xmm0, xmm1);
+  jmp(L_2TAG_PACKET_2_0_2);
+
+  bind(L_2TAG_PACKET_0_0_2);
+  movsd(xmm0, Address(rsp, 112));
+  movdqu(xmm1, xmm0);
+  addl(eax, 16);
+  cmpl(eax, 32768);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_3_0_2);
+  cmpl(eax, 16);
+  jcc(Assembler::below, L_2TAG_PACKET_4_0_2);
+
+  bind(L_2TAG_PACKET_5_0_2);
+  addsd(xmm0, xmm0);
+  jmp(L_2TAG_PACKET_2_0_2);
+
+  bind(L_2TAG_PACKET_6_0_2);
+  jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
+  cmpl(edx, 0);
+  jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
+  jmp(L_2TAG_PACKET_7_0_2);
+
+  bind(L_2TAG_PACKET_3_0_2);
+  movdl(edx, xmm1);
+  psrlq(xmm1, 32);
+  movdl(ecx, xmm1);
+  addl(ecx, ecx);
+  cmpl(ecx, -2097152);
+  jcc(Assembler::aboveEqual, L_2TAG_PACKET_6_0_2);
+  orl(edx, ecx);
+  cmpl(edx, 0);
+  jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
+
+  bind(L_2TAG_PACKET_7_0_2);
+  xorpd(xmm1, xmm1);
+  xorpd(xmm0, xmm0);
+  movl(eax, 32752);
+  pinsrw(xmm1, eax, 3);
+  movl(edx, 3);
+  mulsd(xmm0, xmm1);
+
+  bind(L_2TAG_PACKET_9_0_2);
+  movsd(Address(rsp, 0), xmm0);
+  movsd(xmm0, Address(rsp, 112));
+  fld_d(Address(rsp, 0));
+  jmp(L_2TAG_PACKET_10_0_2);
+
+  bind(L_2TAG_PACKET_8_0_2);
+  xorpd(xmm1, xmm1);
+  xorpd(xmm0, xmm0);
+  movl(eax, 49136);
+  pinsrw(xmm0, eax, 3);
+  divsd(xmm0, xmm1);
+  movl(edx, 2);
+  jmp(L_2TAG_PACKET_9_0_2);
+
+  bind(L_2TAG_PACKET_4_0_2);
+  movdl(edx, xmm1);
+  psrlq(xmm1, 32);
+  movdl(ecx, xmm1);
+  orl(edx, ecx);
+  cmpl(edx, 0);
+  jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
+  xorpd(xmm1, xmm1);
+  movl(eax, 18416);
+  pinsrw(xmm1, eax, 3);
+  mulsd(xmm0, xmm1);
+  movapd(xmm1, xmm0);
+  pextrw(eax, xmm0, 3);
+  por(xmm0, xmm2);
+  psllq(xmm0, 5);
+  movl(ecx, 18416);
+  psrlq(xmm0, 34);
+  rcpss(xmm0, xmm0);
+  psllq(xmm1, 12);
+  pshufd(xmm6, xmm5, 228);
+  psrlq(xmm1, 12);
+  jmp(L_2TAG_PACKET_1_0_2);
+
+  bind(L_2TAG_PACKET_2_0_2);
+  movsd(Address(rsp, 24), xmm0);
+  fld_d(Address(rsp, 24));
+
+  bind(L_2TAG_PACKET_10_0_2);
+  movl(tmp, Address(rsp, 40));
+}
+
+#endif
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2095,14 +2095,6 @@
 
   void generate_math_stubs() {
     {
-      StubCodeMark mark(this, "StubRoutines", "log");
-      StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
-
-      __ fld_d(Address(rsp, 4));
-      __ flog();
-      __ ret(0);
-    }
-    {
       StubCodeMark mark(this, "StubRoutines", "log10");
       StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
 
@@ -3065,6 +3057,32 @@
 
   }
 
+ address generate_libmLog() {
+   address start = __ pc();
+
+   const XMMRegister x0 = xmm0;
+   const XMMRegister x1 = xmm1;
+   const XMMRegister x2 = xmm2;
+   const XMMRegister x3 = xmm3;
+
+   const XMMRegister x4 = xmm4;
+   const XMMRegister x5 = xmm5;
+   const XMMRegister x6 = xmm6;
+   const XMMRegister x7 = xmm7;
+
+   const Register tmp = rbx;
+
+   BLOCK_COMMENT("Entry:");
+   __ enter(); // required for proper stackwalking of RuntimeStub frame
+   __ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
+   __ leave(); // required for proper stackwalking of RuntimeStub frame
+   __ ret(0);
+
+   return start;
+
+ }
+
+
 
   // Safefetch stubs.
   void generate_safefetch(const char* name, int size, address* entry,
@@ -3288,6 +3306,7 @@
     }
     if (VM_Version::supports_sse2()) {
       StubRoutines::_dexp = generate_libmExp();
+      StubRoutines::_dlog = generate_libmLog();
     }
   }
 
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2974,19 +2974,6 @@
 
   void generate_math_stubs() {
     {
-      StubCodeMark mark(this, "StubRoutines", "log");
-      StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
-
-      __ subq(rsp, 8);
-      __ movdbl(Address(rsp, 0), xmm0);
-      __ fld_d(Address(rsp, 0));
-      __ flog();
-      __ fstp_d(Address(rsp, 0));
-      __ movdbl(xmm0, Address(rsp, 0));
-      __ addq(rsp, 8);
-      __ ret(0);
-    }
-    {
       StubCodeMark mark(this, "StubRoutines", "log10");
       StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
 
@@ -4187,15 +4174,58 @@
 
 #ifdef _WIN64
     // save the xmm registers which must be preserved 6-7
-    __ movdqu(xmm_save(6), as_XMMRegister(6));
-    __ movdqu(xmm_save(7), as_XMMRegister(7));
+    __ subptr(rsp, 4 * wordSize);
+    __ movdqu(Address(rsp, 0), xmm6);
+    __ movdqu(Address(rsp, 2 * wordSize), xmm7);
 #endif
       __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
 
 #ifdef _WIN64
     // restore xmm regs belonging to calling function
-    __ movdqu(as_XMMRegister(6), xmm_save(6));
-    __ movdqu(as_XMMRegister(7), xmm_save(7));
+      __ movdqu(xmm6, Address(rsp, 0));
+      __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+      __ addptr(rsp, 4 * wordSize);
+#endif
+
+    __ leave(); // required for proper stackwalking of RuntimeStub frame
+    __ ret(0);
+
+    return start;
+
+  }
+
+  address generate_libmLog() {
+    address start = __ pc();
+
+    const XMMRegister x0 = xmm0;
+    const XMMRegister x1 = xmm1;
+    const XMMRegister x2 = xmm2;
+    const XMMRegister x3 = xmm3;
+
+    const XMMRegister x4 = xmm4;
+    const XMMRegister x5 = xmm5;
+    const XMMRegister x6 = xmm6;
+    const XMMRegister x7 = xmm7;
+
+    const Register tmp1 = r11;
+    const Register tmp2 = r8;
+
+    BLOCK_COMMENT("Entry:");
+    __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+#ifdef _WIN64
+    // save the xmm registers which must be preserved 6-7
+    __ subptr(rsp, 4 * wordSize);
+    __ movdqu(Address(rsp, 0), xmm6);
+    __ movdqu(Address(rsp, 2 * wordSize), xmm7);
+#endif
+    __ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2);
+
+#ifdef _WIN64
+    // restore xmm regs belonging to calling function
+    __ movdqu(xmm6, Address(rsp, 0));
+    __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+    __ addptr(rsp, 4 * wordSize);
 #endif
 
     __ leave(); // required for proper stackwalking of RuntimeStub frame
@@ -4392,7 +4422,10 @@
       StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
       StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
     }
-    StubRoutines::_dexp = generate_libmExp();
+    if (VM_Version::supports_sse2()) {
+      StubRoutines::_dexp = generate_libmExp();
+      StubRoutines::_dlog = generate_libmLog();
+    }
   }
 
   void generate_all() {
--- a/hotspot/src/cpu/x86/vm/x86.ad	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86.ad	Wed Jul 05 20:58:59 2017 +0200
@@ -1707,6 +1707,10 @@
       if (!VM_Version::supports_cx8())
         ret_value = false;
       break;
+    case Op_CMoveVD:
+      if (UseAVX < 1 || UseAVX > 2)
+        ret_value = false;
+      break;
   }
 
   return ret_value;  // Per default match rules are supported.
@@ -2089,6 +2093,29 @@
   interface(REG_INTER);
 %}
 
+// Comparison Code for FP conditional move
+operand cmpOp_vcmppd() %{
+  match(Bool);
+
+  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
+            n->as_Bool()->_test._test != BoolTest::no_overflow);
+  format %{ "" %}
+  interface(COND_INTER) %{
+    equal        (0x0, "eq");
+    less         (0x1, "lt");
+    less_equal   (0x2, "le");
+    not_equal    (0xC, "ne");
+    greater_equal(0xD, "ge");
+    greater      (0xE, "gt");
+    //TODO cannot compile (adlc breaks) without two next lines with error:
+    // x86_64.ad(13987) Syntax Error: :In operand cmpOp_vcmppd: Do not support this encode constant: ' %{
+    // equal' for overflow.
+    overflow     (0x20, "o");  // not really supported by the instruction
+    no_overflow  (0x21, "no"); // not really supported by the instruction
+  %}
+%}
+
+
 // INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
 
 // ============================================================================
@@ -7393,6 +7420,22 @@
   ins_pipe( pipe_slow );
 %}
 
+instruct vcmov4D_reg(vecY dst, vecY src1, vecY src2, immI8 cop, cmpOp_vcmppd copnd) %{
+  predicate(UseAVX > 0 && UseAVX < 3 && n->as_Vector()->length() == 4);
+  match(Set dst (CMoveVD (Binary copnd cop) (Binary src1 src2)));
+  effect(TEMP dst, USE src1, USE src2);
+  format %{ "cmppd.$copnd  $dst, $src1, $src2  ! vcmovevd, cond=$cop\n\t"
+            "vpblendd $dst,$src1,$src2,$dst ! vcmovevd\n\t"
+         %}
+  ins_encode %{
+    int vector_len = 1;
+    int cond = (Assembler::Condition)($copnd$$cmpcode);
+    __ cmppd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cond, vector_len);
+    __ vpblendd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $dst$$XMMRegister, vector_len);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
 // --------------------------------- DIV --------------------------------------
 
 // Floats vector div
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 20:58:59 2017 +0200
@@ -9950,41 +9950,6 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct logDPR_reg(regDPR1 dst, regDPR1 src) %{
-  predicate (UseSSE<=1);
-  // The source Double operand on FPU stack
-  match(Set dst (LogD src));
-  // fldln2       ; push log_e(2) on the FPU stack; full 80-bit number
-  // fxch         ; swap ST(0) with ST(1)
-  // fyl2x        ; compute log_e(2) * log_2(x)
-  format %{ "FLDLN2 \t\t\t#Log_e\n\t"
-            "FXCH   \n\t"
-            "FYL2X  \t\t\t# Q=Log_e*Log_2(x)"
-         %}
-  ins_encode( Opcode(0xD9), Opcode(0xED),   // fldln2
-              Opcode(0xD9), Opcode(0xC9),   // fxch
-              Opcode(0xD9), Opcode(0xF1));  // fyl2x
-
-  ins_pipe( pipe_slow );
-%}
-
-instruct logD_reg(regD dst, regD src, eFlagsReg cr) %{
-  predicate (UseSSE>=2);
-  effect(KILL cr);
-  // The source and result Double operands in XMM registers
-  match(Set dst (LogD src));
-  // fldln2       ; push log_e(2) on the FPU stack; full 80-bit number
-  // fyl2x        ; compute log_e(2) * log_2(x)
-  format %{ "FLDLN2 \t\t\t#Log_e\n\t"
-            "FYL2X  \t\t\t# Q=Log_e*Log_2(x)"
-         %}
-  ins_encode( Opcode(0xD9), Opcode(0xED),   // fldln2
-              Push_SrcD(src),
-              Opcode(0xD9), Opcode(0xF1),   // fyl2x
-              Push_ResultD(dst));
-  ins_pipe( pipe_slow );
-%}
-
 //-------------Float Instructions-------------------------------
 // Float Math
 
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 20:58:59 2017 +0200
@@ -9870,21 +9870,6 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct logD_reg(regD dst) %{
-  // The source and result Double operands in XMM registers
-  match(Set dst (LogD dst));
-  // fldln2       ; push log_e(2) on the FPU stack; full 80-bit number
-  // fyl2x        ; compute log_e(2) * log_2(x)
-  format %{ "fldln2\t\t\t#Log_e\n\t"
-            "fyl2x\t\t\t# Q=Log_e*Log_2(x)\n\t"
-         %}
-  ins_encode( Opcode(0xD9), Opcode(0xED),   // fldln2
-              Push_SrcXD(dst),
-              Opcode(0xD9), Opcode(0xF1),   // fyl2x
-              Push_ResultXD(dst));
-  ins_pipe( pipe_slow );
-%}
-
 instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
   match(Set dst (PowD src0 src1));  // Raise src0 to the src1'th power
   effect(KILL rax, KILL rdx, KILL rcx, KILL cr);
--- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -60,7 +60,7 @@
 
 // ----------------------------------------------------------------------------
 
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
   ShouldNotReachHere(); // Only needed for COMPILER2.
   return NULL;
 }
--- a/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -59,11 +59,6 @@
   ShouldNotCallThis();
 }
 
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
-                                                       CodeBuffer*       dst) {
-  ShouldNotCallThis();
-}
-
 void metadata_Relocation::pd_fix_value(address x) {
   ShouldNotCallThis();
 }
--- a/hotspot/src/cpu/zero/vm/vm_version_zero.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/vm_version_zero.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -37,4 +37,5 @@
     warning("Unaligned memory access is not available on this CPU");
     FLAG_SET_DEFAULT(UseUnalignedAccesses, false);
   }
+  FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0);
 }
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -4006,7 +4006,6 @@
         strcmp(opType,"DivD")==0 ||
         strcmp(opType,"DivF")==0 ||
         strcmp(opType,"DivI")==0 ||
-        strcmp(opType,"LogD")==0 ||
         strcmp(opType,"Log10D")==0 ||
         strcmp(opType,"ModD")==0 ||
         strcmp(opType,"ModF")==0 ||
@@ -4141,6 +4140,7 @@
     "AddVB","AddVS","AddVI","AddVL","AddVF","AddVD",
     "SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
     "MulVS","MulVI","MulVL","MulVF","MulVD",
+    "CMoveVD",
     "DivVF","DivVD",
     "AbsVF","AbsVD",
     "NegVF","NegVD",
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -34,6 +34,7 @@
 #include "c1/c1_ValueStack.hpp"
 #include "code/debugInfoRec.hpp"
 #include "compiler/compileLog.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/sharedRuntime.hpp"
 
 typedef enum {
@@ -418,9 +419,9 @@
     exception_handler_table(),
     implicit_exception_table(),
     compiler(),
-    _env->comp_level(),
     has_unsafe_access(),
-    SharedRuntime::is_wide_vector(max_vector_size())
+    SharedRuntime::is_wide_vector(max_vector_size()),
+    directive()
   );
 }
 
@@ -445,7 +446,7 @@
     dependency_recorder()->assert_evol_method(method());
   }
 
-  if (method()->break_at_execute()) {
+  if (directive()->BreakAtCompileOption) {
     BREAKPOINT;
   }
 
@@ -534,9 +535,10 @@
 
 
 Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-                         int osr_bci, BufferBlob* buffer_blob)
+                         int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
 : _compiler(compiler)
 , _env(env)
+, _directive(directive)
 , _log(env->log())
 , _method(method)
 , _osr_bci(osr_bci)
@@ -587,7 +589,6 @@
   _env->set_compiler_data(NULL);
 }
 
-
 void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
 #ifndef PRODUCT
   if (PrintExceptionHandlers && Verbose) {
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -67,6 +67,7 @@
   int _next_id;
   int _next_block_id;
   AbstractCompiler*  _compiler;
+  DirectiveSet*      _directive;
   ciEnv*             _env;
   CompileLog*        _log;
   ciMethod*          _method;
@@ -118,7 +119,7 @@
  public:
   // creation
   Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-              int osr_bci, BufferBlob* buffer_blob);
+              int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
   ~Compilation();
 
 
@@ -128,6 +129,7 @@
 
   // accessors
   ciEnv* env() const                             { return _env; }
+  DirectiveSet* directive() const                { return _directive; }
   CompileLog* log() const                        { return _log; }
   AbstractCompiler* compiler() const             { return _compiler; }
   bool has_exception_handlers() const            { return _has_exception_handlers; }
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -238,7 +238,7 @@
   return true;
 }
 
-void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
+void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
   assert(buffer_blob != NULL, "Must exist");
   // invoke compilation
@@ -247,7 +247,7 @@
     // of Compilation to occur before we release the any
     // competing compiler thread
     ResourceMark rm;
-    Compilation c(this, env, method, entry_bci, buffer_blob);
+    Compilation c(this, env, method, entry_bci, buffer_blob, directive);
   }
 }
 
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_C1_C1_COMPILER_HPP
 
 #include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 // There is one instance of the Compiler per CompilerThread.
 
@@ -50,7 +51,7 @@
   virtual void initialize();
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
   // Print compilation timers and statistics
   virtual void print_timers();
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -3365,7 +3365,7 @@
 
 // negative filter: should callee NOT be inlined?  returns NULL, ok to inline, or rejection msg
 const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
-  if ( callee->should_not_inline())    return "disallowed by CompileCommand";
+  if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
   if ( callee->dont_inline())          return "don't inline by annotation";
   return NULL;
 }
@@ -3494,8 +3494,7 @@
   {
     VM_ENTRY_MARK;
     methodHandle mh(THREAD, callee->get_Method());
-    methodHandle ct(THREAD, method()->get_Method());
-    is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
+    is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
   }
 
   if (!is_available) {
@@ -3690,13 +3689,14 @@
   }
 
   // now perform tests that are based on flag settings
-  if (callee->force_inline() || callee->should_inline()) {
+  bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
+  if (callee->force_inline() || inlinee_by_directive) {
     if (inline_level() > MaxForceInlineLevel                    ) INLINE_BAILOUT("MaxForceInlineLevel");
     if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
 
     const char* msg = "";
     if (callee->force_inline())  msg = "force inline by annotation";
-    if (callee->should_inline()) msg = "force inline by CompileCommand";
+    if (inlinee_by_directive)    msg = "force inline by CompileCommand";
     print_inlining(callee, msg);
   } else {
     // use heuristic controls on inlining
@@ -4207,7 +4207,8 @@
     event.commit();
   }
 #endif // INCLUDE_TRACE
-  if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
+
+  if (!compilation()->directive()->PrintInliningOption) {
     return;
   }
   CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -731,7 +731,6 @@
     case lir_tan:
     case lir_sin:
     case lir_cos:
-    case lir_log:
     case lir_log10: {
       assert(op->as_Op2() != NULL, "must be");
       LIR_Op2* op2 = (LIR_Op2*)op;
@@ -1769,7 +1768,6 @@
      case lir_sin:                   s = "sin";           break;
      case lir_cos:                   s = "cos";           break;
      case lir_tan:                   s = "tan";           break;
-     case lir_log:                   s = "log";           break;
      case lir_log10:                 s = "log10";         break;
      case lir_pow:                   s = "pow";           break;
      case lir_logic_and:             s = "logic_and";     break;
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -959,7 +959,6 @@
       , lir_sin
       , lir_cos
       , lir_tan
-      , lir_log
       , lir_log10
       , lir_pow
       , lir_logic_and
@@ -2193,7 +2192,6 @@
 
   void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_abs , from, tmp, to)); }
   void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
-  void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_log,  from, LIR_OprFact::illegalOpr, to, tmp)); }
   void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)              { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
   void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
   void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -738,7 +738,6 @@
     case lir_sin:
     case lir_tan:
     case lir_cos:
-    case lir_log:
     case lir_log10:
     case lir_pow:
       intrinsic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -153,8 +153,13 @@
 
 // only the classes below belong in the same file
 class LIRGenerator: public InstructionVisitor, public BlockClosure {
+ // LIRGenerator should never get instatiated on the heap.
+ private:
+  void* operator new(size_t size) throw();
+  void* operator new[](size_t size) throw();
+  void operator delete(void* p);
+  void operator delete[](void* p);
 
- private:
   Compilation*  _compilation;
   ciMethod*     _method;    // method that we are compiling
   PhiResolverState  _resolver_state;
@@ -244,7 +249,7 @@
   void do_getClass(Intrinsic* x);
   void do_currentThread(Intrinsic* x);
   void do_MathIntrinsic(Intrinsic* x);
-  void do_ExpIntrinsic(Intrinsic* x);
+  void do_LibmIntrinsic(Intrinsic* x);
   void do_ArrayCopy(Intrinsic* x);
   void do_CompareAndSwap(Intrinsic* x, ValueType* type);
   void do_NIOCheckIndex(Intrinsic* x);
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -6586,7 +6586,6 @@
         case lir_cos:
         case lir_abs:
         case lir_log10:
-        case lir_log:
         case lir_pow:
         case lir_logic_and:
         case lir_logic_or:
--- a/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_RangeCheckElimination.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -45,8 +45,14 @@
   define_stack(IntegerStack, intArray)
   define_array(IntegerMap, IntegerStack*)
 
-  class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure {
+  class Verification : public BlockClosure {
+  // RangeCheckEliminator::Verification should never get instatiated on the heap.
   private:
+    void* operator new(size_t size) throw();
+    void* operator new[](size_t size) throw();
+    void operator delete(void* p);
+    void operator delete[](void* p);
+
     IR *_ir;
     boolArray _used;
     BlockBeginList _current;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -318,6 +318,7 @@
 #endif
   FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32());
   FUNCTION_CASE(entry, StubRoutines::dexp());
+  FUNCTION_CASE(entry, StubRoutines::dlog());
 
 #undef FUNCTION_CASE
 
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -38,7 +38,8 @@
 #include "code/scopeDesc.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/disassembler.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
@@ -956,9 +957,9 @@
                             ExceptionHandlerTable* handler_table,
                             ImplicitExceptionTable* inc_table,
                             AbstractCompiler* compiler,
-                            int comp_level,
                             bool has_unsafe_access,
                             bool has_wide_vectors,
+                            DirectiveSet* directives,
                             RTMState  rtm_state) {
   VM_ENTRY_MARK;
   nmethod* nm = NULL;
@@ -1034,11 +1035,20 @@
                                debug_info(), dependencies(), code_buffer,
                                frame_words, oop_map_set,
                                handler_table, inc_table,
-                               compiler, comp_level);
+                               compiler, task()->comp_level());
+
     // Free codeBlobs
     code_buffer->free_blob();
 
     if (nm != NULL) {
+      bool printnmethods = directives->PrintAssemblyOption || directives->PrintNMethodsOption;
+      if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+        nm->print_nmethod(printnmethods);
+      }
+      if (directives->PrintAssemblyOption) {
+        Disassembler::decode(nm);
+      }
+
       nm->set_has_unsafe_access(has_unsafe_access);
       nm->set_has_wide_vectors(has_wide_vectors);
 #if INCLUDE_RTM_OPT
@@ -1069,7 +1079,7 @@
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
           tty->print_cr("Installing method (%d) %s ",
-                        comp_level,
+                        task()->comp_level(),
                         method_name);
         }
         // Allow the code to be executed
@@ -1080,7 +1090,7 @@
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
           tty->print_cr("Installing osr method (%d) %s @ %d",
-                        comp_level,
+                        task()->comp_level(),
                         method_name,
                         entry_bci);
         }
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -32,9 +32,11 @@
 #include "code/dependencies.hpp"
 #include "code/exceptionHandlerTable.hpp"
 #include "compiler/oopMap.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/thread.hpp"
 
 class CompileTask;
+class DirectiveSet;
 
 // ciEnv
 //
@@ -352,6 +354,7 @@
   // The compiler task which has created this env.
   // May be useful to find out compile_id, comp_level, etc.
   CompileTask* task() { return _task; }
+
   // Handy forwards to the task:
   int comp_level();   // task()->comp_level()
   uint compile_id();  // task()->compile_id()
@@ -367,9 +370,9 @@
                        ExceptionHandlerTable*    handler_table,
                        ImplicitExceptionTable*   inc_table,
                        AbstractCompiler*         compiler,
-                       int                       comp_level,
                        bool                      has_unsafe_access,
                        bool                      has_wide_vectors,
+                       DirectiveSet*             directives,
                        RTMState                  rtm_state = NoRTM);
 
 
--- a/hotspot/src/share/vm/ci/ciField.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciField.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -190,6 +190,14 @@
   // so there is no hacking of finals going on with them.
   if (holder->is_anonymous())
     return true;
+  // Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
+  // more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
+  if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
+      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
+      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
+      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
+    return true;
+  }
   return TrustFinalNonStaticFields;
 }
 
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -35,7 +35,6 @@
 #include "ci/ciUtilities.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "compiler/abstractCompiler.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "compiler/methodLiveness.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -1044,51 +1043,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciMethod::should_inline
-//
-// Should this method be inlined during compilation?
-bool ciMethod::should_inline() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_not_inline
-//
-// Should this method be disallowed from inlining during compilation?
-bool ciMethod::should_not_inline() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_not_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_print_assembly
-//
-// Should the compiler print the generated code for this method?
-bool ciMethod::should_print_assembly() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_print(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::break_at_execute
-//
-// Should the compiler insert a breakpoint into the generated code
-// method?
-bool ciMethod::break_at_execute() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_break_at(mh);
-}
-
-// ------------------------------------------------------------------
 // ciMethod::has_option
 //
 bool ciMethod::has_option(const char* option) {
@@ -1101,20 +1055,12 @@
 // ------------------------------------------------------------------
 // ciMethod::has_option_value
 //
-template<typename T>
-bool ciMethod::has_option_value(const char* option, T& value) {
+bool ciMethod::has_option_value(const char* option, double& value) {
   check_is_loaded();
   VM_ENTRY_MARK;
   methodHandle mh(THREAD, get_Method());
   return CompilerOracle::has_option_value(mh, option, value);
 }
-// Explicit instantiation for all OptionTypes supported.
-template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
-template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
-template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
-template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
-template bool ciMethod::has_option_value<double>(const char* option, double& value);
-
 // ------------------------------------------------------------------
 // ciMethod::can_be_compiled
 //
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -104,8 +104,6 @@
 
   void load_code();
 
-  void check_is_loaded() const                   { assert(is_loaded(), "not loaded"); }
-
   bool ensure_method_data(methodHandle h_m);
 
   void code_at_put(int bci, Bytecodes::Code code) {
@@ -120,6 +118,8 @@
   void assert_call_type_ok(int bci);
 
  public:
+  void check_is_loaded() const                   { assert(is_loaded(), "not loaded"); }
+
   // Basic method information.
   ciFlags flags() const                          { check_is_loaded(); return _flags; }
   ciSymbol* name() const                         { return _name; }
@@ -265,14 +265,8 @@
   // Find the proper vtable index to invoke this method.
   int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
 
-  // Compilation directives
-  bool should_inline();
-  bool should_not_inline();
-  bool should_print_assembly();
-  bool break_at_execute();
   bool has_option(const char *option);
-  template<typename T>
-  bool has_option_value(const char* option, T& value);
+  bool has_option_value(const char* option, double& value);
   bool can_be_compiled();
   bool can_be_osr_compiled(int entry_bci);
   void set_not_compilable(const char* reason = NULL);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -417,36 +417,10 @@
   }
 }
 
-bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) {
+bool vmIntrinsics::is_disabled_by_flags(methodHandle method) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
-  // Check if the intrinsic corresponding to 'method' has been disabled on
-  // the command line by using the DisableIntrinsic flag (either globally
-  // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
-  // for details).
-  // Usually, the compilation context is the caller of the method 'method'.
-  // The only case when for a non-recursive method 'method' the compilation context
-  // is not the caller of the 'method' (but it is the method itself) is
-  // java.lang.ref.Referene::get.
-  // For java.lang.ref.Reference::get, the intrinsic version is used
-  // instead of the compiled version so that the value in the referent
-  // field can be registered by the G1 pre-barrier code. The intrinsified
-  // version of Reference::get also adds a memory barrier to prevent
-  // commoning reads from the referent field across safepoint since GC
-  // can change the referent field's value. See Compile::Compile()
-  // in src/share/vm/opto/compile.cpp or
-  // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
-  // for more details.
-  ccstr disable_intr = NULL;
-  if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
-      (!compilation_context.is_null() &&
-       CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
-       strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
-  ) {
-    return true;
-  }
-
   // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
   // the following switch statement.
   if (!InlineNatives) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -202,7 +202,11 @@
   template(java_lang_StackTraceElement,               "java/lang/StackTraceElement")              \
                                                                                                   \
   /* Concurrency support */                                                                       \
-  template(java_util_concurrent_locks_AbstractOwnableSynchronizer,   "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
+  template(java_util_concurrent_locks_AbstractOwnableSynchronizer,           "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
+  template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl,       "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
+  template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater,    "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
+  template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
+  template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl,     "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
   template(sun_misc_Contended_signature,              "Lsun/misc/Contended;")                     \
                                                                                                   \
   /* class symbols needed by intrinsics */                                                        \
@@ -1402,7 +1406,7 @@
 
   // Returns true if a compiler intrinsic is disabled by command-line flags
   // and false otherwise.
-  static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context);
+  static bool is_disabled_by_flags(methodHandle method);
 };
 
 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -32,7 +32,7 @@
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "compiler/disassembler.hpp"
 #include "interpreter/bytecode.hpp"
 #include "oops/methodData.hpp"
@@ -582,9 +582,6 @@
                                             basic_lock_owner_sp_offset,
                                             basic_lock_sp_offset, oop_maps);
     NOT_PRODUCT(if (nm != NULL)  native_nmethod_stats.note_native_nmethod(nm));
-    if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
-      Disassembler::decode(nm);
-    }
   }
   // verify nmethod
   debug_only(if (nm) nm->verify();) // might block
@@ -666,9 +663,6 @@
         }
       }
       NOT_PRODUCT(if (nm != NULL)  note_java_nmethod(nm));
-      if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
-        Disassembler::decode(nm);
-      }
     }
   }
   // Do verification and logging outside CodeCache_lock.
@@ -908,13 +902,6 @@
            _method->is_static() == (entry_point() == _verified_entry_point),
            " entry points must be same for static methods and vice versa");
   }
-
-  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
-    || CompilerOracle::should_print(_method)
-    || CompilerOracle::has_option_string(_method, "PrintNMethods");
-  if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
-    print_nmethod(printnmethods);
-  }
 }
 
 // Print a short set of xml attributes to identify this nmethod.  The
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
 
 #include "ci/compilerInterface.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 typedef void (*initializer)(void);
 
@@ -114,36 +115,33 @@
 
   // Determine if the current compiler provides an intrinsic
   // for method 'method'. An intrinsic is available if:
-  //  - the intrinsic is enabled (by using the appropriate command-line flag) and
+  //  - the intrinsic is enabled (by using the appropriate command-line flag,
+  //    the command-line compile ommand, or a compiler directive)
   //  - the platform on which the VM is running supports the intrinsic
   //    (i.e., the platform provides the instructions necessary for the compiler
   //    to generate the intrinsic code).
   //
-  // The second parameter, 'compilation_context', is needed to implement functionality
-  // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
-  // be used to prohibit the compilers to use an intrinsic. There are three ways to
-  // disable an intrinsic using the DisableIntrinsic flag:
+  // The directive provides the compilation context and includes pre-evaluated values
+  // dependent on VM flags, compile commands, and compiler directives.
   //
-  // (1) -XX:DisableIntrinsic=_hashCode,_getClass
-  //     Disables intrinsification of _hashCode and _getClass globally
-  //     (i.e., the intrinsified version the methods will not be used at all).
-  // (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
-  //     Disables intrinsification of _hashCode if it is called from
-  //     aClass::aMethod (but not for any other call site of _hashCode)
-  // (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
-  //     Some methods are not compiled by C2. Instead, the C2 compiler
-  //     returns directly the intrinsified version of these methods.
-  //     The command above forces C2 to compile _Reference_get, but
-  //     allows using the intrinsified version of _Reference_get at all
-  //     other call sites.
-  //
-  // From the modes above, (1) disable intrinsics globally, (2) and (3)
-  // disable intrinsics on a per-method basis. In cases (2) and (3) the
-  // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
-  // respectively.
-  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+  // Usually, the compilation context is the caller of the method 'method'.
+  // The only case when for a non-recursive method 'method' the compilation context
+  // is not the caller of the 'method' (but it is the method itself) is
+  // java.lang.ref.Referene::get.
+  // For java.lang.ref.Reference::get, the intrinsic version is used
+  // instead of the compiled version so that the value in the referent
+  // field can be registered by the G1 pre-barrier code. The intrinsified
+  // version of Reference::get also adds a memory barrier to prevent
+  // commoning reads from the referent field across safepoint since GC
+  // can change the referent field's value. See Compile::Compile()
+  // in src/share/vm/opto/compile.cpp or
+  // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
+  // for more details.
+
+  virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) {
     return is_intrinsic_supported(method) &&
-           !vmIntrinsics::is_disabled_by_flags(method, compilation_context);
+           !directive->is_intrinsic_disabled(method) &&
+           !vmIntrinsics::is_disabled_by_flags(method);
   }
 
   // Determines if an intrinsic is supported by the compiler, that is,
@@ -176,7 +174,7 @@
   void set_state     (int state);
   void set_shut_down ()           { set_state(shut_down); }
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
     ShouldNotReachHere();
   }
 
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -29,6 +29,7 @@
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
 #include "compiler/compilerOracle.hpp"
+#include "compiler/directivesParser.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
 #include "oops/methodData.hpp"
@@ -202,10 +203,22 @@
 
 static CompilationLog* _compilation_log = NULL;
 
-void compileBroker_init() {
+bool compileBroker_init() {
   if (LogEvents) {
     _compilation_log = new CompilationLog();
   }
+
+  // init directives stack, adding default directive
+  DirectivesStack::init();
+
+  if (DirectivesParser::has_file()) {
+    return DirectivesParser::parse_from_flag();
+  } else if (PrintCompilerDirectives) {
+    // Print default directive even when no other was added
+    DirectivesStack::print(tty);
+  }
+
+  return true;
 }
 
 CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
@@ -1180,12 +1193,16 @@
     return true;
   }
 
+  // Breaking the abstraction - directives are only used inside a compilation otherwise.
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
+  bool excluded = directive->ExcludeOption;
+  DirectivesStack::release(directive);
+
   // The method may be explicitly excluded by the user.
-  bool quietly;
   double scale;
-  if (CompilerOracle::should_exclude(method, quietly)
-      || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
-    if (!quietly) {
+  if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
+    bool quietly = CompilerOracle::should_exclude_quietly();
+    if (PrintCompilation && !quietly) {
       // This does not happen quietly...
       ResourceMark rm;
       tty->print("### Excluding %s:%s",
@@ -1194,7 +1211,7 @@
       method->print_short_name(tty);
       tty->cr();
     }
-    method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompileCommand");
+    method->set_not_compilable(comp_level, !quietly, "excluded by CompileCommand");
   }
 
   return false;
@@ -1357,7 +1374,6 @@
     ThreadInVMfromNative tv(thread);
     ResetNoHandleMark rnhm;
 
-
     if (!comp->is_shark()) {
       // Perform per-thread and global initializations
       comp->initialize();
@@ -1629,6 +1645,10 @@
   }
 }
 
+int DirectivesStack::_depth = 0;
+CompilerDirectives* DirectivesStack::_top = NULL;
+CompilerDirectives* DirectivesStack::_bottom = NULL;
+
 // ------------------------------------------------------------------
 // CompileBroker::invoke_compiler_on_method
 //
@@ -1655,16 +1675,20 @@
   bool should_log = (thread->log() != NULL);
   bool should_break = false;
   int task_level = task->comp_level();
+
+  // Look up matching directives
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(task->method(), compiler(task_level));
+
+  should_break = directive->BreakAtExecuteOption || task->check_break_at_flags();
+  if (should_log && !directive->LogOption) {
+    should_log = false;
+  }
   {
     // create the handle inside it's own block so it can't
     // accidentally be referenced once the thread transitions to
     // native.  The NoHandleMark before the transition should catch
     // any cases where this occurs in the future.
     methodHandle method(thread, task->method());
-    should_break = check_break_at(method, compile_id, is_osr);
-    if (should_log && !CompilerOracle::should_log(method)) {
-      should_log = false;
-    }
     assert(!method->is_native(), "no longer compile natives");
 
     // Save information about this method in case of failure.
@@ -1732,7 +1756,7 @@
           locker.wait(Mutex::_no_safepoint_check_flag);
         }
       }
-      comp->compile_method(&ci_env, target, osr_bci);
+      comp->compile_method(&ci_env, target, osr_bci, directive);
     }
 
     if (!ci_env.failing() && task->code() == NULL) {
@@ -1762,6 +1786,7 @@
 
     post_compile(thread, task, event, !ci_env.failing(), &ci_env);
   }
+  DirectivesStack::release(directive);
   pop_jni_handle_block();
 
   methodHandle method(thread, task->method());
@@ -1947,21 +1972,6 @@
   JNIHandleBlock::release_block(compile_handles, thread); // may block
 }
 
-
-// ------------------------------------------------------------------
-// CompileBroker::check_break_at
-//
-// Should the compilation break at the current compilation.
-bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) {
-  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
-    return true;
-  } else if( CompilerOracle::should_break_at(method) ) { // break when compiling
-    return true;
-  } else {
-    return (compile_id == CIBreakAt);
-  }
-}
-
 // ------------------------------------------------------------------
 // CompileBroker::collect_statistics
 //
@@ -2232,3 +2242,4 @@
   st->cr();
 #endif
 }
+
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -28,8 +28,10 @@
 #include "ci/compilerInterface.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileTask.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/perfData.hpp"
 #include "trace/tracing.hpp"
+#include "utilities/stack.hpp"
 
 class nmethod;
 class nmethodLocker;
@@ -129,13 +131,12 @@
   ~CompileTaskWrapper();
 };
 
-
 // Compilation
 //
 // The broker for all compilation requests.
 class CompileBroker: AllStatic {
  friend class Threads;
-  friend class CompileTaskWrapper;
+ friend class CompileTaskWrapper;
 
  public:
   enum {
@@ -238,7 +239,6 @@
   static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
   static void push_jni_handle_block();
   static void pop_jni_handle_block();
-  static bool check_break_at(methodHandle method, int compile_id, bool is_osr);
   static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
 
   static void compile_method_base(methodHandle method,
@@ -253,7 +253,11 @@
   static bool init_compiler_runtime();
   static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
 
- public:
+public:
+
+  static DirectivesStack* dirstack();
+  static void set_dirstack(DirectivesStack* stack);
+
   enum {
     // The entry bci used for non-OSR compilations.
     standard_entry_bci = InvocationEntryBci
@@ -267,6 +271,7 @@
 
   static bool compilation_is_in_queue(methodHandle method);
   static void print_compile_queues(outputStream* st);
+  static void print_directives(outputStream* st);
   static int queue_size(int comp_level) {
     CompileQueue *q = compile_queue(comp_level);
     return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/compiler/compileTask.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -26,6 +26,7 @@
 #include "compiler/compileTask.hpp"
 #include "compiler/compileLog.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 CompileTask*  CompileTask::_task_free_list = NULL;
 #ifdef ASSERT
@@ -372,6 +373,19 @@
 }
 
 // ------------------------------------------------------------------
+// CompileTask::check_break_at_flags
+bool CompileTask::check_break_at_flags() {
+  int compile_id = this->_compile_id;
+  bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
+
+  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
+    return true;
+  } else {
+    return (compile_id == CIBreakAt);
+  }
+}
+
+// ------------------------------------------------------------------
 // CompileTask::print_inlining
 void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
   //         1234567
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/compilerOracle.hpp"
+
+CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
+  _c1_store = new DirectiveSet(this);
+  _c2_store = new DirectiveSet(this);
+};
+
+CompilerDirectives::~CompilerDirectives() {
+  if (_c1_store != NULL) {
+    delete _c1_store;
+  }
+  if (_c2_store != NULL) {
+    delete _c2_store;
+  }
+
+  // remove all linked method matchers
+  BasicMatcher* tmp = _match;
+  while (tmp != NULL) {
+    BasicMatcher* next = tmp->next();
+    delete tmp;
+    tmp = next;
+  }
+}
+
+void CompilerDirectives::print(outputStream* st) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  if (_match != NULL) {
+    st->cr();
+    st->print("Directive:");
+    if (is_default_directive()) {
+      st->print_cr(" (default)");
+    } else {
+      st->cr();
+    }
+    st->print(" matching: ");
+    _match->print(st);
+    BasicMatcher* tmp = _match->next();
+    while (tmp != NULL) {
+      st->print(", ");
+      tmp->print(st);
+      tmp = tmp->next();
+    }
+    st->cr();
+  } else {
+    assert(0, "There should always be a match");
+  }
+
+  if (_c1_store != NULL) {
+    st->print_cr(" c1 directives:");
+    _c1_store->print(st);
+  }
+  if (_c2_store != NULL) {
+    st->cr();
+    st->print_cr(" c2 directives:");
+    _c2_store->print(st);
+  }
+  //---
+}
+
+void CompilerDirectives::finalize() {
+  if (_c1_store != NULL) {
+    _c1_store->finalize();
+  }
+  if (_c2_store != NULL) {
+    _c2_store->finalize();
+  }
+}
+
+void DirectiveSet::finalize() {
+  // if any flag has been modified - set directive as enabled
+  // unless it already has been explicitly set.
+  if (!_modified[EnableIndex]) {
+    if (_inlinematchers != NULL) {
+      EnableOption = true;
+      return;
+    }
+    int i;
+    for (i = 0; i < number_of_flags; i++) {
+      if (_modified[i]) {
+        EnableOption = true;
+        return;
+      }
+    }
+  }
+}
+
+CompilerDirectives* CompilerDirectives::next() {
+  return _next;
+}
+
+bool CompilerDirectives::match(methodHandle method) {
+  if (is_default_directive()) {
+    return true;
+  }
+  if (method == NULL) {
+    return false;
+  }
+  if (_match->match(method)) {
+    return true;
+  }
+  return false;
+}
+
+bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
+  BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
+  if (bm == NULL) {
+    assert(error_msg != NULL, "Must have error message");
+    return false;
+  } else {
+    bm->set_next(_match);
+    _match = bm;
+    return true;
+  }
+}
+
+void CompilerDirectives::inc_refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  _ref_count++;
+}
+
+void CompilerDirectives::dec_refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  _ref_count--;
+}
+
+int CompilerDirectives::refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  return _ref_count;
+}
+
+DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  inc_refcount(); // The compiling thread is responsible to decrement this when finished.
+  if (comp == NULL) { // Xint
+    return _c1_store;
+  } else if (comp->is_c2()) {
+    return _c2_store;
+  } else if (comp->is_c1()) {
+    return _c1_store;
+  } else if (comp->is_shark()) {
+    return NULL;
+  } else if (comp->is_jvmci()) {
+    return NULL;
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
+// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
+// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
+// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
+// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
+//
+// To simplify the processing of the list, the canonicalize_disableintrinsic() method
+// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
+ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
+  char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
+  int i = 0;
+  char current;
+  while ((current = option_value[i]) != '\0') {
+    if (current == '\n' || current == ' ') {
+      canonicalized_list[i] = ',';
+    } else {
+      canonicalized_list[i] = current;
+    }
+    i++;
+  }
+  canonicalized_list[i] = '\0';
+  return canonicalized_list;
+}
+
+DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
+#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
+  compilerdirectives_common_flags(init_defaults_definition)
+  compilerdirectives_c2_flags(init_defaults_definition)
+  compilerdirectives_c1_flags(init_defaults_definition)
+  memset(_modified, 0, sizeof _modified);
+
+  // Canonicalize DisableIntrinsic to contain only ',' as a separator.
+  this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
+}
+
+DirectiveSet::~DirectiveSet() {
+  // remove all linked methodmatchers
+  InlineMatcher* tmp = _inlinematchers;
+  while (tmp != NULL) {
+    InlineMatcher* next = tmp->next();
+    delete tmp;
+    tmp = next;
+  }
+
+  // When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
+  // into a new string. Therefore, that string is deallocated when
+  // the DirectiveSet is destroyed.
+  assert(this->DisableIntrinsicOption != NULL, "");
+  FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
+}
+
+// Backward compatibility for CompileCommands
+// Breaks the abstraction and causes lots of extra complexity
+// - if some option is changed we need to copy directiveset since it no longer can be shared
+// - Need to free copy after use
+// - Requires a modified bit so we don't overwrite options that is set by directives
+
+DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
+  // Early bail out - checking all options is expensive - we rely on them not being used
+  // Only set a flag if it has not been modified and value changes.
+  // Only copy set if a flag needs to be set
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
+    DirectiveSet* set = DirectiveSet::clone(this);
+
+    bool changed = false; // Track if we actually change anything
+
+    // All CompileCommands are not equal so this gets a bit verbose
+    // When CompileCommands have been refactored less clutter will remain.
+    if (CompilerOracle::should_break_at(method)) {
+      if (!_modified[BreakAtCompileIndex]) {
+        set->BreakAtCompileOption = true;
+        changed = true;
+      }
+      if (!_modified[BreakAtExecuteIndex]) {
+        set->BreakAtExecuteOption = true;
+        changed = true;
+      }
+    }
+    if (CompilerOracle::should_log(method)) {
+      if (!_modified[LogIndex]) {
+        set->LogOption = true;
+        changed = true;
+      }
+    }
+    if (CompilerOracle::should_print(method)) {
+      if (!_modified[PrintAssemblyIndex]) {
+        set->PrintAssemblyOption = true;
+        changed = true;
+      }
+    }
+    // Exclude as in should not compile == Enabled
+    if (CompilerOracle::should_exclude(method)) {
+      if (!_modified[ExcludeIndex]) {
+        set->ExcludeOption = true;
+        changed = true;
+      }
+    }
+
+    // inline and dontinline (including exclude) are implemented in the directiveset accessors
+#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
+    compilerdirectives_common_flags(init_default_cc)
+    compilerdirectives_c2_flags(init_default_cc)
+    compilerdirectives_c1_flags(init_default_cc)
+
+    // Canonicalize DisableIntrinsic to contain only ',' as a separator.
+    ccstrlist option_value;
+    if (!_modified[DisableIntrinsicIndex] &&
+        CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
+      set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
+    }
+
+
+    if (!changed) {
+      // We didn't actually update anything, discard.
+      delete set;
+    } else {
+      // We are returning a (parentless) copy. The originals parent don't need to account for this.
+      DirectivesStack::release(this);
+      return set;
+    }
+  }
+  // Nothing changed
+  return this;
+}
+
+CompilerDirectives* DirectiveSet::directive() {
+  assert(_directive != NULL, "Must have been initialized");
+  return _directive;
+}
+
+bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
+  if (_inlinematchers != NULL) {
+    if (_inlinematchers->match(method, InlineMatcher::force_inline)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool DirectiveSet::should_inline(ciMethod* inlinee) {
+  inlinee->check_is_loaded();
+  VM_ENTRY_MARK;
+  methodHandle mh(THREAD, inlinee->get_Method());
+
+  if (matches_inline(mh, InlineMatcher::force_inline)) {
+    return true;
+  }
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_inline(mh)) {
+    return true;
+  }
+  return false;
+}
+
+bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
+  inlinee->check_is_loaded();
+  VM_ENTRY_MARK;
+  methodHandle mh(THREAD, inlinee->get_Method());
+
+  if (matches_inline(mh, InlineMatcher::dont_inline)) {
+    return true;
+  }
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_not_inline(mh)) {
+    return true;
+  }
+  return false;
+}
+
+bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
+  InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
+  if (m != NULL) {
+    // add matcher last in chain - the order is significant
+    append_inline(m);
+    return true;
+  } else {
+    assert(error_msg != NULL, "Error message must be set");
+    return false;
+  }
+}
+
+void DirectiveSet::append_inline(InlineMatcher* m) {
+  if (_inlinematchers == NULL) {
+    _inlinematchers = m;
+    return;
+  }
+  InlineMatcher* tmp = _inlinematchers;
+  while (tmp->next() != NULL) {
+    tmp = tmp->next();
+  }
+  tmp->set_next(m);
+}
+
+void DirectiveSet::print_inline(outputStream* st) {
+  if (_inlinematchers == NULL) {
+    st->print_cr("  inline: -");
+  } else {
+    st->print("  inline: ");
+    _inlinematchers->print(st);
+    InlineMatcher* tmp = _inlinematchers->next();
+    while (tmp != NULL) {
+      st->print(", ");
+      tmp->print(st);
+      tmp = tmp->next();
+    }
+    st->cr();
+  }
+}
+
+bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  ResourceMark rm;
+
+  // Create a copy of the string that contains the list of disabled
+  // intrinsics. The copy is created because the string
+  // will be modified by strtok(). Then, the list is tokenized with
+  // ',' as a separator.
+  size_t length = strlen(DisableIntrinsicOption);
+  char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
+  strncpy(local_list, DisableIntrinsicOption, length + 1);
+
+  char* token = strtok(local_list, ",");
+  while (token != NULL) {
+    if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
+      return true;
+    } else {
+      token = strtok(NULL, ",");
+    }
+  }
+
+  return false;
+}
+
+DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
+  DirectiveSet* set = new DirectiveSet(NULL);
+  memcpy(set->_modified, src->_modified, sizeof(src->_modified));
+
+  InlineMatcher* tmp = src->_inlinematchers;
+  while (tmp != NULL) {
+    set->append_inline(tmp->clone());
+    tmp = tmp->next();
+  }
+
+  #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
+    compilerdirectives_common_flags(copy_members_definition)
+    compilerdirectives_c2_flags(copy_members_definition)
+    compilerdirectives_c1_flags(copy_members_definition)
+
+  // Create a local copy of the DisableIntrinsicOption.
+  assert(src->DisableIntrinsicOption != NULL, "");
+  size_t len = strlen(src->DisableIntrinsicOption) + 1;
+  char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
+  strncpy(s, src->DisableIntrinsicOption, len);
+  assert(s[len-1] == '\0', "");
+  set->DisableIntrinsicOption = s;
+  return set;
+}
+
+// Create a new dirstack and push a default directive
+void DirectivesStack::init() {
+  CompilerDirectives* _default_directives = new CompilerDirectives();
+  char str[] = "*.*";
+  const char* error_msg = NULL;
+  _default_directives->add_match(str, error_msg);
+#ifdef COMPILER1
+  _default_directives->_c1_store->EnableOption = true;
+#endif
+#ifdef COMPILER2
+  _default_directives->_c2_store->EnableOption = true;
+#endif
+  assert(error_msg == NULL, "Must succeed.");
+  push(_default_directives);
+}
+
+DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+  assert(_bottom != NULL, "Must never be empty");
+  return _bottom->get_for(comp);
+}
+
+void DirectivesStack::push(CompilerDirectives* directive) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+  directive->inc_refcount();
+  if (_top == NULL) {
+    assert(_bottom == NULL, "There can only be one default directive");
+    _bottom = directive; // default directive, can never be removed.
+  }
+
+  directive->set_next(_top);
+  _top = directive;
+  _depth++;
+}
+
+void DirectivesStack::pop() {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  pop_inner();
+}
+
+void DirectivesStack::pop_inner() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+
+  if (_top->next() == NULL) {
+    return; // Do nothing - don't allow an empty stack
+  }
+  CompilerDirectives* tmp = _top;
+  _top = _top->next();
+  _depth--;
+
+  DirectivesStack::release(tmp);
+}
+
+void DirectivesStack::clear() {
+  // holding the lock during the whole operation ensuring consistent result
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  while (_top->next() != NULL) {
+    pop_inner();
+  }
+}
+
+void DirectivesStack::print(outputStream* st) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  CompilerDirectives* tmp = _top;
+  while (tmp != NULL) {
+    tmp->print(st);
+    tmp = tmp->next();
+    st->cr();
+  }
+}
+
+void DirectivesStack::release(DirectiveSet* set) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  if (set->is_exclusive_copy()) {
+    // Old CompilecCmmands forced us to create an exclusive copy
+    delete set;
+  } else {
+    assert(set->directive() != NULL, "");
+    release(set->directive());
+  }
+}
+
+
+void DirectivesStack::release(CompilerDirectives* dir) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  dir->dec_refcount();
+  if (dir->refcount() == 0) {
+    delete dir;
+  }
+}
+
+DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
+  assert(_depth > 0, "Must never be empty");
+  CompilerDirectives* dir = _top;
+  assert(dir != NULL, "Must be initialized");
+
+  DirectiveSet* match = NULL;
+  {
+    MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+    while (dir != NULL) {
+      if (dir->is_default_directive() || dir->match(method)) {
+        match = dir->get_for(comp);
+        if (match == NULL) {
+          // temporary workaround for compilers without directives.
+          if (dir->is_default_directive()) {
+            // default dir is always enabled
+            // match c1 store - it contains all common flags even if C1 is unavailable
+            match = dir->_c1_store;
+            break;
+          }
+        }
+        if (match->EnableOption) {
+          // The directiveSet for this compile is also enabled -> success
+          break;
+        }
+      }
+      dir = dir->next();
+    }
+  }
+
+  guarantee(match != NULL, "There should always be a default directive that matches");
+  // Check for legacy compile commands update, without DirectivesStack_lock
+  return match->compilecommand_compatibility_init(method);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+#define SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+
+#include "ci/ciMetadata.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/methodMatcher.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/exceptions.hpp"
+
+  //      Directives flag name,    type, default value, compile command name
+  #define compilerdirectives_common_flags(cflags) \
+    cflags(Enable,                  bool, false, X) \
+    cflags(Exclude,                 bool, false, X) \
+    cflags(BreakAtExecute,          bool, false, X) \
+    cflags(BreakAtCompile,          bool, false, X) \
+    cflags(Log,                     bool, false, X) \
+    cflags(PrintAssembly,           bool, PrintAssembly, PrintAssembly) \
+    cflags(PrintInlining,           bool, PrintInlining, PrintInlining) \
+    cflags(PrintNMethods,           bool, PrintNMethods, PrintNMethods) \
+    cflags(ReplayInline,            bool, false, ReplayInline) \
+    cflags(DumpReplay,              bool, false, DumpReplay) \
+    cflags(DumpInline,              bool, false, DumpInline) \
+    cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
+    cflags(DisableIntrinsic,        ccstrlist, DisableIntrinsic, DisableIntrinsic)
+
+#ifdef COMPILER1
+  #define compilerdirectives_c1_flags(cflags)
+#else
+  #define compilerdirectives_c1_flags(cflags)
+#endif
+
+#ifdef COMPILER2
+  #define compilerdirectives_c2_flags(cflags) \
+    cflags(BlockLayoutByFrequency,  bool, BlockLayoutByFrequency,  BlockLayoutByFrequency) \
+    cflags(PrintOptoAssembly,       bool, PrintOptoAssembly, PrintOptoAssembly) \
+    cflags(PrintIntrinsics,         bool, PrintIntrinsics, PrintIntrinsics) \
+    cflags(TraceOptoPipelining,     bool, false, TraceOptoPipelining) \
+    cflags(TraceOptoOutput,         bool, false, TraceOptoOutput) \
+    cflags(TraceSpilling,           bool, TraceSpilling, TraceSpilling) \
+    cflags(Vectorize,               bool, false, Vectorize) \
+    cflags(VectorizeDebug,          bool, false, VectorizeDebug) \
+    cflags(CloneMapDebug,           bool, false, CloneMapDebug) \
+    cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
+    NOT_PRODUCT( cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \
+    cflags(MaxNodeLimit,            intx, MaxNodeLimit, MaxNodeLimit)
+#else
+  #define compilerdirectives_c2_flags(cflags)
+#endif
+
+class CompilerDirectives;
+class DirectiveSet;
+
+class DirectivesStack : AllStatic {
+private:
+  static CompilerDirectives* _top;
+  static CompilerDirectives* _bottom;
+  static int _depth;
+
+  static void pop_inner(); // no lock version of pop
+public:
+  static void init();
+  static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
+  static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
+  static void push(CompilerDirectives* directive);
+  static void pop();
+  static void clear();
+  static void print(outputStream* st);
+  static void release(DirectiveSet* set);
+  static void release(CompilerDirectives* dir);
+};
+
+class DirectiveSet : public CHeapObj<mtCompiler> {
+private:
+  InlineMatcher* _inlinematchers;
+  CompilerDirectives* _directive;
+
+  static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
+
+public:
+  DirectiveSet(CompilerDirectives* directive);
+  ~DirectiveSet();
+  CompilerDirectives* directive();
+  bool parse_and_add_inline(char* str, const char*& error_msg);
+  void append_inline(InlineMatcher* m);
+  bool should_inline(ciMethod* inlinee);
+  bool should_not_inline(ciMethod* inlinee);
+  void print_inline(outputStream* st);
+  DirectiveSet* compilecommand_compatibility_init(methodHandle method);
+  bool is_exclusive_copy() { return _directive == NULL; }
+  bool matches_inline(methodHandle method, int inline_action);
+  static DirectiveSet* clone(DirectiveSet const* src);
+  bool is_intrinsic_disabled(methodHandle method);
+  void finalize();
+
+  typedef enum {
+#define enum_of_flags(name, type, dvalue, cc_flag) name##Index,
+    compilerdirectives_common_flags(enum_of_flags)
+    compilerdirectives_c2_flags(enum_of_flags)
+    compilerdirectives_c1_flags(enum_of_flags)
+    number_of_flags
+  } flags;
+
+  bool _modified[number_of_flags];
+
+#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
+  compilerdirectives_common_flags(flag_store_definition)
+  compilerdirectives_c2_flags(flag_store_definition)
+  compilerdirectives_c1_flags(flag_store_definition)
+
+// Casting to get the same function signature for all setters. Used from parser.
+#define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = 1; }
+  compilerdirectives_common_flags(set_function_definition)
+  compilerdirectives_c2_flags(set_function_definition)
+  compilerdirectives_c1_flags(set_function_definition)
+
+  void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } }
+  void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } }
+  void print_double(outputStream* st, ccstr n, double v, bool mod) { if (mod) { st->print("%s:%f ", n, v); } }
+  void print_ccstr(outputStream* st, ccstr n, ccstr v, bool mod) { if (mod) { st->print("%s:%s ", n, v); } }
+  void print_ccstrlist(outputStream* st, ccstr n, ccstr v, bool mod) { print_ccstr(st, n, v, mod); }
+
+void print(outputStream* st) {
+    print_inline(st);
+    st->print("  ");
+#define print_function_definition(name, type, dvalue, cc_flag) print_##type(st, #name, this->name##Option, true);//(bool)_modified[name##Index]);
+    compilerdirectives_common_flags(print_function_definition)
+    compilerdirectives_c2_flags(print_function_definition)
+    compilerdirectives_c1_flags(print_function_definition)
+    st->cr();
+  }
+};
+
+class CompilerDirectives : public CHeapObj<mtCompiler> {
+private:
+  CompilerDirectives* _next;
+  BasicMatcher* _match;
+  int _ref_count;
+
+public:
+
+  CompilerDirectives();
+  ~CompilerDirectives();
+
+  CompilerDirectives* next();
+  void set_next(CompilerDirectives* next) {_next = next; }
+
+  bool match(methodHandle method);
+  BasicMatcher* match() { return _match; }
+  bool add_match(char* str, const char*& error_msg);
+  DirectiveSet* get_for(AbstractCompiler *comp);
+  void print(outputStream* st);
+  bool is_default_directive() { return _next == NULL; }
+  void finalize();
+
+  void inc_refcount();
+  void dec_refcount();
+  int refcount();
+
+  DirectiveSet* _c1_store;
+  DirectiveSet* _c2_store;
+};
+
+#endif // SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -106,6 +106,7 @@
 
 static BasicMatcher* lists[OracleCommandCount] = { 0, };
 static TypedMethodOptionMatcher* option_list = NULL;
+static bool any_set = false;
 
 class TypedMethodOptionMatcher : public MethodMatcher {
  private:
@@ -292,6 +293,7 @@
   matcher->init(option, get_type_for<T>(), option_list);
   matcher->set_value<T>(value);
   option_list = matcher;
+  any_set = true;
   return;
 }
 
@@ -308,7 +310,9 @@
   }
   bm->set_next(lists[command]);
   lists[command] = bm;
-
+  if ((command != DontInlineCommand) && (command != InlineCommand)) {
+    any_set = true;
+  }
   return;
 }
 
@@ -324,6 +328,10 @@
   return false;
 }
 
+bool CompilerOracle::has_any_option() {
+  return any_set;
+}
+
 // Explicit instantiation for all OptionTypes supported.
 template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
 template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
@@ -337,15 +345,10 @@
   return value;
 }
 
-bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
-  quietly = true;
-  if (lists[ExcludeCommand] != NULL) {
-    if (lists[ExcludeCommand]->match(method)) {
-      quietly = _quiet;
-      return true;
-    }
+bool CompilerOracle::should_exclude(methodHandle method) {
+  if (check_predicate(ExcludeCommand, method)) {
+    return true;
   }
-
   if (lists[CompileOnlyCommand] != NULL) {
     return !lists[CompileOnlyCommand]->match(method);
   }
@@ -356,8 +359,6 @@
   return (check_predicate(InlineCommand, method));
 }
 
-// Check both DontInlineCommand and ExcludeCommand here
-// - consistent behavior for all compilers
 bool CompilerOracle::should_not_inline(methodHandle method) {
   return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
 }
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -46,7 +46,8 @@
   static void parse_from_file();
 
   // Tells whether we to exclude compilation of method
-  static bool should_exclude(methodHandle method, bool& quietly);
+  static bool should_exclude(methodHandle method);
+  static bool should_exclude_quietly() { return _quiet; }
 
   // Tells whether we want to inline this method
   static bool should_inline(methodHandle method);
@@ -71,6 +72,9 @@
   template<typename T>
   static bool has_option_value(methodHandle method, const char* option, T& value);
 
+  // Fast check if there is any option available that compile control needs to know about
+  static bool has_any_option();
+
   // Reads from string instead of file
   static void parse_from_string(const char* command_string, void (*parser)(char*));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
+#include <string.h>
+
+void DirectivesParser::push_tmp(CompilerDirectives* dir) {
+  dir->set_next(_tmp_top);
+  _tmp_top = dir;
+}
+
+CompilerDirectives* DirectivesParser::pop_tmp() {
+  if (_tmp_top == NULL) {
+    return NULL;
+  }
+  CompilerDirectives* tmp = _tmp_top;
+  _tmp_top = _tmp_top->next();
+  tmp->set_next(NULL);
+  return tmp;
+}
+
+bool DirectivesParser::parse_string(const char* text, outputStream* st) {
+  DirectivesParser cd(text, st);
+  if (cd.valid()) {
+    return cd.install_directives();
+  }
+  st->flush();
+  st->print_cr("Parsing of compiler directives failed");
+  return false;
+}
+
+bool DirectivesParser::has_file() {
+  return CompilerDirectivesFile != NULL;
+}
+
+bool DirectivesParser::parse_from_flag() {
+  return parse_from_file(CompilerDirectivesFile, tty);
+}
+
+bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
+  assert(filename != NULL, "Test before calling this");
+  if (!parse_from_file_inner(filename, st)) {
+    st->print_cr("Could not load file: %s", filename);
+    return false;
+  }
+  return true;
+}
+
+bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
+  struct stat st;
+  ResourceMark rm;
+  if (os::stat(filename, &st) == 0) {
+    // found file, open it
+    int file_handle = os::open(filename, 0, 0);
+    if (file_handle != -1) {
+      // read contents into resource array
+      char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
+      size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
+      buffer[num_read] = '\0';
+      // close file
+      os::close(file_handle);
+      return parse_string(buffer, stream);
+    }
+  }
+  return false;
+}
+
+bool DirectivesParser::install_directives() {
+  // Pop from internal temporary stack and push to compileBroker.
+  CompilerDirectives* tmp = pop_tmp();
+  int i = 0;
+  while (tmp != NULL) {
+    i++;
+    DirectivesStack::push(tmp);
+    tmp = pop_tmp();
+  }
+  if (i == 0) {
+    _st->print_cr("No directives in file");
+    return false;
+  } else {
+    _st->print_cr("%i compiler directives added", i);
+    if (PrintCompilerDirectives) {
+      // Print entire directives stack after new has been pushed.
+      DirectivesStack::print(_st);
+    }
+    return true;
+  }
+}
+
+DirectivesParser::DirectivesParser(const char* text, outputStream* st)
+: JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) {
+#ifndef PRODUCT
+  memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
+#endif
+  parse();
+}
+
+DirectivesParser::~DirectivesParser() {
+}
+
+const DirectivesParser::key DirectivesParser::keys[] = {
+    // name, keytype, allow_array, allowed_mask, set_function
+    { "c1",     type_c1,     0, mask(type_directives), NULL, UnknownFlagType },
+    { "c2",     type_c2,     0, mask(type_directives), NULL, UnknownFlagType },
+    { "match",  type_match,  1, mask(type_directives), NULL, UnknownFlagType },
+    { "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+    { "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+    { "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+
+    // Global flags
+    #define common_flag_key(name, type, dvalue, compiler) \
+    { #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
+    compilerdirectives_common_flags(common_flag_key)
+    compilerdirectives_c2_flags(common_flag_key)
+    compilerdirectives_c1_flags(common_flag_key)
+    #undef common_flag_key
+};
+
+const DirectivesParser::key DirectivesParser::dir_array_key = {
+     "top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::dir_key = {
+   "top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::value_array_key = {
+   "value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
+};
+
+const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
+  for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
+    if (strncasecmp(keys[i].name, str, len) == 0) {
+      return &keys[i];
+    }
+  }
+  return NULL;
+}
+
+uint DirectivesParser::mask(keytype kt) {
+  return 1 << (kt + 1);
+}
+
+bool DirectivesParser::push_key(const char* str, size_t len) {
+  bool result = true;
+  const key* k = lookup_key(str, len);
+
+  if (k == NULL) {
+    // os::strdup
+    char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
+    strncpy(s, str, len);
+    s[len] = '\0';
+    error(KEY_ERROR, "No such key: '%s'.", s);
+    FREE_C_HEAP_ARRAY(char, s);
+    return false;
+  }
+
+  return push_key(k);
+}
+
+bool DirectivesParser::push_key(const key* k) {
+  assert(k->allowedmask != 0, "not allowed anywhere?");
+
+  // Exceeding the stack should not be possible with a valid compiler directive,
+  // and an invalid should abort before this happens
+  assert(depth < MAX_DEPTH, "exceeded stack depth");
+  if (depth >= MAX_DEPTH) {
+    error(INTERNAL_ERROR, "Stack depth exceeded.");
+    return false;
+  }
+
+  assert(stack[depth] == NULL, "element not nulled, something is wrong");
+
+  if (depth == 0 && !(k->allowedmask & 1)) {
+    error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
+    return false;
+  }
+
+  if (depth > 0) {
+    const key* prev = stack[depth - 1];
+    if (!(k->allowedmask & mask(prev->type))) {
+      error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
+      return false;
+    }
+  }
+
+  stack[depth] = k;
+  depth++;
+  return true;
+}
+
+const DirectivesParser::key* DirectivesParser::current_key() {
+  assert(depth > 0, "getting key from empty stack");
+  if (depth == 0) {
+    return NULL;
+  }
+  return stack[depth - 1];
+}
+
+const DirectivesParser::key* DirectivesParser::pop_key() {
+  assert(depth > 0, "popping empty stack");
+  if (depth == 0) {
+    error(INTERNAL_ERROR, "Popping empty stack.");
+    return NULL;
+  }
+  depth--;
+
+  const key* k = stack[depth];
+#ifndef PRODUCT
+  stack[depth] = NULL;
+#endif
+
+  return k;
+}
+
+bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
+
+  void (DirectiveSet::*test)(void *args);
+  test = option_key->set;
+
+  switch (t) {
+    case JSON_TRUE:
+      if (option_key->flag_type != boolFlag) {
+        error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        bool val = true;
+        (set->*test)((void *)&val);
+      }
+      break;
+
+    case JSON_FALSE:
+      if (option_key->flag_type != boolFlag) {
+        error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        bool val = false;
+        (set->*test)((void *)&val);
+      }
+      break;
+
+    case JSON_NUMBER_INT:
+      if (option_key->flag_type != intxFlag) {
+        if (option_key->flag_type == doubleFlag) {
+          double dval = (double)v->int_value;
+          (set->*test)((void *)&dval);
+          break;
+        }
+        error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        intx ival = v->int_value;
+        (set->*test)((void *)&ival);
+      }
+      break;
+
+    case JSON_NUMBER_FLOAT:
+      if (option_key->flag_type != doubleFlag) {
+        error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        double dval = v->double_value;
+        (set->*test)((void *)&dval);
+      }
+      break;
+
+    case JSON_STRING:
+      if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
+        error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1,  mtCompiler);
+        strncpy(s, v->str.start, v->str.length + 1);
+        s[v->str.length] = '\0';
+        (set->*test)((void *)&s);
+      }
+      break;
+
+    default:
+      assert(0, "Should not reach here.");
+    }
+  return true;
+}
+
+bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
+
+  const key* option_key = pop_key();
+  const key* enclosing_key = current_key();
+
+  if (option_key->type == value_array_key.type) {
+    // Multi value array, we are really setting the value
+    // for the key one step further up.
+    option_key = pop_key();
+    enclosing_key = current_key();
+
+    // Repush option_key and multi value marker, since
+    // we need to keep them until all multi values are set.
+    push_key(option_key);
+    push_key(&value_array_key);
+  }
+
+  switch (option_key->type) {
+  case type_flag:
+  {
+    if (current_directiveset == NULL) {
+      assert(depth == 2, "Must not have active directive set");
+
+      if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
+        return false;
+      }
+      if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
+        return false;
+      }
+    } else {
+      assert(depth > 2, "Must have active current directive set");
+      if (!set_option_flag(t, v, option_key, current_directiveset)) {
+        return false;
+      }
+    }
+    break;
+  }
+
+  case type_match:
+    if (t != JSON_STRING) {
+      error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+      return false;
+    }
+    if (enclosing_key->type != type_directives) {
+      error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
+      return false;
+    }
+    {
+      char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+      strncpy(s, v->str.start, v->str.length);
+      s[v->str.length] = '\0';
+
+      const char* error_msg = NULL;
+      if (!current_directive->add_match(s, error_msg)) {
+        assert (error_msg != NULL, "Must have valid error message");
+        error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+      }
+      FREE_C_HEAP_ARRAY(char, s);
+    }
+    break;
+
+  case type_inline:
+    if (t != JSON_STRING) {
+      error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+      return false;
+    }
+    {
+      //char* s = strndup(v->str.start, v->str.length);
+      char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+      strncpy(s, v->str.start, v->str.length);
+      s[v->str.length] = '\0';
+
+      const char* error_msg = NULL;
+      if (current_directiveset == NULL) {
+        if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+        if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+      } else {
+        if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+      }
+      FREE_C_HEAP_ARRAY(char, s);
+    }
+    break;
+
+  case type_c1:
+    current_directiveset = current_directive->_c1_store;
+    if (t != JSON_TRUE && t != JSON_FALSE) {
+      error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+      return false;
+    }
+    break;
+
+  case type_c2:
+    current_directiveset = current_directive->_c2_store;
+    if (t != JSON_TRUE && t != JSON_FALSE) {
+      error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+      return false;
+    }
+    break;
+
+  case type_enable:
+    switch (enclosing_key->type) {
+    case type_c1:
+    case type_c2:
+    {
+      if (t != JSON_TRUE && t != JSON_FALSE) {
+        error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name);
+        return false;
+      }
+      int val = (t == JSON_TRUE);
+      current_directiveset->set_Enable(&val);
+      break;
+    }
+
+    case type_directives:
+      error(VALUE_ERROR, "Enable keyword not available for generic directive");
+      return false;
+
+    default:
+      error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name);
+      ShouldNotReachHere();
+      return false;
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return true;
+}
+
+bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
+  const key* k;
+
+  if (depth == 0) {
+    switch (t) {
+      case JSON_ARRAY_BEGIN:
+        return push_key(&dir_array_key);
+
+      case JSON_OBJECT_BEGIN:
+        // push synthetic dir_array
+        push_key(&dir_array_key);
+        assert(depth == 1, "Make sure the stack are aligned with the directives");
+        break;
+
+      default:
+        error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+        return false;
+      }
+  }
+  if (depth == 1) {
+    switch (t) {
+      case JSON_OBJECT_BEGIN:
+        // Parsing a new directive.
+        current_directive = new CompilerDirectives();
+        return push_key(&dir_key);
+
+      case JSON_ARRAY_END:
+        k = pop_key();
+
+        if (k->type != type_dir_array) {
+          error(SYNTAX_ERROR, "Expected end of directives array");
+          return false;
+        }
+        return true;
+
+    default:
+      error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+      return false;
+    }
+  } else {
+    switch (t) {
+    case JSON_OBJECT_BEGIN:
+      k = current_key();
+      switch (k->type) {
+      case type_c1:
+        current_directiveset = current_directive->_c1_store;
+        return true;
+      case type_c2:
+        current_directiveset = current_directive->_c2_store;
+        return true;
+
+      case type_dir_array:
+        return push_key(&dir_key);
+
+      default:
+        error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
+        return false;
+      }
+      return false;
+
+    case JSON_OBJECT_END:
+      k = pop_key();
+      switch (k->type) {
+      case type_c1:
+      case type_c2:
+        // This is how we now if options apply to a single or both directive sets
+        current_directiveset = NULL;
+        break;
+
+      case type_directives:
+        // Check, finish and push to stack!
+        if (current_directive->match() == NULL) {
+          error(INTERNAL_ERROR, "Directive missing required match.");
+          return false;
+        }
+        current_directive->finalize();
+        push_tmp(current_directive);
+        current_directive = NULL;
+        break;
+
+      default:
+        error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
+        ShouldNotReachHere();
+        return false;
+      }
+      return true;
+
+    case JSON_ARRAY_BEGIN:
+      k = current_key();
+      if (!(k->allow_array_value)) {
+        if (k->type == type_dir_array) {
+          error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
+        } else {
+          error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
+        }
+        return false;
+      }
+      return push_key(&value_array_key);
+
+    case JSON_ARRAY_END:
+      k = pop_key(); // Pop multi value marker
+      assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
+      k = pop_key(); // Pop key for option that was set
+      return true;
+
+    case JSON_KEY:
+      return push_key(v->str.start, v->str.length);
+
+    case JSON_STRING:
+    case JSON_NUMBER_INT:
+    case JSON_NUMBER_FLOAT:
+    case JSON_TRUE:
+    case JSON_FALSE:
+    case JSON_NULL:
+      return set_option(t, v);
+
+    default:
+      error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
+      ShouldNotReachHere();
+      return false;
+    }
+  }
+}
+
+#ifndef PRODUCT
+void DirectivesParser::test(const char* text, bool should_pass) {
+  DirectivesParser cd(text, tty);
+  if (should_pass) {
+    assert(cd.valid() == true, "failed on a valid DirectivesParser string");
+    if (VerboseInternalVMTests) {
+      tty->print("-- DirectivesParser test passed as expected --\n");
+    }
+  } else {
+    assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string");
+    if (VerboseInternalVMTests) {
+      tty->print("-- DirectivesParser test failed as expected --\n");
+    }
+  }
+}
+
+bool DirectivesParser::test() {
+  DirectivesParser::test("{}", false);
+  DirectivesParser::test("[]", true);
+  DirectivesParser::test("[{}]", false);
+  DirectivesParser::test("[{},{}]", false);
+  DirectivesParser::test("{},{}", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    inline : \"+java/util.*\"," "\n"
+    "    PrintAssembly: true," "\n"
+    "    BreakAtExecute: true," "\n"
+    "  }" "\n"
+    "]" "\n", true);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  [" "\n"
+    "    {" "\n"
+    "      match: \"foo/bar.*\"," "\n"
+    "      inline : \"+java/util.*\"," "\n"
+    "      PrintAssembly: true," "\n"
+    "      BreakAtExecute: true," "\n"
+    "    }" "\n"
+    "  ]" "\n"
+    "]" "\n", false);
+
+  /*DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    c1: {"
+    "      PrintIntrinsics: false," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", false);*/
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    c2: {" "\n"
+    "      PrintInlining: false," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", true);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    PrintInlining: [" "\n"
+    "      true," "\n"
+    "      false" "\n"
+    "    ]," "\n"
+    "  }" "\n"
+    "]" "\n", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {"
+    "    // pattern to match against class+method+signature" "\n"
+    "    // leading and trailing wildcard (*) allowed" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "" "\n"
+    "    // override defaults for specified compiler" "\n"
+    "    // we may differentiate between levels too. TBD." "\n"
+    "    c1:  {" "\n"
+    "      //override c1 presets " "\n"
+    "      DumpReplay: false," "\n"
+    "      BreakAtCompile: true," "\n"
+    "    }," "\n"
+    "" "\n"
+    "    c2: {" "\n"
+    "        // control inlining of method" "\n"
+    "        // + force inline, - dont inline" "\n"
+    "        inline : \"+java/util.*\"," "\n"
+    "        PrintInlining: true," "\n"
+    "    }," "\n"
+    "" "\n"
+    "    // directives outside a specific preset applies to all compilers" "\n"
+    "    inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
+    "    BreakAtExecute: true," "\n"
+    "    Log: true," "\n"
+    "  }," "\n"
+    "  {" "\n"
+    "    // matching several patterns require an array" "\n"
+    "    match: [\"baz.*\",\"frob.*\"]," "\n"
+    "" "\n"
+    "    // applies to all compilers" "\n"
+    "    // + force inline, - dont inline" "\n"
+    "    inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
+    "    PrintInlining: true," "\n"
+    "" "\n"
+    "    // force matching compiles to be blocking/syncronous" "\n"
+    "    PrintNMethods: true" "\n"
+    "  }," "\n"
+    "]" "\n", true);
+
+  // Test max stack depth
+    DirectivesParser::test(
+      "[" "\n"             // depth 1: type_dir_array
+      "  {" "\n"           // depth 2: type_directives
+      "    match: \"*.*\"," // match required
+      "    c1:" "\n"       // depth 3: type_c1
+      "    {" "\n"
+      "      inline:" "\n" // depth 4: type_inline
+      "      [" "\n"       // depth 5: type_value_array
+      "        \"foo\"," "\n"
+      "        \"bar\"," "\n"
+      "      ]" "\n"       // depth 3: pop type_value_array and type_inline keys
+      "    }" "\n"         // depth 2: pop type_c1 key
+      "  }" "\n"           // depth 1: pop type_directives key
+      "]" "\n", true);     // depth 0: pop type_dir_array key
+
+    // Test max stack depth
+    DirectivesParser::test(
+      "[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    c1: true," "\n"
+    "    c2: true," "\n"
+    "    match: true," "\n"
+    "    inline: true," "\n"
+    "    enable: true," "\n"
+    "    c1: {" "\n"
+    "      preset: true," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", false);
+
+  return true;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+#define SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+
+#include "utilities/json.hpp"
+#include "compiler/compilerDirectives.hpp"
+
+enum FlagType {
+  boolFlag,
+  intxFlag,
+  doubleFlag,
+  ccstrFlag,
+  ccstrlistFlag,
+  UnknownFlagType
+};
+
+static const char* flag_type_names[] = {
+    "bool",
+    "int",
+    "double",
+    "string",
+    "string list",
+    "unknown"
+};
+
+class DirectivesParser : public JSON {
+public:
+  static bool has_file();
+  static bool parse_from_flag();
+  static bool parse_from_file(const char* filename, outputStream* st);
+  static bool parse_string(const char* string, outputStream* st);
+  bool install_directives();
+
+private:
+  DirectivesParser(const char* text, outputStream* st);
+  ~DirectivesParser();
+
+  bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+  static bool parse_from_file_inner(const char* filename, outputStream* st);
+
+  // types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
+  typedef enum {
+     type_c1,
+     type_c2,
+     type_enable,
+     type_preset,
+     type_match,
+     type_inline,
+
+     // After here, there is no correlation between
+     // keytype and keys array
+     //type_strategy,
+     type_flag,
+     //type_dir,
+
+     // Synthetic.
+     type_dir_array,
+     type_directives,
+     type_value_array
+  } keytype;
+
+  // name, type, dtd info and maybe a setter
+  // this is how we map key-values
+  typedef struct {
+     const char *name;
+     keytype     type;
+     uint    allow_array_value : 1;
+     uint    allowedmask;
+     void (DirectiveSet::*set)(void* arg);
+     FlagType flag_type;
+  } key;
+
+  // Array with valid keys for the directive file
+  static const key keys[];
+  // Marker for outermost moosewings/array
+  static const key dir_array_key;
+  // Marker for a directives set (these are "implicit" objects, as in not named)
+  static const key dir_key;
+  // Marker for a multi value
+  static const key value_array_key;
+
+  // A compiler directive shouldn't be able to use more than 5 stack slots.
+  // Example of max stack usage:
+  // depth 1: type_dir_array  [
+  // depth 2: type_directives   {
+  // depth 3: type_c1             c1: {
+  // depth 4: type_inline           inline:
+  // depth 5: type_value_array      [ ...
+  static const uint MAX_DEPTH = 5;
+  const key* stack[MAX_DEPTH];
+  uint depth;
+
+  bool push_key(const char* str, size_t len);
+  bool push_key(const key* k);
+  const key* current_key();
+  const key* pop_key();
+  static const key* lookup_key(const char* s, size_t len);
+
+  bool set_option(JSON_TYPE t, JSON_VAL* v);
+  bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
+
+  CompilerDirectives* current_directive;
+  DirectiveSet*       current_directiveset;
+
+  void push_tmp(CompilerDirectives* dir);
+  CompilerDirectives* pop_tmp();
+  CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
+
+  static uint mask(keytype kt);
+
+#ifndef PRODUCT
+  static void test(const char* json, bool valid);
+public:
+  static bool test();
+#endif
+};
+
+#endif // SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
--- a/hotspot/src/share/vm/compiler/methodMatcher.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -320,13 +320,11 @@
 }
 
 void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
-  ResourceMark rm;
-
   if (mode == Suffix || mode == Substring || mode == Any) {
     st->print("*");
   }
   if (mode != Any) {
-    h->print_symbol_on(st);
+    h->print_utf8_on(st);
   }
   if (mode == Prefix || mode == Substring) {
     st->print("*");
@@ -334,14 +332,117 @@
 }
 
 void MethodMatcher::print_base(outputStream* st) {
+  ResourceMark rm;
+
   print_symbol(st, class_name(), _class_mode);
   st->print(".");
   print_symbol(st, method_name(), _method_mode);
   if (signature() != NULL) {
-    signature()->print_symbol_on(st);
+    signature()->print_utf8_on(st);
   }
 }
 
+BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+  assert(error_msg == NULL, "Don't call here with error_msg already set");
+  BasicMatcher* bm = new BasicMatcher();
+  MethodMatcher::parse_method_pattern(line, error_msg, bm);
+  if (error_msg != NULL) {
+    delete bm;
+    return NULL;
+  }
 
+  // check for bad trailing characters
+  int bytes_read = 0;
+  sscanf(line, "%*[ \t]%n", &bytes_read);
+  if (line[bytes_read] != '\0') {
+    error_msg = "Unrecognized trailing text after method pattern";
+    delete bm;
+    return NULL;
+  }
+  return bm;
+}
+
+bool BasicMatcher::match(methodHandle method) {
+  for (BasicMatcher* current = this; current != NULL; current = current->next()) {
+    if (current->matches(method)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void InlineMatcher::print(outputStream* st) {
+  if (_inline_action == InlineMatcher::force_inline) {
+    st->print("+");
+  } else {
+    st->print("-");
+  }
+  print_base(st);
+}
+
+InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+  assert(error_msg == NULL, "Dont call here with error_msg already set");
+  InlineMatcher* im = new InlineMatcher();
+  MethodMatcher::parse_method_pattern(line, error_msg, im);
+  if (error_msg != NULL) {
+    delete im;
+    return NULL;
+  }
+  return im;
+}
 
+bool InlineMatcher::match(methodHandle method, int inline_action) {
+  for (InlineMatcher* current = this; current != NULL; current = current->next()) {
+    if (current->matches(method)) {
+      return (current->_inline_action == inline_action);
+    }
+  }
+  return false;
+}
 
+InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error_msg) {
+  // check first token is +/-
+  InlineType _inline_action;
+   switch (str[0]) {
+   case '-':
+     _inline_action = InlineMatcher::dont_inline;
+     break;
+   case '+':
+     _inline_action = InlineMatcher::force_inline;
+     break;
+   default:
+     error_msg = "Missing leading inline type (+/-)";
+     return NULL;
+   }
+   str++;
+
+   int bytes_read = 0;
+   assert(error_msg== NULL, "error_msg must not be set yet");
+   InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
+   if (im == NULL) {
+     assert(error_msg != NULL, "Must have error message");
+     return NULL;
+   }
+   im->set_action(_inline_action);
+   return im;
+}
+
+InlineMatcher* InlineMatcher::clone() {
+   InlineMatcher* m = new InlineMatcher();
+   m->_class_mode =  _class_mode;
+   m->_method_mode = _method_mode;
+   m->_inline_action = _inline_action;
+   m->_class_name = _class_name;
+   if(_class_name != NULL) {
+     _class_name->increment_refcount();
+   }
+   m->_method_name = _method_name;
+   if (_method_name != NULL) {
+     _method_name->increment_refcount();
+   }
+   m->_signature = _signature;
+   if (_signature != NULL) {
+     _signature->increment_refcount();
+   }
+   return m;
+}
--- a/hotspot/src/share/vm/compiler/methodMatcher.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -81,35 +81,8 @@
     _next(next) {
   }
 
-  static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg) {
-    assert(error_msg == NULL, "Dont call here with error_msg already set");
-    BasicMatcher* bm = new BasicMatcher();
-    MethodMatcher::parse_method_pattern(line, error_msg, bm);
-    if (error_msg != NULL) {
-      delete bm;
-      return NULL;
-    }
-
-    // check for bad trailing characters
-    int bytes_read = 0;
-    sscanf(line, "%*[ \t]%n", &bytes_read);
-    if (line[bytes_read] != '\0') {
-      error_msg = "Unrecognized trailing text after method pattern";
-      delete bm;
-      return NULL;
-    }
-    return bm;
-  }
-
-  bool match(methodHandle method) {
-    for (BasicMatcher* current = this; current != NULL; current = current->next()) {
-      if (current->matches(method)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
+  static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
+  bool match(methodHandle method);
   void set_next(BasicMatcher* next) { _next = next; }
   BasicMatcher* next() { return _next; }
 
@@ -122,5 +95,33 @@
   }
 };
 
+class InlineMatcher : public MethodMatcher {
+public:
+  enum InlineType {
+      unknown_inline,
+      dont_inline,
+      force_inline
+    };
+
+private:
+  InlineType _inline_action;
+  InlineMatcher * _next;
+
+  InlineMatcher() : MethodMatcher(),
+    _inline_action(unknown_inline), _next(NULL) {
+  }
+
+public:
+  static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
+  bool match(methodHandle method, int inline_action);
+  void print(outputStream* st);
+  void set_next(InlineMatcher* next) { _next = next; }
+  InlineMatcher* next() { return _next; }
+  void set_action(InlineType inline_action) { _inline_action = inline_action; }
+  int inline_action() { return _inline_action; }
+  static InlineMatcher* parse_inline_pattern(char* line, const char*& error_msg);
+  InlineMatcher* clone();
+};
+
 #endif // SHARE_VM_COMPILER_METHODMATCHER_HPP
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -145,7 +145,7 @@
 
 
 // Compilation entry point for methods
-void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
   ShouldNotReachHere();
 }
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -69,7 +69,7 @@
   void bootstrap();
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
   void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
 
--- a/hotspot/src/share/vm/oops/symbol.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/oops/symbol.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -154,6 +154,10 @@
   return as_C_string(str, buf_len);
 }
 
+void Symbol::print_utf8_on(outputStream* st) const {
+  st->print("%s", as_C_string());
+}
+
 void Symbol::print_symbol_on(outputStream* st) const {
   ResourceMark rm;
   st = st ? st : tty;
--- a/hotspot/src/share/vm/oops/symbol.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/oops/symbol.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -225,6 +225,7 @@
 
   // Printing
   void print_symbol_on(outputStream* st = NULL) const;
+  void print_utf8_on(outputStream* st) const;
   void print_on(outputStream* st) const;         // First level print
   void print_value_on(outputStream* st) const;   // Second level print.
 
--- a/hotspot/src/share/vm/opto/block.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/block.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "libadt/vectset.hpp"
 #include "memory/allocation.inline.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "opto/block.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/chaitin.hpp"
@@ -365,7 +366,7 @@
 , _node_to_block_mapping(arena)
 , _node_latency(NULL)
 #ifndef PRODUCT
-, _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining"))
+, _trace_opto_pipelining(C->directive()->TraceOptoPipeliningOption)
 #endif
 #ifdef ASSERT
 , _raw_oops(arena)
--- a/hotspot/src/share/vm/opto/block.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/block.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -368,7 +368,6 @@
 class PhaseCFG : public Phase {
   friend class VMStructs;
  private:
-
   // Root of whole program
   RootNode* _root;
 
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -108,7 +108,7 @@
                                int caller_bci, ciCallProfile& profile,
                                WarmCallInfo* wci_result) {
   // Allows targeted inlining
-  if (callee_method->should_inline()) {
+  if (C->directive()->should_inline(callee_method)) {
     *wci_result = *(WarmCallInfo::always_hot());
     if (C->print_inlining() && Verbose) {
       CompileTask::print_inline_indent(inline_level());
@@ -222,12 +222,12 @@
   }
 
   // ignore heuristic controls on inlining
-  if (callee_method->should_inline()) {
+  if (C->directive()->should_inline(callee_method)) {
     set_msg("force inline by CompileCommand");
     return false;
   }
 
-  if (callee_method->should_not_inline()) {
+  if (C->directive()->should_not_inline(callee_method)) {
     set_msg("disallowed by CompileCommand");
     return true;
   }
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -154,7 +154,7 @@
   notproduct(bool, PrintOptoStatistics, false,                              \
           "Print New compiler statistics")                                  \
                                                                             \
-  notproduct(bool, PrintOptoAssembly, false,                                \
+  diagnostic(bool, PrintOptoAssembly, false,                                \
           "Print New compiler assembly output")                             \
                                                                             \
   develop_pd(bool, OptoPeephole,                                            \
@@ -342,6 +342,9 @@
   product(bool, SuperWordReductions, true,                                  \
           "Enable reductions support in superword.")                        \
                                                                             \
+  product(bool, UseCMoveUnconditionally, false,                             \
+          "Use CMove (scalar and vector) ignoring profitability test.")     \
+                                                                            \
   product(bool, DoReserveCopyInSuperWord, true,                             \
           "Create reserve copy of graph in SuperWord.")                     \
                                                                             \
@@ -368,18 +371,18 @@
   product(bool, UseRDPCForConstantTableBase, false,                         \
           "Use Sparc RDPC instruction for the constant table base.")        \
                                                                             \
-  develop(bool, PrintIdealGraph, false,                                     \
+  notproduct(bool, PrintIdealGraph, false,                                  \
           "Print ideal graph to XML file / network interface. "             \
           "By default attempts to connect to the visualizer on a socket.")  \
                                                                             \
-  develop(intx, PrintIdealGraphLevel, 0,                                    \
+  notproduct(intx, PrintIdealGraphLevel, 0,                                 \
           "Level of detail of the ideal graph printout. "                   \
-          "System-wide value, 0=nothing is printed, 3=all details printed. "\
+          "System-wide value, 0=nothing is printed, 4=all details printed. "\
           "Level of detail of printouts can be set on a per-method level "  \
           "as well by using CompileCommand=option.")                        \
-          range(0, 3)                                                       \
+          range(0, 4)                                                       \
                                                                             \
-  develop(intx, PrintIdealGraphPort, 4444,                                  \
+  notproduct(intx, PrintIdealGraphPort, 4444,                               \
           "Ideal graph printer to network port")                            \
           range(0, SHRT_MAX)                                                \
                                                                             \
@@ -632,7 +635,7 @@
   develop(bool, PrintDominators, false,                                     \
           "Print out dominator trees for GVN")                              \
                                                                             \
-  notproduct(bool, TraceSpilling, false,                                    \
+  diagnostic(bool, TraceSpilling, false,                                    \
           "Trace spilling")                                                 \
                                                                             \
   diagnostic(bool, TraceTypeProfile, false,                                 \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -94,15 +94,16 @@
   }
 }
 
-void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
   assert(is_initialized(), "Compiler thread must be initialized");
 
   bool subsume_loads = SubsumeLoads;
   bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
   bool eliminate_boxing = EliminateAutoBox;
+
   while (!env->failing()) {
     // Attempt to compile while subsuming loads into machine instructions.
-    Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing);
+    Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
 
     // Check result and retry if appropriate.
     if (C.failure_reason() != NULL) {
--- a/hotspot/src/share/vm/opto/c2compiler.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -41,7 +41,8 @@
   // Compilation entry point for methods
   void compile_method(ciEnv* env,
                       ciMethod* target,
-                      int entry_bci);
+                      int entry_bci,
+                      DirectiveSet* directive);
 
   // sentinel value used to trigger backtracking in compile_method().
   static const char* retry_no_subsuming_loads();
--- a/hotspot/src/share/vm/opto/chaitin.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -211,7 +211,7 @@
   , _scratch_int_pressure(0, INTPRESSURE)
   , _scratch_float_pressure(0, FLOATPRESSURE)
 #ifndef PRODUCT
-  , _trace_spilling(TraceSpilling || C->method_has_option("TraceSpilling"))
+  , _trace_spilling(C->directive()->TraceSpillingOption)
 #endif
 {
   Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]);
--- a/hotspot/src/share/vm/opto/classes.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -64,6 +64,7 @@
 macro(ClearArray)
 macro(ConstraintCast)
 macro(CMoveD)
+macro(CMoveVD)
 macro(CMoveF)
 macro(CMoveI)
 macro(CMoveL)
@@ -161,7 +162,6 @@
 macro(LoadRange)
 macro(LoadS)
 macro(Lock)
-macro(LogD)
 macro(Log10D)
 macro(Loop)
 macro(LoopLimit)
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -464,7 +464,7 @@
   Type::Initialize(compile);
   _compile->set_scratch_buffer_blob(NULL);
   _compile->begin_method();
-  _compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name));
+  _compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
 }
 CompileWrapper::~CompileWrapper() {
   _compile->end_method();
@@ -496,7 +496,7 @@
     tty->print_cr("** Bailout: Recompile without boxing elimination       **");
     tty->print_cr("*********************************************************");
   }
-  if (env()->break_at_compile()) {
+  if (C->directive()->BreakAtCompileOption) {
     // Open the debugger when compiling this method.
     tty->print("### Breaking when compiling: ");
     method()->print_short_name();
@@ -617,9 +617,10 @@
 
 
 Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci,
-                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing )
+                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
                 : Phase(Compiler),
                   _env(ci_env),
+                  _directive(directive),
                   _log(ci_env->log()),
                   _compile_id(ci_env->compile_id()),
                   _save_argument_registers(false),
@@ -649,7 +650,7 @@
                   _dead_node_list(comp_arena()),
                   _dead_node_count(0),
 #ifndef PRODUCT
-                  _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
+                  _trace_opto_output(directive->TraceOptoOutputOption),
                   _in_dump_cnt(0),
                   _printer(IdealGraphPrinter::printer()),
 #endif
@@ -673,7 +674,11 @@
                   _interpreter_frame_size(0),
                   _max_node_limit(MaxNodeLimit) {
   C = this;
-
+#ifndef PRODUCT
+  if (_printer != NULL) {
+    _printer->set_compile(this);
+  }
+#endif
   CompileWrapper cw(this);
 
   if (CITimeVerbose) {
@@ -687,9 +692,9 @@
   TraceTime t2(NULL, &_t_methodCompilation, CITime, false);
 
 #ifndef PRODUCT
-  bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly");
+  bool print_opto_assembly = directive->PrintOptoAssemblyOption;
   if (!print_opto_assembly) {
-    bool print_assembly = (PrintAssembly || _method->should_print_assembly());
+    bool print_assembly = directive->PrintAssemblyOption;
     if (print_assembly && !Disassembler::can_decode()) {
       tty->print_cr("PrintAssembly request changed to PrintOptoAssembly");
       print_opto_assembly = true;
@@ -698,12 +703,12 @@
   set_print_assembly(print_opto_assembly);
   set_parsed_irreducible_loop(false);
 
-  if (method()->has_option("ReplayInline")) {
+  if (directive->ReplayInlineOption) {
     _replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level());
   }
 #endif
-  set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
-  set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
+  set_print_inlining(directive->PrintInliningOption NOT_PRODUCT( || PrintOptoInlining));
+  set_print_intrinsics(directive->PrintIntrinsicsOption);
   set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
 
   if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
@@ -837,8 +842,8 @@
   // Drain the list.
   Finish_Warm();
 #ifndef PRODUCT
-  if (_printer && _printer->should_print(_method)) {
-    _printer->print_inlining(this);
+  if (_printer && _printer->should_print(1)) {
+    _printer->print_inlining();
   }
 #endif
 
@@ -871,10 +876,10 @@
   NOT_PRODUCT( verify_barriers(); )
 
   // Dump compilation data to replay it.
-  if (method()->has_option("DumpReplay")) {
+  if (directive->DumpReplayOption) {
     env()->dump_replay_data(_compile_id);
   }
-  if (method()->has_option("DumpInline") && (ilt() != NULL)) {
+  if (directive->DumpInlineOption && (ilt() != NULL)) {
     env()->dump_inline_data(_compile_id);
   }
 
@@ -918,9 +923,9 @@
                            frame_size_in_words(), _oop_map_set,
                            &_handler_table, &_inc_table,
                            compiler,
-                           env()->comp_level(),
                            has_unsafe_access(),
                            SharedRuntime::is_wide_vector(max_vector_size()),
+                           _directive,
                            rtm_state()
                            );
 
@@ -938,9 +943,11 @@
                   int is_fancy_jump,
                   bool pass_tls,
                   bool save_arg_registers,
-                  bool return_pc )
+                  bool return_pc,
+                  DirectiveSet* directive)
   : Phase(Compiler),
     _env(ci_env),
+    _directive(directive),
     _log(ci_env->log()),
     _compile_id(0),
     _save_argument_registers(save_arg_registers),
@@ -1090,7 +1097,7 @@
   Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
   set_decompile_count(0);
 
-  set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
+  set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption);
   set_num_loop_opts(LoopOptsCount);
   set_do_inlining(Inline);
   set_max_inline_size(MaxInlineSize);
@@ -1101,24 +1108,22 @@
 
   set_do_vector_loop(false);
 
-  bool do_vector = false;
   if (AllowVectorizeOnDemand) {
-    if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) {
+    if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) {
       set_do_vector_loop(true);
+      NOT_PRODUCT(if (do_vector_loop() && Verbose) {tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n",  method()->name()->as_quoted_ascii());})
     } else if (has_method() && method()->name() != 0 &&
                method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
       set_do_vector_loop(true);
     }
-#ifndef PRODUCT
-    if (do_vector_loop() && Verbose) {
-      tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n",  method()->name()->as_quoted_ascii());
-    }
-#endif
   }
+  set_use_cmove(UseCMoveUnconditionally /* || do_vector_loop()*/); //TODO: consider do_vector_loop() mandate use_cmove unconditionally
+  NOT_PRODUCT(if (use_cmove() && Verbose && has_method()) {tty->print("Compile::Init: use CMove without profitability tests for method %s\n",  method()->name()->as_quoted_ascii());})
 
   set_age_code(has_method() && method()->profile_aging());
   set_rtm_state(NoRTM); // No RTM lock eliding by default
-  method_has_option_value("MaxNodeLimit", _max_node_limit);
+  _max_node_limit = _directive->MaxNodeLimitOption;
+
 #if INCLUDE_RTM_OPT
   if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
     int rtm_state = method()->method_data()->rtm_state();
@@ -2091,7 +2096,7 @@
   TracePhase tp("optimizer", &timers[_t_optimizer]);
 
 #ifndef PRODUCT
-  if (env()->break_at_compile()) {
+  if (_directive->BreakAtCompileOption) {
     BREAKPOINT;
   }
 
@@ -4357,7 +4362,6 @@
   return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
 }
 
-const char*   CloneMap::debug_option_name = "CloneMapDebug";
 CloneMap&     Compile::clone_map()                 { return _clone_map; }
 void          Compile::set_clone_map(Dict* d)      { _clone_map._dict = d; }
 
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -374,6 +374,7 @@
   bool                  _do_count_invocations;  // True if we generate code to count invocations
   bool                  _do_method_data_update; // True if we generate code to update MethodData*s
   bool                  _do_vector_loop;        // True if allowed to execute loop in parallel iterations
+  bool                  _use_cmove;             // True if CMove should be used without profitability analysis
   bool                  _age_code;              // True if we need to profile code age (decrement the aging counter)
   int                   _AliasLevel;            // Locally-adjusted version of AliasLevel flag.
   bool                  _print_assembly;        // True if we should dump assembly code for this compilation
@@ -391,6 +392,7 @@
   // Compilation environment.
   Arena                 _comp_arena;            // Arena with lifetime equivalent to Compile
   ciEnv*                _env;                   // CI interface
+  DirectiveSet*         _directive;             // Compiler directive
   CompileLog*           _log;                   // from CompilerThread
   const char*           _failure_reason;        // for record_failure/failing pattern
   GrowableArray<CallGenerator*>* _intrinsics;   // List of intrinsics.
@@ -527,6 +529,10 @@
     print_inlining_stream()->print("%s", ss.as_string());
   }
 
+#ifndef PRODUCT
+  IdealGraphPrinter* printer() { return _printer; }
+#endif
+
   void log_late_inline(CallGenerator* cg);
   void log_inline_id(CallGenerator* cg);
   void log_inline_failure(const char* msg);
@@ -578,6 +584,7 @@
 
   // ID for this compilation.  Useful for setting breakpoints in the debugger.
   int               compile_id() const          { return _compile_id; }
+  DirectiveSet*     directive() const           { return _directive; }
 
   // Does this compilation allow instructions to subsume loads?  User
   // instructions that subsume a load may result in an unschedulable
@@ -651,6 +658,8 @@
   void          set_do_method_data_update(bool z) { _do_method_data_update = z; }
   bool              do_vector_loop() const      { return _do_vector_loop; }
   void          set_do_vector_loop(bool z)      { _do_vector_loop = z; }
+  bool              use_cmove() const           { return _use_cmove; }
+  void          set_use_cmove(bool z)           { _use_cmove = z; }
   bool              age_code() const             { return _age_code; }
   void          set_age_code(bool z)             { _age_code = z; }
   int               AliasLevel() const           { return _AliasLevel; }
@@ -671,10 +680,7 @@
   bool          method_has_option(const char * option) {
     return method() != NULL && method()->has_option(option);
   }
-  template<typename T>
-  bool          method_has_option_value(const char * option, T& value) {
-    return method() != NULL && method()->has_option_value(option, value);
-  }
+
 #ifndef PRODUCT
   bool          trace_opto_output() const       { return _trace_opto_output; }
   bool              parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
@@ -692,8 +698,8 @@
 
   void begin_method() {
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
-      _printer->begin_method(this);
+    if (_printer && _printer->should_print(1)) {
+      _printer->begin_method();
     }
 #endif
     C->_latest_stage_start_counter.stamp();
@@ -711,8 +717,8 @@
 
 
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
-      _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
+    if (_printer && _printer->should_print(level)) {
+      _printer->print_method(CompilerPhaseTypeHelper::to_string(cpt), level);
     }
 #endif
     C->_latest_stage_start_counter.stamp();
@@ -728,7 +734,7 @@
       event.commit();
     }
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
+    if (_printer && _printer->should_print(level)) {
       _printer->end_method();
     }
 #endif
@@ -1107,7 +1113,7 @@
   // continuation.
   Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
           int entry_bci, bool subsume_loads, bool do_escape_analysis,
-          bool eliminate_boxing);
+          bool eliminate_boxing, DirectiveSet* directive);
 
   // Second major entry point.  From the TypeFunc signature, generate code
   // to pass arguments from the Java calling convention to the C calling
@@ -1115,7 +1121,7 @@
   Compile(ciEnv* ci_env, const TypeFunc *(*gen)(),
           address stub_function, const char *stub_name,
           int is_fancy_jump, bool pass_tls,
-          bool save_arg_registers, bool return_pc);
+          bool save_arg_registers, bool return_pc, DirectiveSet* directive);
 
   // From the TypeFunc signature, generate code to pass arguments
   // from Compiled calling convention to Interpreter's calling convention
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -292,11 +292,11 @@
 
 }
 
-void IdealGraphPrinter::print_inlining(Compile* compile) {
+void IdealGraphPrinter::print_inlining() {
 
   // Print inline tree
   if (_should_send_method) {
-    InlineTree *inlineTree = compile->ilt();
+    InlineTree *inlineTree = C->ilt();
     if (inlineTree != NULL) {
       print_inline_tree(inlineTree);
     } else {
@@ -306,9 +306,9 @@
 }
 
 // Has to be called whenever a method is compiled
-void IdealGraphPrinter::begin_method(Compile* compile) {
+void IdealGraphPrinter::begin_method() {
 
-  ciMethod *method = compile->method();
+  ciMethod *method = C->method();
   assert(_output, "output stream must exist!");
   assert(method, "null methods are not allowed!");
   assert(!_current_method, "current method must be null!");
@@ -662,16 +662,14 @@
   }
 }
 
-void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) {
-  print(compile, name, (Node *)compile->root(), level, clear_nodes);
+void IdealGraphPrinter::print_method(const char *name, int level, bool clear_nodes) {
+  print(name, (Node *)C->root(), level, clear_nodes);
 }
 
 // Print current ideal graph
-void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {
+void IdealGraphPrinter::print(const char *name, Node *node, int level, bool clear_nodes) {
 
-  if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return;
-
-  this->C = compile;
+  if (!_current_method || !_should_send_method || !should_print(level)) return;
 
   // Warning, unsafe cast?
   _chaitin = (PhaseChaitin *)C->regalloc();
@@ -722,10 +720,8 @@
 }
 
 // Should method be printed?
-bool IdealGraphPrinter::should_print(ciMethod* method, int level) {
-  intx ideal_graph_level = PrintIdealGraphLevel;
-  method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
-  return ideal_graph_level >= level;
+bool IdealGraphPrinter::should_print(int level) {
+  return C->directive()->IGVPrintLevelOption >= level;
 }
 
 extern const char *NodeClassNames[];
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -127,13 +127,14 @@
 
   bool traverse_outs();
   void set_traverse_outs(bool b);
-  void print_inlining(Compile* compile);
-  void begin_method(Compile* compile);
+  void print_inlining();
+  void begin_method();
   void end_method();
-  void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false);
-  void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false);
+  void print_method(const char *name, int level=1, bool clear_nodes = false);
+  void print(const char *name, Node *root, int level=1, bool clear_nodes = false);
   void print_xml(const char *name);
-  static bool should_print(ciMethod* method, int level = 1);
+  bool should_print(int level);
+  void set_compile(Compile* compile) {C = compile; }
 };
 
 #endif
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -326,9 +326,10 @@
     // methods access VM-internal data.
     VM_ENTRY_MARK;
     methodHandle mh(THREAD, m->get_Method());
-    methodHandle ct(THREAD, method()->get_Method());
     is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
-                   !vmIntrinsics::is_disabled_by_flags(mh, ct);
+                   !C->directive()->is_intrinsic_disabled(mh) &&
+                   !vmIntrinsics::is_disabled_by_flags(mh);
+
   }
 
   if (is_available) {
@@ -1368,7 +1369,6 @@
   switch (id) {
   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
-  case vmIntrinsics::_dlog:   n = new LogDNode(C, control(),   arg);  break;
   case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg);  break;
   default:  fatal_unexpected_iid(id);  break;
   }
@@ -1752,7 +1752,9 @@
   case vmIntrinsics::_dtan:   return Matcher::has_match_rule(Op_TanD)   ? inline_trig(id) :
     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan),   "TAN");
 
-  case vmIntrinsics::_dlog:   return Matcher::has_match_rule(Op_LogD)   ? inline_math(id) :
+  case vmIntrinsics::_dlog:
+    return StubRoutines::dlog() != NULL ?
+    runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog),   "LOG");
   case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
--- a/hotspot/src/share/vm/opto/loopnode.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopnode.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -1143,7 +1143,7 @@
 // dominated in the outer loop by this node chain:
 //   intcon(1)->If->IfFalse->reserved_copy.
 // The original loop is dominated by the the same node chain but IfTrue projection:
-//   intcon(1)->If->IfTrue->original_loop.
+//   intcon(0)->If->IfTrue->original_loop.
 //
 // In this implementation of CountedLoopReserveKit the ctor includes create_reserve()
 // and the dtor, checks _use_new value.
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -512,8 +512,11 @@
     PhiNode* phi = out->as_Phi();
     BasicType bt = phi->type()->basic_type();
     switch (bt) {
-    case T_FLOAT:
-    case T_DOUBLE: {
+    case T_DOUBLE:
+      if (C->use_cmove()) {
+        continue; //TODO: maybe we want to add some cost
+      }
+    case T_FLOAT: {
       cost += Matcher::float_cmove_cost(); // Could be very expensive
       break;
     }
@@ -573,7 +576,7 @@
         }
       }
     }
-  }
+  }//for
   Node* bol = iff->in(1);
   assert(bol->Opcode() == Op_Bool, "");
   int cmp_op = bol->in(1)->Opcode();
@@ -595,7 +598,8 @@
   }
   // Check for highly predictable branch.  No point in CMOV'ing if
   // we are going to predict accurately all the time.
-  if (iff->_prob < infrequent_prob ||
+  if (C->use_cmove() && cmp_op == Op_CmpD) ;//keep going
+  else if (iff->_prob < infrequent_prob ||
       iff->_prob > (1.0f - infrequent_prob))
     return NULL;
 
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2316,7 +2316,8 @@
       case Op_CMoveI:
       case Op_CMoveL:
       case Op_CMoveN:
-      case Op_CMoveP: {
+      case Op_CMoveP:
+      case Op_CMoveVD:  {
         // Restructure into a binary tree for Matching.  It's possible that
         // we could move this code up next to the graph reshaping for IfNodes
         // or vice-versa, but I do not want to debug this for Ladybird.
--- a/hotspot/src/share/vm/opto/output.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -28,6 +28,7 @@
 #include "code/debugInfo.hpp"
 #include "code/debugInfoRec.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "compiler/oopMap.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/ad.hpp"
@@ -89,9 +90,8 @@
 
   }
 
-
   // Break before main entry point
-  if( (_method && _method->break_at_execute())
+  if( (_method && C->directive()->BreakAtExecuteOption)
 #ifndef PRODUCT
     ||(OptoBreakpoint && is_method_compilation())
     ||(OptoBreakpointOSR && is_osr_compilation())
--- a/hotspot/src/share/vm/opto/parse2.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2378,13 +2378,13 @@
   }
 
 #ifndef PRODUCT
-  IdealGraphPrinter *printer = IdealGraphPrinter::printer();
-  if (printer && printer->should_print(_method)) {
+  IdealGraphPrinter *printer = C->printer();
+  if (printer && printer->should_print(1)) {
     char buffer[256];
     sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
     bool old = printer->traverse_outs();
     printer->set_traverse_outs(true);
-    printer->print_method(C, buffer, 4);
+    printer->print_method(buffer, 4);
     printer->set_traverse_outs(old);
   }
 #endif
--- a/hotspot/src/share/vm/opto/runtime.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -159,9 +159,13 @@
                                     const char *name, int is_fancy_jump,
                                     bool pass_tls,
                                     bool save_argument_registers,
-                                    bool return_pc ) {
+                                    bool return_pc) {
+
+  // Matching the default directive, we currently have no method to match.
+  DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
   ResourceMark rm;
-  Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc );
+  Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc, directive);
+  DirectivesStack::release(directive);
   return  C.stub_entry_point();
 }
 
--- a/hotspot/src/share/vm/opto/subnode.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -1510,17 +1510,6 @@
 
 //=============================================================================
 //------------------------------Value------------------------------------------
-// Compute log
-const Type *LogDNode::Value( PhaseTransform *phase ) const {
-  const Type *t1 = phase->type( in(1) );
-  if( t1 == Type::TOP ) return Type::TOP;
-  if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
-  double d = t1->getd();
-  return TypeD::make( StubRoutines::intrinsic_log( d ) );
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
 // Compute log10
 const Type *Log10DNode::Value( PhaseTransform *phase ) const {
   const Type *t1 = phase->type( in(1) );
--- a/hotspot/src/share/vm/opto/subnode.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/subnode.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -477,20 +477,6 @@
   virtual const Type *Value( PhaseTransform *phase ) const;
 };
 
-//------------------------------LogDNode---------------------------------------
-// Log_e of a double
-class LogDNode : public Node {
-public:
-  LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
-    init_flags(Flag_is_expensive);
-    C->add_expensive_node(this);
-  }
-  virtual int Opcode() const;
-  const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual uint ideal_reg() const { return Op_RegD; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-};
-
 //------------------------------Log10DNode---------------------------------------
 // Log_10 of a double
 class Log10DNode : public Node {
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -37,6 +37,7 @@
 #include "opto/opaquenode.hpp"
 #include "opto/superword.hpp"
 #include "opto/vectornode.hpp"
+#include "opto/movenode.hpp"
 
 //
 //                  S U P E R W O R D   T R A N S F O R M
@@ -55,6 +56,7 @@
   _mem_slice_tail(arena(), 8,  0, NULL),  // memory slice tails
   _node_info(arena(), 8,  0, SWNodeInfo::initial), // info needed per node
   _clone_map(phase->C->clone_map()),      // map of nodes created in cloning
+  _cmovev_kit(_arena, this),              // map to facilitate CMoveVD creation
   _align_to_ref(NULL),                    // memory reference to align vectors to
   _disjoint_ptrs(arena(), 8,  0, OrderedPair::initial), // runtime disambiguated pointer pairs
   _dg(_arena),                            // dependence graph
@@ -72,6 +74,7 @@
   _num_work_vecs(0),                      // amount of vector work we have
   _num_reductions(0),                     // amount of reduction work we have
   _do_vector_loop(phase->C->do_vector_loop()),  // whether to do vectorization/simd style
+  _do_reserve_copy(DoReserveCopyInSuperWord),
   _ii_first(-1),                          // first loop generation index - only if do_vector_loop()
   _ii_last(-1),                           // last loop generation index - only if do_vector_loop()
   _ii_order(arena(), 8, 0, 0)
@@ -79,12 +82,9 @@
 #ifndef PRODUCT
   _vector_loop_debug = 0;
   if (_phase->C->method() != NULL) {
-    _phase->C->method()->has_option_value("VectorizeDebug", _vector_loop_debug);
+    _vector_loop_debug = phase->C->directive()->VectorizeDebugOption;
   }
-  _CountedLoopReserveKit_debug = 0;
-  if (_phase->C->method() != NULL) {
-    _phase->C->method()->has_option_value("DoReserveCopyInSuperWordDebug", _CountedLoopReserveKit_debug);
-  }
+
 #endif
 }
 
@@ -102,7 +102,18 @@
   if (!cl->is_main_loop() ) return; // skip normal, pre, and post loops
   // Check for no control flow in body (other than exit)
   Node *cl_exit = cl->loopexit();
-  if (cl_exit->in(0) != lpt->_head) return;
+  if (cl_exit->in(0) != lpt->_head) {
+    #ifndef PRODUCT
+      if (TraceSuperWord) {
+        tty->print_cr("SuperWord::transform_loop: loop too complicated, cl_exit->in(0) != lpt->_head");
+        tty->print("cl_exit %d", cl_exit->_idx); cl_exit->dump();
+        tty->print("cl_exit->in(0) %d", cl_exit->in(0)->_idx); cl_exit->in(0)->dump();
+        tty->print("lpt->_head %d", lpt->_head->_idx); lpt->_head->dump();
+        lpt->dump_head();
+      }
+    #endif
+    return;
+  }
 
   // Make sure the are no extra control users of the loop backedge
   if (cl->back_control()->outcnt() != 1) {
@@ -391,6 +402,10 @@
 
   construct_my_pack_map();
 
+  if (_do_vector_loop) {
+    merge_packs_to_cmovd();
+  }
+
   filter_packs();
 
   schedule();
@@ -1071,6 +1086,17 @@
 
 //------------------------------data_size---------------------------
 int SuperWord::data_size(Node* s) {
+  Node* use = NULL; //test if the node is a candidate for CMoveVD optimization, then return the size of CMov
+  if (_do_vector_loop) {
+    use = _cmovev_kit.is_Bool_candidate(s);
+    if (use != NULL) {
+      return data_size(use);
+    }
+    use = _cmovev_kit.is_CmpD_candidate(s);
+    if (use != NULL) {
+      return data_size(use);
+    }
+  }
   int bsize = type2aelembytes(velt_basic_type(s));
   assert(bsize != 0, "valid size");
   return bsize;
@@ -1117,6 +1143,7 @@
   if (s1->is_Load()) return false;
 
   int align = alignment(s1);
+  NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: s1 %d, align %d", s1->_idx, align);)
   bool changed = false;
   int start = s1->is_Store() ? MemNode::ValueIn   : 1;
   int end   = s1->is_Store() ? MemNode::ValueIn+1 : s1->req();
@@ -1131,6 +1158,7 @@
         pair->push(t1);
         pair->push(t2);
         _packset.append(pair);
+        NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: set_alignment(%d, %d, %d)", t1->_idx, t2->_idx, align);)
         set_alignment(t1, t2, align);
         changed = true;
       }
@@ -1152,6 +1180,7 @@
   if (s1->is_Store()) return false;
 
   int align = alignment(s1);
+  NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: s1 %d, align %d", s1->_idx, align);)
   int savings = -1;
   int num_s1_uses = 0;
   Node* u1 = NULL;
@@ -1183,6 +1212,7 @@
     pair->push(u1);
     pair->push(u2);
     _packset.append(pair);
+    NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: set_alignment(%d, %d, %d)", u1->_idx, u2->_idx, align);)
     set_alignment(u1, u2, align);
     changed = true;
   }
@@ -1458,6 +1488,196 @@
 #endif
 }
 
+//------------------------------merge_packs_to_cmovd---------------------------
+// Merge CMoveD into new vector-nodes
+// We want to catch this pattern and subsume CmpD and Bool into CMoveD
+//
+//                   SubD             ConD
+//                  /  |               /
+//                 /   |           /   /
+//                /    |       /      /
+//               /     |   /         /
+//              /      /            /
+//             /    /  |           /
+//            v /      |          /
+//         CmpD        |         /
+//          |          |        /
+//          v          |       /
+//         Bool        |      /
+//           \         |     /
+//             \       |    /
+//               \     |   /
+//                 \   |  /
+//                   \ v /
+//                   CMoveD
+//
+
+void SuperWord::merge_packs_to_cmovd() {
+  for (int i = _packset.length() - 1; i >= 0; i--) {
+    _cmovev_kit.make_cmovevd_pack(_packset.at(i));
+  }
+  #ifndef PRODUCT
+    if (TraceSuperWord) {
+      tty->print_cr("\nSuperWord::merge_packs_to_cmovd(): After merge");
+      print_packset();
+      tty->cr();
+    }
+  #endif
+}
+
+Node* CMoveKit::is_Bool_candidate(Node* def) const {
+  Node* use = NULL;
+  if (!def->is_Bool() || def->in(0) != NULL || def->outcnt() != 1) {
+    return NULL;
+  }
+  for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
+    use = def->fast_out(j);
+    if (!_sw->same_generation(def, use) || !use->is_CMove()) {
+      return NULL;
+    }
+  }
+  return use;
+}
+
+Node* CMoveKit::is_CmpD_candidate(Node* def) const {
+  Node* use = NULL;
+  if (!def->is_Cmp() || def->in(0) != NULL || def->outcnt() != 1) {
+    return NULL;
+  }
+  for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
+    use = def->fast_out(j);
+    if (!_sw->same_generation(def, use) || (use = is_Bool_candidate(use)) == NULL || !_sw->same_generation(def, use)) {
+      return NULL;
+    }
+  }
+  return use;
+}
+
+Node_List* CMoveKit::make_cmovevd_pack(Node_List* cmovd_pk) {
+  Node *cmovd = cmovd_pk->at(0);
+  if (!cmovd->is_CMove()) {
+    return NULL;
+  }
+  if (pack(cmovd) != NULL) { // already in the cmov pack
+    return NULL;
+  }
+  if (cmovd->in(0) != NULL) {
+    NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CMoveD %d has control flow, escaping...", cmovd->_idx); cmovd->dump();})
+    return NULL;
+  }
+
+  Node* bol = cmovd->as_CMove()->in(CMoveNode::Condition);
+  if (!bol->is_Bool()
+      || bol->outcnt() != 1
+      || !_sw->same_generation(bol, cmovd)
+      || bol->in(0) != NULL  // BoolNode has control flow!!
+      || _sw->my_pack(bol) == NULL) {
+      NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: Bool %d does not fit CMoveD %d for building vector, escaping...", bol->_idx, cmovd->_idx); bol->dump();})
+      return NULL;
+  }
+  Node_List* bool_pk = _sw->my_pack(bol);
+  if (bool_pk->size() != cmovd_pk->size() ) {
+    return NULL;
+  }
+
+  Node* cmpd = bol->in(1);
+  if (!cmpd->is_Cmp()
+      || cmpd->outcnt() != 1
+      || !_sw->same_generation(cmpd, cmovd)
+      || cmpd->in(0) != NULL  // CmpDNode has control flow!!
+      || _sw->my_pack(cmpd) == NULL) {
+      NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CmpD %d does not fit CMoveD %d for building vector, escaping...", cmpd->_idx, cmovd->_idx); cmpd->dump();})
+      return NULL;
+  }
+  Node_List* cmpd_pk = _sw->my_pack(cmpd);
+  if (cmpd_pk->size() != cmovd_pk->size() ) {
+    return NULL;
+  }
+
+  if (!test_cmpd_pack(cmpd_pk, cmovd_pk)) {
+    NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: cmpd pack for CmpD %d failed vectorization test", cmpd->_idx); cmpd->dump();})
+    return NULL;
+  }
+
+  Node_List* new_cmpd_pk = new Node_List();
+  uint sz = cmovd_pk->size() - 1;
+  for (uint i = 0; i <= sz; ++i) {
+    Node* cmov = cmovd_pk->at(i);
+    Node* bol  = bool_pk->at(i);
+    Node* cmp  = cmpd_pk->at(i);
+
+    new_cmpd_pk->insert(i, cmov);
+
+    map(cmov, new_cmpd_pk);
+    map(bol, new_cmpd_pk);
+    map(cmp, new_cmpd_pk);
+
+    _sw->set_my_pack(cmov, new_cmpd_pk); // and keep old packs for cmp and bool
+  }
+  _sw->_packset.remove(cmovd_pk);
+  _sw->_packset.remove(bool_pk);
+  _sw->_packset.remove(cmpd_pk);
+  _sw->_packset.append(new_cmpd_pk);
+  NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print_cr("CMoveKit::make_cmovevd_pack: added syntactic CMoveD pack"); _sw->print_pack(new_cmpd_pk);})
+  return new_cmpd_pk;
+}
+
+bool CMoveKit::test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk) {
+  Node* cmpd0 = cmpd_pk->at(0);
+  assert(cmpd0->is_Cmp(), "CMoveKit::test_cmpd_pack: should be CmpDNode");
+  assert(cmovd_pk->at(0)->is_CMove(), "CMoveKit::test_cmpd_pack: should be CMoveD");
+  assert(cmpd_pk->size() == cmovd_pk->size(), "CMoveKit::test_cmpd_pack: should be same size");
+  Node* in1 = cmpd0->in(1);
+  Node* in2 = cmpd0->in(2);
+  Node_List* in1_pk = _sw->my_pack(in1);
+  Node_List* in2_pk = _sw->my_pack(in2);
+
+  if (in1_pk != NULL && in1_pk->size() != cmpd_pk->size()
+    || in2_pk != NULL && in2_pk->size() != cmpd_pk->size() ) {
+    return false;
+  }
+
+  // test if "all" in1 are in the same pack or the same node
+  if (in1_pk == NULL) {
+    for (uint j = 1; j < cmpd_pk->size(); j++) {
+      if (cmpd_pk->at(j)->in(1) != in1) {
+        return false;
+      }
+    }//for: in1_pk is not pack but all CmpD nodes in the pack have the same in(1)
+  }
+  // test if "all" in2 are in the same pack or the same node
+  if (in2_pk == NULL) {
+    for (uint j = 1; j < cmpd_pk->size(); j++) {
+      if (cmpd_pk->at(j)->in(2) != in2) {
+        return false;
+      }
+    }//for: in2_pk is not pack but all CmpD nodes in the pack have the same in(2)
+  }
+  //now check if cmpd_pk may be subsumed in vector built for cmovd_pk
+  int cmovd_ind1, cmovd_ind2;
+  if (cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
+   && cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
+      cmovd_ind1 = CMoveNode::IfFalse;
+      cmovd_ind2 = CMoveNode::IfTrue;
+  } else if (cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
+          && cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
+      cmovd_ind2 = CMoveNode::IfFalse;
+      cmovd_ind1 = CMoveNode::IfTrue;
+  }
+  else {
+    return false;
+  }
+
+  for (uint j = 1; j < cmpd_pk->size(); j++) {
+    if (cmpd_pk->at(j)->in(1) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind1)
+        || cmpd_pk->at(j)->in(2) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind2)) {
+        return false;
+    }//if
+  }
+  NOT_PRODUCT(if(_sw->is_trace_cmov()) { tty->print("CMoveKit::test_cmpd_pack: cmpd pack for 1st CmpD %d is OK for vectorization: ", cmpd0->_idx); cmpd0->dump(); })
+  return true;
+}
+
 //------------------------------implemented---------------------------
 // Can code be generated for pack p?
 bool SuperWord::implemented(Node_List* p) {
@@ -1477,21 +1697,31 @@
     } else {
       retValue = VectorNode::implemented(opc, size, velt_basic_type(p0));
     }
+    if (!retValue) {
+      if (is_cmov_pack(p)) {
+        NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::implemented: found cmpd pack"); print_pack(p);})
+        return true;
+      }
+    }
   }
   return retValue;
 }
 
+bool SuperWord::is_cmov_pack(Node_List* p) {
+  return _cmovev_kit.pack(p->at(0)) != NULL;
+}
 //------------------------------same_inputs--------------------------
 // For pack p, are all idx operands the same?
-static bool same_inputs(Node_List* p, int idx) {
+bool SuperWord::same_inputs(Node_List* p, int idx) {
   Node* p0 = p->at(0);
   uint vlen = p->size();
   Node* p0_def = p0->in(idx);
   for (uint i = 1; i < vlen; i++) {
     Node* pi = p->at(i);
     Node* pi_def = pi->in(idx);
-    if (p0_def != pi_def)
+    if (p0_def != pi_def) {
       return false;
+    }
   }
   return true;
 }
@@ -1509,8 +1739,9 @@
   // the same. Later, implement PackNode and allow differing, non-vector inputs
   // (maybe just the ones from outside the block.)
   for (uint i = start; i < end; i++) {
-    if (!is_vector_use(p0, i))
+    if (!is_vector_use(p0, i)) {
       return false;
+    }
   }
   // Check if reductions are connected
   if (p0->is_reduction()) {
@@ -1541,6 +1772,9 @@
     // just the ones outside the block.)
     for (uint i = 0; i < p->size(); i++) {
       Node* def = p->at(i);
+      if (is_cmov_pack_internal_node(p, def)) {
+        continue;
+      }
       for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
         Node* use = def->fast_out(j);
         for (uint k = 0; k < use->req(); k++) {
@@ -1810,14 +2044,14 @@
   uint max_vlen_in_bytes = 0;
   uint max_vlen = 0;
 
-  NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
-
-  CountedLoopReserveKit make_reversable(_phase, _lpt, DoReserveCopyInSuperWord);
-
-  NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
-
-  if (DoReserveCopyInSuperWord && !make_reversable.has_reserved()) {
-    NOT_PRODUCT({tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
+  NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
+
+  CountedLoopReserveKit make_reversable(_phase, _lpt, do_reserve_copy());
+
+  NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
+
+  if (do_reserve_copy() && !make_reversable.has_reserved()) {
+    NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
     return;
   }
 
@@ -1830,6 +2064,7 @@
       Node* vn = NULL;
       Node* low_adr = p->at(0);
       Node* first   = executed_first(p);
+      NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d executed first, %d executed last in pack", first->_idx, n->_idx); print_pack(p);})
       int   opc = n->Opcode();
       if (n->is_Load()) {
         Node* ctl = n->in(MemNode::Control);
@@ -1855,13 +2090,21 @@
       } else if (n->is_Store()) {
         // Promote value to be stored to vector
         Node* val = vector_opd(p, MemNode::ValueIn);
+        if (val == NULL) {
+          if (do_reserve_copy()) {
+            NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");})
+            return; //and reverse to backup IG
+          }
+          ShouldNotReachHere();
+        }
+
         Node* ctl = n->in(MemNode::Control);
         Node* mem = first->in(MemNode::Memory);
         Node* adr = low_adr->in(MemNode::Address);
         const TypePtr* atyp = n->adr_type();
         vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
         vlen_in_bytes = vn->as_StoreVector()->memory_size();
-      } else if (n->req() == 3) {
+      } else if (n->req() == 3 && !is_cmov_pack(p)) {
         // Promote operands to vector
         Node* in1 = NULL;
         bool node_isa_reduction = n->is_reduction();
@@ -1870,8 +2113,22 @@
           in1 = low_adr->in(1);
         } else {
           in1 = vector_opd(p, 1);
+          if (in1 == NULL) {
+            if (do_reserve_copy()) {
+              NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");})
+              return; //and reverse to backup IG
+            }
+            ShouldNotReachHere();
+          }
         }
         Node* in2 = vector_opd(p, 2);
+        if (in2 == NULL) {
+          if (do_reserve_copy()) {
+            NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");})
+            return; //and reverse to backup IG
+          }
+          ShouldNotReachHere();
+        }
         if (VectorNode::is_invariant_vector(in1) && (node_isa_reduction == false) && (n->is_Add() || n->is_Mul())) {
           // Move invariant vector input into second position to avoid register spilling.
           Node* tmp = in1;
@@ -1895,10 +2152,71 @@
         Node* in = vector_opd(p, 1);
         vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
         vlen_in_bytes = vn->as_Vector()->length_in_bytes();
+      } else if (is_cmov_pack(p)) {
+        if (!n->is_CMove()) {
+          continue;
+        }
+        // place here CMoveVDNode
+        NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: print before CMove vectorization"); print_loop(false);})
+        Node* bol = n->in(CMoveNode::Condition);
+        if (!bol->is_Bool() && bol->Opcode() == Op_ExtractI && bol->req() > 1 ) {
+          NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d is not Bool node, trying its in(1) node %d", bol->_idx, bol->in(1)->_idx); bol->dump(); bol->in(1)->dump();})
+          bol = bol->in(1); //may be ExtractNode
+        }
+
+        assert(bol->is_Bool(), "should be BoolNode - too late to bail out!");
+        if (!bol->is_Bool()) {
+          if (do_reserve_copy()) {
+            NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();})
+            return; //and reverse to backup IG
+          }
+          ShouldNotReachHere();
+        }
+
+        int cond = (int)bol->as_Bool()->_test._test;
+        Node* in_cc  = _igvn.intcon(cond);
+        NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created intcon in_cc node %d", in_cc->_idx); in_cc->dump();})
+        Node* cc = bol->clone();
+        cc->set_req(1, in_cc);
+        NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created bool cc node %d", cc->_idx); cc->dump();})
+
+        Node* src1 = vector_opd(p, 2); //2=CMoveNode::IfFalse
+        if (src1 == NULL) {
+          if (do_reserve_copy()) {
+            NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");})
+            return; //and reverse to backup IG
+          }
+          ShouldNotReachHere();
+        }
+        Node* src2 = vector_opd(p, 3); //3=CMoveNode::IfTrue
+        if (src2 == NULL) {
+          if (do_reserve_copy()) {
+            NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");})
+            return; //and reverse to backup IG
+          }
+          ShouldNotReachHere();
+        }
+        BasicType bt = velt_basic_type(n);
+        const TypeVect* vt = TypeVect::make(bt, vlen);
+        vn = new CMoveVDNode(cc, src1, src2, vt);
+        NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created new CMove node %d: ", vn->_idx); vn->dump();})
       } else {
+        if (do_reserve_copy()) {
+          NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");})
+          return; //and reverse to backup IG
+        }
         ShouldNotReachHere();
       }
+
       assert(vn != NULL, "sanity");
+      if (vn == NULL) {
+        if (do_reserve_copy()){
+          NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");})
+          return; //and reverse to backup IG
+        }
+        ShouldNotReachHere();
+      }
+
       _igvn.register_new_node_with_optimizer(vn);
       _phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
       for (uint j = 0; j < p->size(); j++) {
@@ -1918,7 +2236,8 @@
       }
 #endif
     }
-  }
+  }//for (int i = 0; i < _block.length(); i++)
+
   C->set_max_vector_size(max_vlen_in_bytes);
 
   if (SuperWordLoopUnrollAnalysis) {
@@ -1934,10 +2253,10 @@
     }
   }
 
-  if (DoReserveCopyInSuperWord) {
+  if (do_reserve_copy()) {
     make_reversable.use_new();
   }
-  NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
+  NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
   return;
 }
 
@@ -1951,6 +2270,10 @@
   if (same_inputs(p, opd_idx)) {
     if (opd->is_Vector() || opd->is_LoadVector()) {
       assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector");
+      if (opd_idx == 2 && VectorNode::is_shift(p0)) {
+        NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("shift's count can't be vector");})
+        return NULL;
+      }
       return opd; // input is matching vector
     }
     if ((opd_idx == 2) && VectorNode::is_shift(p0)) {
@@ -1973,6 +2296,10 @@
           _phase->set_ctrl(cnt, _phase->get_ctrl(opd));
         }
         assert(opd->bottom_type()->isa_int(), "int type only");
+        if (!opd->bottom_type()->isa_int()) {
+          NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should be int type only");})
+          return NULL;
+        }
         // Move non constant shift count into vector register.
         cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0));
       }
@@ -1983,6 +2310,10 @@
       return cnt;
     }
     assert(!opd->is_StoreVector(), "such vector is not expected here");
+    if (opd->is_StoreVector()) {
+      NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("StoreVector is not expected here");})
+      return NULL;
+    }
     // Convert scalar input to vector with the same number of elements as
     // p0's vector. Use p0's type because size of operand's container in
     // vector should match p0's size regardless operand's size.
@@ -2009,6 +2340,10 @@
     Node* pi = p->at(i);
     Node* in = pi->in(opd_idx);
     assert(my_pack(in) == NULL, "Should already have been unpacked");
+    if (my_pack(in) != NULL) {
+      NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should already have been unpacked");})
+      return NULL;
+    }
     assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
     pk->add_opd(in);
   }
@@ -2040,8 +2375,9 @@
       for (uint k = 0; k < use->req(); k++) {
         Node* n = use->in(k);
         if (def == n) {
-          if (!is_vector_use(use, k)) {
-            _n_idx_list.push(use, k);
+          Node_List* u_pk = my_pack(use);
+          if ((u_pk == NULL || !is_cmov_pack(u_pk) || use->is_CMove()) && !is_vector_use(use, k)) {
+              _n_idx_list.push(use, k);
           }
         }
       }
--- a/hotspot/src/share/vm/opto/superword.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -29,6 +29,7 @@
 #include "opto/phaseX.hpp"
 #include "opto/vectornode.hpp"
 #include "utilities/growableArray.hpp"
+#include "libadt/dict.hpp"
 
 //
 //                  S U P E R W O R D   T R A N S F O R M
@@ -200,6 +201,24 @@
   static const SWNodeInfo initial;
 };
 
+class SuperWord;
+class CMoveKit {
+ friend class SuperWord;
+ private:
+  SuperWord* _sw;
+  Dict* _dict;
+  CMoveKit(Arena* a, SuperWord* sw) : _sw(sw)  {_dict = new Dict(cmpkey, hashkey, a);}
+  void*     _2p(Node* key)        const  { return (void*)(intptr_t)key; } // 2 conversion functions to make gcc happy
+  Dict*     dict()                const  { return _dict; }
+  void map(Node* key, Node_List* val)    { assert(_dict->operator[](_2p(key)) == NULL, "key existed"); _dict->Insert(_2p(key), (void*)val); }
+  void unmap(Node* key)                  { _dict->Delete(_2p(key)); }
+  Node_List* pack(Node* key)      const  { return (Node_List*)_dict->operator[](_2p(key)); }
+  Node* is_Bool_candidate(Node* nd) const; // if it is the right candidate return corresponding CMove* ,
+  Node* is_CmpD_candidate(Node* nd) const; // otherwise return NULL
+  Node_List* make_cmovevd_pack(Node_List* cmovd_pk);
+  bool test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk);
+};//class CMoveKit
+
 // JVMCI: OrderedPair is moved up to deal with compilation issues on Windows
 //------------------------------OrderedPair---------------------------
 // Ordered pair of Node*.
@@ -229,6 +248,7 @@
 // Transforms scalar operations into packed (superword) operations.
 class SuperWord : public ResourceObj {
  friend class SWPointer;
+ friend class CMoveKit;
  private:
   PhaseIdealLoop* _phase;
   Arena*          _arena;
@@ -247,8 +267,8 @@
   GrowableArray<Node*> _iteration_first; // nodes in the generation that has deps from phi
   GrowableArray<Node*> _iteration_last;  // nodes in the generation that has deps to   phi
   GrowableArray<SWNodeInfo> _node_info;  // Info needed per node
-  CloneMap&                 _clone_map;  // map of nodes created in cloning
-
+  CloneMap&            _clone_map;       // map of nodes created in cloning
+  CMoveKit             _cmovev_kit;      // support for vectorization of CMov
   MemNode* _align_to_ref;                // Memory reference that pre-loop will align to
 
   GrowableArray<OrderedPair> _disjoint_ptrs; // runtime disambiguated pointer pairs
@@ -282,8 +302,11 @@
   bool     is_trace_mem_slice()    { return (_vector_loop_debug & 4) > 0; }
   bool     is_trace_loop()         { return (_vector_loop_debug & 8) > 0; }
   bool     is_trace_adjacent()     { return (_vector_loop_debug & 16) > 0; }
+  bool     is_trace_cmov()         { return (_vector_loop_debug & 32) > 0; }
+  bool     is_trace_loop_reverse() { return (_vector_loop_debug & 64) > 0; }
 #endif
   bool     do_vector_loop()        { return _do_vector_loop; }
+  bool     do_reserve_copy()       { return _do_reserve_copy; }
  private:
   IdealLoopTree* _lpt;             // Current loop tree node
   LoopNode*      _lp;              // Current LoopNode
@@ -292,6 +315,7 @@
   bool           _race_possible;   // In cases where SDMU is true
   bool           _early_return;    // True if we do not initialize
   bool           _do_vector_loop;  // whether to do vectorization/simd style
+  bool           _do_reserve_copy; // do reserve copy of the graph(loop) before final modification in output
   int            _num_work_vecs;   // Number of non memory vector operations
   int            _num_reductions;  // Number of reduction expressions applied
   int            _ii_first;        // generation with direct deps from mem phi
@@ -299,7 +323,6 @@
   GrowableArray<int> _ii_order;
 #ifndef PRODUCT
   uintx          _vector_loop_debug; // provide more printing in debug mode
-  uintx          _CountedLoopReserveKit_debug; // for debugging CountedLoopReserveKit
 #endif
 
   // Accessors
@@ -360,9 +383,13 @@
   bool same_velt_type(Node* n1, Node* n2);
 
   // my_pack
-  Node_List* my_pack(Node* n)                { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; }
-  void set_my_pack(Node* n, Node_List* p)    { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; }
-
+  Node_List* my_pack(Node* n)                 { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; }
+  void set_my_pack(Node* n, Node_List* p)     { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; }
+  // is pack good for converting into one vector node replacing 12 nodes of Cmp, Bool, CMov
+  bool is_cmov_pack(Node_List* p);
+  bool is_cmov_pack_internal_node(Node_List* p, Node* nd) { return is_cmov_pack(p) && !nd->is_CMove(); }
+  // For pack p, are all idx operands the same?
+  bool same_inputs(Node_List* p, int idx);
   // CloneMap utilities
   bool same_origin_idx(Node* a, Node* b) const;
   bool same_generation(Node* a, Node* b) const;
@@ -439,6 +466,8 @@
   void construct_my_pack_map();
   // Remove packs that are not implemented or not profitable.
   void filter_packs();
+  // Merge CMoveD into new vector-nodes
+  void merge_packs_to_cmovd();
   // Adjust the memory graph for the packed operations
   void schedule();
   // Remove "current" from its current position in the memory graph and insert
--- a/hotspot/src/share/vm/opto/vectornode.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/vectornode.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -86,6 +86,9 @@
   case Op_MulD:
     assert(bt == T_DOUBLE, "must be");
     return Op_MulVD;
+  case Op_CMoveD:
+    assert(bt == T_DOUBLE, "must be");
+    return Op_CMoveVD;
   case Op_DivF:
     assert(bt == T_FLOAT, "must be");
     return Op_DivVF;
@@ -185,7 +188,7 @@
       (vlen > 1) && is_power_of_2(vlen) &&
       Matcher::vector_size_supported(bt, vlen)) {
     int vopc = VectorNode::opcode(opc, bt);
-    return vopc > 0 && Matcher::match_rule_supported(vopc);
+    return vopc > 0 && Matcher::match_rule_supported(vopc) && (vopc != Op_CMoveD || vlen == 4);
   }
   return false;
 }
--- a/hotspot/src/share/vm/opto/vectornode.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/opto/vectornode.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -44,6 +44,13 @@
     init_req(2, n2);
   }
 
+  VectorNode(Node* n1, Node* n2, Node* n3, const TypeVect* vt) : TypeNode(vt, 4) {
+    init_class_id(Class_Vector);
+    init_req(1, n1);
+    init_req(2, n2);
+    init_req(3, n3);
+  }
+
   const TypeVect* vect_type() const { return type()->is_vect(); }
   uint length() const { return vect_type()->length(); } // Vector length
   uint length_in_bytes() const { return vect_type()->length_in_bytes(); }
@@ -253,6 +260,14 @@
   virtual int Opcode() const;
 };
 
+//------------------------------CMoveVDNode--------------------------------------
+// Vector multiply double
+class CMoveVDNode : public VectorNode {
+public:
+  CMoveVDNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {}
+  virtual int Opcode() const;
+};
+
 //------------------------------MulReductionVINode--------------------------------------
 // Vector multiply int as a reduction
 class MulReductionVINode : public ReductionNode {
--- a/hotspot/src/share/vm/prims/jni.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -3840,7 +3840,9 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/heapRegionRemSet.hpp"
 #endif
+#include "compiler/directivesParser.hpp"
 #include "memory/guardedMemory.hpp"
+#include "utilities/json.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/quickSort.hpp"
 #if INCLUDE_VM_STRUCTS
@@ -3904,6 +3906,8 @@
     run_unit_test(ObjectMonitor::sanity_checks());
     run_unit_test(Test_linked_list());
     run_unit_test(TestChunkedList_test());
+    run_unit_test(JSONTest::test());
+    run_unit_test(DirectivesParser::test());
 #if INCLUDE_VM_STRUCTS
     run_unit_test(VMStructs::test());
 #endif
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -551,14 +551,20 @@
   method_id = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
+
+  DirectiveSet* directive;
   if (compilation_context != NULL) {
     compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
     CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
     methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
-    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch);
+    directive = DirectivesStack::getMatchingDirective(cch, CompileBroker::compiler((int)compLevel));
   } else {
-    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL);
+    // Calling with NULL matches default directive
+    directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler((int)compLevel));
   }
+  bool result = CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, directive);
+  DirectivesStack::release(directive);
+  return result;
 WB_END
 
 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
@@ -624,6 +630,47 @@
   return (mh->queued_for_compilation() || nm != NULL);
 WB_END
 
+WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple));
+  bool result = directive->PrintAssemblyOption;
+  DirectivesStack::release(directive);
+
+  return result;
+WB_END
+
+WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+
+  ResourceMark rm;
+  const char* error_msg = NULL;
+  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
+  InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
+
+  if (m == NULL) {
+    assert(error_msg != NULL, "Always have an error message");
+    tty->print_cr("Got error: %s", error_msg);
+    return -1; // Pattern failed
+  }
+
+  // Pattern works - now check if it matches
+  int result;
+  if (m->match(mh, InlineMatcher::force_inline)) {
+    result = 2; // Force inline match
+  } else if (m->match(mh, InlineMatcher::dont_inline)) {
+    result = 1; // Dont inline match
+  } else {
+    result = 0; // No match
+  }
+  delete m;
+  return result;
+WB_END
 
 WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
@@ -1475,6 +1522,13 @@
   {CC"matchesMethod",
       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
                                                       (void*)&WB_MatchesMethod},
+  {CC"matchesInline",
+      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
+                                                      (void*)&WB_MatchesInline},
+  {CC"shouldPrintAssembly",
+        CC"(Ljava/lang/reflect/Executable;)Z",
+                                                        (void*)&WB_ShouldPrintAssembly},
+
   {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
   {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
   {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -3667,6 +3667,9 @@
   product(ccstr, CompileCommandFile, NULL,                                  \
           "Read compiler commands from this file [.hotspot_compiler]")      \
                                                                             \
+  diagnostic(ccstr, CompilerDirectivesFile, NULL,                           \
+          "Read compiler directives from this file")                        \
+                                                                            \
   product(ccstrlist, CompileCommand, "",                                    \
           "Prepend to .hotspot_compiler; e.g. log,java/lang/String.<init>") \
                                                                             \
@@ -4267,7 +4270,13 @@
              "(3) no orphan methods exist for class C (i.e., methods for "  \
              "which the VM declares an intrinsic but that are not declared "\
              "in the loaded class C. "                                      \
-             "Check (3) is available only in debug builds.")
+             "Check (3) is available only in debug builds.")                \
+                                                                            \
+  diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false,          \
+             "Disable backwards compatibility for compile commands.")       \
+                                                                            \
+  diagnostic(bool, PrintCompilerDirectives, false,                          \
+             "Print compiler directives on installation.")
 
 /*
  *  Macros for factoring of globals
--- a/hotspot/src/share/vm/runtime/init.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/init.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -71,7 +71,7 @@
 void vtableStubs_init();
 void InlineCacheBuffer_init();
 void compilerOracle_init();
-void compileBroker_init();
+bool compileBroker_init();
 
 // Initialization after compiler initialization
 bool universe_post_init();  // must happen after compiler_init
@@ -131,7 +131,9 @@
   vtableStubs_init();
   InlineCacheBuffer_init();
   compilerOracle_init();
-  compileBroker_init();
+  if (!compileBroker_init()) {
+    return JNI_EINVAL;
+  }
   VMRegImpl::set_regName();
 
   if (!universe_post_init()) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -90,6 +90,7 @@
 Monitor* Compilation_lock             = NULL;
 Mutex*   CompileTaskAlloc_lock        = NULL;
 Mutex*   CompileStatistics_lock       = NULL;
+Mutex*   DirectivesStack_lock         = NULL;
 Mutex*   MultiArray_lock              = NULL;
 Monitor* Terminator_lock              = NULL;
 Monitor* BeforeExit_lock              = NULL;
@@ -264,6 +265,7 @@
   def(CompiledIC_lock              , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // locks VtableStubs_lock, InlineCacheBuffer_lock
   def(CompileTaskAlloc_lock        , Mutex  , nonleaf+2,   true,  Monitor::_safepoint_check_always);
   def(CompileStatistics_lock       , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);
+  def(DirectivesStack_lock         , Mutex  , special,     true,  Monitor::_safepoint_check_never);
   def(MultiArray_lock              , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // locks SymbolTable_lock
 
   def(JvmtiThreadState_lock        , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // Used by JvmtiThreadState/JvmtiEventController
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -93,6 +93,7 @@
 extern Monitor* Compilation_lock;                // a lock used to pause compilation
 extern Mutex*   CompileTaskAlloc_lock;           // a lock held when CompileTasks are allocated
 extern Mutex*   CompileStatistics_lock;          // a lock held when updating compilation statistics
+extern Mutex*   DirectivesStack_lock;            // a lock held when mutating the dirstack and ref counting directives
 extern Mutex*   MultiArray_lock;                 // a lock used to guard allocation of multi-dim arrays
 extern Monitor* Terminator_lock;                 // a lock used to guard termination of the vm
 extern Monitor* BeforeExit_lock;                 // a lock used to guard cleanups and shutdown hooks
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -2696,6 +2696,12 @@
 
       if (nm != NULL) {
         method->set_code(method, nm);
+
+        DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
+        if (directive->PrintAssemblyOption) {
+          Disassembler::decode(nm, tty);
+        }
+        DirectivesStack::release(directive);
       }
     }
   } // Unlock AdapterHandlerLibrary_lock
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -149,8 +149,8 @@
 address StubRoutines::_montgomerySquare = NULL;
 
 address StubRoutines::_dexp = NULL;
+address StubRoutines::_dlog = NULL;
 
-double (* StubRoutines::_intrinsic_log   )(double) = NULL;
 double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
 double (* StubRoutines::_intrinsic_pow   )(double, double) = NULL;
 double (* StubRoutines::_intrinsic_sin   )(double) = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -208,6 +208,7 @@
   static address _montgomerySquare;
 
   static address _dexp;
+  static address _dlog;
 
   // These are versions of the java.lang.Math methods which perform
   // the same operations as the intrinsic version.  They are used for
@@ -215,7 +216,6 @@
   // intrinsic version returns the same result as the strict version
   // then they can be set to the appropriate function from
   // SharedRuntime.
-  static double (*_intrinsic_log)(double);
   static double (*_intrinsic_log10)(double);
   static double (*_intrinsic_pow)(double, double);
   static double (*_intrinsic_sin)(double);
@@ -376,18 +376,15 @@
   static address montgomeryMultiply()  { return _montgomeryMultiply; }
   static address montgomerySquare()    { return _montgomerySquare; }
 
-  static address dexp()                {return _dexp; }
+  static address dexp()                { return _dexp; }
+  static address dlog()                { return _dlog; }
 
   static address select_fill_function(BasicType t, bool aligned, const char* &name);
 
   static address zero_aligned_words()   { return _zero_aligned_words; }
 
-  static double  intrinsic_log(double d) {
-    assert(_intrinsic_log != NULL, "must be defined");
-    return _intrinsic_log(d);
-  }
   static double  intrinsic_log10(double d) {
-    assert(_intrinsic_log != NULL, "must be defined");
+    assert(_intrinsic_log10 != NULL, "must be defined");
     return _intrinsic_log10(d);
   }
   static double  intrinsic_pow(double d, double d2) {
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -246,12 +246,6 @@
 #ifndef REG_COUNT
   #define REG_COUNT 0
 #endif
-// whole purpose of this function is to work around bug c++/27724 in gcc 4.1.1
-// with optimization turned on it doesn't affect produced code
-static inline uint64_t cast_uint64_t(size_t x)
-{
-  return x;
-}
 
 #if INCLUDE_JVMTI
   #define JVMTI_STRUCTS(static_field) \
@@ -868,6 +862,7 @@
      static_field(StubRoutines,                _squareToLen,                                  address)                               \
      static_field(StubRoutines,                _mulAdd,                                       address)                               \
      static_field(StubRoutines,                _dexp,                                         address)                               \
+     static_field(StubRoutines,                _dlog,                                         address)                               \
      static_field(StubRoutines,                _jbyte_arraycopy,                              address)                               \
      static_field(StubRoutines,                _jshort_arraycopy,                             address)                               \
      static_field(StubRoutines,                _jint_arraycopy,                               address)                               \
@@ -2069,7 +2064,6 @@
   declare_c2_type(TanDNode, Node)                                         \
   declare_c2_type(AtanDNode, Node)                                        \
   declare_c2_type(SqrtDNode, Node)                                        \
-  declare_c2_type(LogDNode, Node)                                         \
   declare_c2_type(Log10DNode, Node)                                       \
   declare_c2_type(PowDNode, Node)                                         \
   declare_c2_type(ReverseBytesINode, Node)                                \
@@ -2100,6 +2094,7 @@
   declare_c2_type(MulVFNode, VectorNode)                                  \
   declare_c2_type(MulReductionVFNode, ReductionNode)                      \
   declare_c2_type(MulVDNode, VectorNode)                                  \
+  declare_c2_type(CMoveVDNode, VectorNode)                                \
   declare_c2_type(MulReductionVDNode, ReductionNode)                      \
   declare_c2_type(DivVFNode, VectorNode)                                  \
   declare_c2_type(DivVDNode, VectorNode)                                  \
@@ -2896,7 +2891,7 @@
 
 // This macro generates a VMStructEntry line for a nonstatic field
 #define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)              \
- { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL },
+ { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, offset_of(typeName, fieldName), NULL },
 
 // This macro generates a VMStructEntry line for a static field
 #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                 \
@@ -2906,7 +2901,7 @@
 // nonstatic field, in which the size of the type is also specified.
 // The type string is given as NULL, indicating an "opaque" type.
 #define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size)    \
-  { QUOTE(typeName), QUOTE(fieldName), NULL, 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL },
+  { QUOTE(typeName), QUOTE(fieldName), NULL, 0, offset_of(typeName, fieldName), NULL },
 
 // This macro generates a VMStructEntry line for an unchecked
 // static field, in which the size of the type is also specified.
@@ -3089,10 +3084,10 @@
 //
 
 #define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \
-  { QUOTE(name), cast_uint64_t(name) },
+  { QUOTE(name), name },
 
 #define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \
-  { name, cast_uint64_t(value) },
+  { name, value },
 
 // This macro generates the sentinel value indicating the end of the list
 #define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \
@@ -3540,43 +3535,40 @@
 
 extern "C" {
 
-// see comments on cast_uint64_t at the top of this file
-#define ASSIGN_CONST_TO_64BIT_VAR(var, expr) \
-    JNIEXPORT uint64_t var = cast_uint64_t(expr);
-#define ASSIGN_OFFSET_TO_64BIT_VAR(var, type, field)   \
-  ASSIGN_CONST_TO_64BIT_VAR(var, offset_of(type, field))
-#define ASSIGN_STRIDE_TO_64BIT_VAR(var, array) \
-  ASSIGN_CONST_TO_64BIT_VAR(var, (char*)&array[1] - (char*)&array[0])
+#define STRIDE(array) ((char*)&array[1] - (char*)&array[0])
+
+JNIEXPORT VMStructEntry* gHotSpotVMStructs = VMStructs::localHotSpotVMStructs;
+JNIEXPORT uint64_t gHotSpotVMStructEntryTypeNameOffset = offset_of(VMStructEntry, typeName);
+JNIEXPORT uint64_t gHotSpotVMStructEntryFieldNameOffset = offset_of(VMStructEntry, fieldName);
+JNIEXPORT uint64_t gHotSpotVMStructEntryTypeStringOffset = offset_of(VMStructEntry, typeString);
+JNIEXPORT uint64_t gHotSpotVMStructEntryIsStaticOffset = offset_of(VMStructEntry, isStatic);
+JNIEXPORT uint64_t gHotSpotVMStructEntryOffsetOffset = offset_of(VMStructEntry, offset);
+JNIEXPORT uint64_t gHotSpotVMStructEntryAddressOffset = offset_of(VMStructEntry, address);
+JNIEXPORT uint64_t gHotSpotVMStructEntryArrayStride = STRIDE(gHotSpotVMStructs);
 
-JNIEXPORT VMStructEntry* gHotSpotVMStructs                 = VMStructs::localHotSpotVMStructs;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeNameOffset,  VMStructEntry, typeName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryFieldNameOffset, VMStructEntry, fieldName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeStringOffset, VMStructEntry, typeString);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryIsStaticOffset, VMStructEntry, isStatic);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryOffsetOffset, VMStructEntry, offset);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryAddressOffset, VMStructEntry, address);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMStructEntryArrayStride, gHotSpotVMStructs);
-JNIEXPORT VMTypeEntry*   gHotSpotVMTypes                   = VMStructs::localHotSpotVMTypes;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryTypeNameOffset, VMTypeEntry, typeName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySuperclassNameOffset, VMTypeEntry, superclassName);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsOopTypeOffset, VMTypeEntry, isOopType);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsIntegerTypeOffset, VMTypeEntry, isIntegerType);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsUnsignedOffset, VMTypeEntry, isUnsigned);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySizeOffset, VMTypeEntry, size);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMTypeEntryArrayStride,gHotSpotVMTypes);
-JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants       = VMStructs::localHotSpotVMIntConstants;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryNameOffset, VMIntConstantEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryValueOffset, VMIntConstantEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMIntConstantEntryArrayStride, gHotSpotVMIntConstants);
-JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants     = VMStructs::localHotSpotVMLongConstants;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryNameOffset, VMLongConstantEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryValueOffset, VMLongConstantEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMLongConstantEntryArrayStride, gHotSpotVMLongConstants);
+JNIEXPORT VMTypeEntry* gHotSpotVMTypes = VMStructs::localHotSpotVMTypes;
+JNIEXPORT uint64_t gHotSpotVMTypeEntryTypeNameOffset = offset_of(VMTypeEntry, typeName);
+JNIEXPORT uint64_t gHotSpotVMTypeEntrySuperclassNameOffset = offset_of(VMTypeEntry, superclassName);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsOopTypeOffset = offset_of(VMTypeEntry, isOopType);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset = offset_of(VMTypeEntry, isIntegerType);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryIsUnsignedOffset = offset_of(VMTypeEntry, isUnsigned);
+JNIEXPORT uint64_t gHotSpotVMTypeEntrySizeOffset = offset_of(VMTypeEntry, size);
+JNIEXPORT uint64_t gHotSpotVMTypeEntryArrayStride = STRIDE(gHotSpotVMTypes);
+
+JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants = VMStructs::localHotSpotVMIntConstants;
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryNameOffset = offset_of(VMIntConstantEntry, name);
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryValueOffset = offset_of(VMIntConstantEntry, value);
+JNIEXPORT uint64_t gHotSpotVMIntConstantEntryArrayStride = STRIDE(gHotSpotVMIntConstants);
+
+JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants = VMStructs::localHotSpotVMLongConstants;
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryNameOffset = offset_of(VMLongConstantEntry, name);
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryValueOffset = offset_of(VMLongConstantEntry, value);
+JNIEXPORT uint64_t gHotSpotVMLongConstantEntryArrayStride = STRIDE(gHotSpotVMLongConstants);
 
 JNIEXPORT VMAddressEntry* gHotSpotVMAddresses = VMStructs::localHotSpotVMAddresses;
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryNameOffset, VMAddressEntry, name);
-ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryValueOffset, VMAddressEntry, value);
-ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMAddressEntryArrayStride, gHotSpotVMAddresses);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryNameOffset = offset_of(VMAddressEntry, name);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryValueOffset = offset_of(VMAddressEntry, value);
+JNIEXPORT uint64_t gHotSpotVMAddressEntryArrayStride = STRIDE(gHotSpotVMAddresses);
 }
 
 #ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -28,7 +28,6 @@
 #include "code/codeCache.hpp"
 #include "code/codeCacheExtensions.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "gc/shared/isGCActiveMark.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -25,6 +25,8 @@
 #include "precompiled.hpp"
 #include "classfile/classLoaderStats.hpp"
 #include "classfile/compactHashtable.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/globals.hpp"
@@ -77,6 +79,11 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
 
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export, true, false));
+
   // Enhanced JMX Agent Support
   // These commands won't be exported via the DiagnosticCommandMBean until an
   // appropriate permission is created for them
@@ -837,6 +844,38 @@
   VMThread::execute(&printCodeCacheOp);
 }
 
+void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::print(output());
+}
+
+CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
+                           DCmdWithParser(output, heap),
+  _filename("filename","Name of the directives file", "STRING",true) {
+  _dcmdparser.add_dcmd_argument(&_filename);
+}
+
+void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesParser::parse_from_file(_filename.value(), output());
+}
+
+int CompilerDirectivesAddDCmd::num_arguments() {
+  ResourceMark rm;
+  CompilerDirectivesAddDCmd* dcmd = new CompilerDirectivesAddDCmd(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+
+void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::pop();
+}
+
+void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::clear();
+}
 #if INCLUDE_SERVICES
 ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
                                        DCmdWithParser(output, heap),
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -613,4 +613,90 @@
   virtual void execute(DCmdSource source, TRAPS);
 };
 
+class CompilerDirectivesPrintDCmd : public DCmd {
+public:
+  CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_print";
+  }
+  static const char* description() {
+    return "Print all active compiler directives.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesRemoveDCmd : public DCmd {
+public:
+  CompilerDirectivesRemoveDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_remove";
+  }
+  static const char* description() {
+    return "Remove latest added compiler directive.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesAddDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<char*> _filename;
+public:
+  CompilerDirectivesAddDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "Compiler.directives_add";
+  }
+  static const char* description() {
+    return "Add compiler directives from file.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments();
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesClearDCmd : public DCmd {
+public:
+  CompilerDirectivesClearDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_clear";
+  }
+  static const char* description() {
+    return "Remove all compiler directives.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/shark/sharkCompiler.cpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -145,7 +145,8 @@
 
 void SharkCompiler::compile_method(ciEnv*    env,
                                    ciMethod* target,
-                                   int       entry_bci) {
+                                   int       entry_bci,
+                                   DirectiveSet* directive) {
   assert(is_initialized(), "should be");
   ResourceMark rm;
   const char *name = methodname(
@@ -216,8 +217,8 @@
                        &handler_table,
                        &inc_table,
                        this,
-                       env->comp_level(),
                        false,
+                       directive(),
                        false);
 }
 
--- a/hotspot/src/share/vm/shark/sharkCompiler.hpp	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -30,6 +30,7 @@
 #include "ci/ciMethod.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "shark/llvmHeaders.hpp"
 #include "shark/sharkMemoryManager.hpp"
 
@@ -54,7 +55,7 @@
   void initialize();
 
   // Compile a normal (bytecode) method and install it in the VM
-  void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* dirset);
 
   // Print compilation timers and statistics
   void print_timers();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.cpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * This is not really json in the state it is now.
+ * Some differences:
+ * - Double quotes around the key in an object is not enforced.
+ *     i.e you can write: { foo : "bar" } instead of { "foo" : "bar" }.
+ * - Comments are allowed.
+ * - The last element in an object or array can have an ending comma.
+ */
+
+#include "precompiled.hpp"
+#include "utilities/json.hpp"
+#include "utilities/ostream.hpp"
+#include <math.h>
+
+const char* strchrnul_(const char *s, int c) {
+  const char* tmp = strchr(s, c);
+  return tmp == NULL ? s + strlen(s) : tmp;
+}
+
+JSON::JSON(const char* text, bool silent, outputStream* st)
+: start(text), pos(text), mark(text),
+  level(0), line(1), column(0), silent(silent), _valid(true), _st(st)
+{
+}
+
+void JSON::parse() {
+  assert(start != NULL, "Need something to parse");
+  if (start == NULL) {
+    _valid = false;
+    error(INTERNAL_ERROR, "JSON parser was called with a string that was NULL.");
+  } else {
+    _valid = parse_json_value();
+  }
+}
+
+bool JSON::valid() {
+  return _valid;
+}
+
+bool JSON::parse_json_value() {
+  int c;
+
+  c = skip_to_token();
+  if (c == -1) {
+    return false;
+  }
+
+  // Must start with object or array
+  if (level == 0) {
+
+    switch (c) {
+    case '{':
+      if (parse_json_object() == false) {
+        return false;
+      }
+      c = skip_to_token();
+      if (c > 0) {
+        mark_pos();
+        error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+        return false;
+      } else if (c < 0) {
+        return false;
+      }
+      return true;
+
+    case '[':
+      if (parse_json_array() == false) {
+        return false;
+      }
+      c = skip_to_token();
+      if (c > 0) {
+        mark_pos();
+        error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+        return false;
+      } else if (c < 0) {
+        return false;
+      }
+      return true;
+
+    case 0:
+      error(SYNTAX_ERROR, "EOS was encountered before any json declarations");
+      return false;
+
+    default:
+      error(SYNTAX_ERROR, "Json must start with an object or an array.");
+      return false;
+    }
+  } else { // level > 0
+    switch (c) {
+    case '{':
+      return parse_json_object();
+
+    case '[':
+      return parse_json_array();
+
+    case '"':
+      return parse_json_string();
+
+    case '-': case '0':
+    case '1': case '2': case '3':
+    case '4': case '5': case '6':
+    case '7': case '8': case '9':
+      return parse_json_number();
+
+    case 't':
+      return parse_json_symbol("true", JSON_TRUE);
+
+    case 'f':
+      return parse_json_symbol("false", JSON_FALSE);
+
+    case 'n':
+      return parse_json_symbol("null", JSON_NULL);
+
+    case 0:
+      error(SYNTAX_ERROR, "EOS was encountered when expecting a json value.");
+      return false;
+
+    default:
+      error(SYNTAX_ERROR, "Could not parse as a json value (did you forget to quote your strings?).");
+      return false;
+    }
+  }
+}
+
+// Should only be called when we actually have the start of an object
+// Otherwise it is an internal error
+bool JSON::parse_json_object() {
+  NOT_PRODUCT(const char* prev_pos);
+  int c;
+
+  mark_pos();
+  // Check that we are not called in error
+  if (expect_any("{", "object start", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (!callback(JSON_OBJECT_BEGIN, NULL, level++)) {
+    return false;
+  }
+
+  for (;;) {
+    mark_pos();
+    c = skip_to_token();
+    if (c == 0) {
+      error(SYNTAX_ERROR, "EOS when expecting an object key or object end");
+      return false;
+    } else if (c < 0) {
+      return false;
+    } else if (c == '}') {
+      // We got here from either empty object "{}" or ending comma "{a:1,}"
+      next();
+      break;
+    }
+
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_key() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    skip_to_token();
+    mark_pos();
+    if (expect_any(":", "object key-value separator") <= 0) {
+      return false;
+    }
+
+    skip_to_token();
+    mark_pos();
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_value() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    c = skip_to_token();
+    mark_pos();
+    if (expect_any(",}", "value separator or object end") <= 0) {
+      return false;
+    }
+    if (c == '}') {
+      break;
+    }
+  }
+
+  assert(c == '}', "array parsing ended without object end token ('}')");
+  return callback(JSON_OBJECT_END, NULL, --level);
+}
+
+// Should only be called when we actually have the start of an array
+// Otherwise it is an internal error
+bool JSON::parse_json_array() {
+  NOT_PRODUCT(const char* prev_pos);
+  int c;
+
+  mark_pos();
+  // Check that we are not called in error
+  if (expect_any("[", "array start character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (!callback(JSON_ARRAY_BEGIN, NULL, level++)) {
+    return false;
+  }
+
+  for (;;) {
+    mark_pos();
+    c = skip_to_token();
+    if (c == 0) {
+      error(SYNTAX_ERROR, "EOS when expecting a json value or array end");
+      return false;
+    } else if (c < 0) {
+      return false;
+    } else if (c == ']') {
+      // We got here from either empty array "[]" or ending comma "[1,]"
+      next();
+      break;
+    }
+
+    mark_pos();
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_value() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    c = skip_to_token();
+    mark_pos();
+    if (expect_any(",]", "value separator or array end") <= 0) {
+      return false;
+    }
+    if (c == ']') {
+      break;
+    }
+  }
+
+  assert(c == ']', "array parsing ended without array end token (']')");
+  return callback(JSON_ARRAY_END, NULL, --level);
+}
+
+bool JSON::parse_json_string(bool key) {
+  const char* end;
+  JSON_VAL v;
+
+  mark_pos();
+  if (expect_any("\"", "string start character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  end = strchr(pos, '"'); // TODO: escapes
+  if (end == NULL) {
+    error(SYNTAX_ERROR, "String started here never ended. Expected \'\"\' before EOS.");
+    return false;
+  }
+
+  v.str.start = pos;
+  v.str.length = end - pos;
+  skip(end - pos);
+
+  if (expect_any("\"", "string end character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (key == true) {
+    return callback(JSON_KEY, &v, level);
+  } else {
+    return callback(JSON_STRING, &v, level);
+  }
+}
+
+// TODO: hotspot equivalents?
+static bool is_alpha(u_char c) {
+  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+static bool is_numeric(u_char c) {
+  return (c >= '0' && c <= '9');
+}
+static bool is_alnum(u_char c) {
+  return is_alpha(c) || is_numeric(c);
+}
+static bool is_word(u_char c) {
+  return c == '_' || is_alnum(c);
+}
+
+// Allow object keys to be without quotation,
+// but then restrict to ([a-zA-Z0-9_])+
+bool JSON::parse_json_key() {
+  const char* begin;
+  JSON_VAL v;
+  u_char c;
+
+  mark_pos();
+  c = peek();
+  if (c == '"') {
+    return parse_json_string(true);
+  }
+
+  begin = pos;
+  c = peek();
+  if (c == 0) {
+    error(SYNTAX_ERROR, "Got EOS when expecting an object key.");
+    return false;
+  } else if (is_word(c) == false) {
+    error(SYNTAX_ERROR, "Expected an object key, which can be a double-quoted (\") string or a simple string (only alphanumeric characters and underscore, separated by whitespace) that doesn't need to be quoted.");
+    return false;
+  }
+
+  for (;;) {
+    c = peek();
+    // Allow the key to be delimited by control characters and the object key-value separator ':'
+    if (c <= ' ' || c == ':') {
+      break;
+    } else if (is_word(c) == false) {
+      error(SYNTAX_ERROR, "Object key need to be quoted, or consist entirely of alphanumeric characters and underscores.");
+      return false;
+    }
+    next();
+  }
+
+  v.str.start = begin;
+  v.str.length = pos - begin;
+  return callback(JSON_KEY, &v, level);
+}
+
+bool JSON::parse_json_number() {
+  double double_value;
+  int tokens, read;
+  JSON_VAL v;
+
+  mark_pos();
+
+  // Parsing number - for simplicity ints are limited to 2**53
+  // sscanf as a double and check if part is 0.
+  tokens = sscanf(pos, "%lf%n", &double_value, &read);
+  assert(tokens <= 1, "scanf implementation that counts as a token, parsing json numbers will always fail");
+  if (tokens == 1) {
+    assert(read > 0, "sanity");
+
+    if (floor(double_value) == double_value) {
+      // No exponent - treat as an int
+      v.int_value = (int)double_value;
+      if (!callback(JSON_NUMBER_INT, &v, level)) {
+        return false;
+      }
+    } else {
+      v.double_value = double_value;
+      if (!callback(JSON_NUMBER_FLOAT, &v, level)) {
+        return false;
+      }
+    }
+    skip(read);
+    return true;
+  }
+
+  error(SYNTAX_ERROR, "Couldn't parse json number (note that exponents are not supported).");
+  return false;
+}
+
+bool JSON::parse_json_symbol(const char* name, JSON_TYPE symbol) {
+  if (expect_string(name, "maybe you forgot to quote your strings?") == false) {
+    mark_pos();
+    return false;
+  }
+  return callback(symbol, NULL, level);
+}
+
+void JSON::mark_pos() {
+  assert((mark == start || *(mark - 1)) != 0, "buffer overrun");
+  assert(mark <= pos, "mark runahead");
+
+  u_char c;
+
+  while (mark < pos) {
+    c = *mark;
+    assert(c != 0, "pos buffer overrun?");
+    if (c != 0) {
+      mark++;
+      column++;
+    }
+    if (c == '\n') {
+      line++;
+      column = 0;
+    }
+  }
+
+  assert(mark <= pos, "mark runahead");
+}
+
+u_char JSON::next() {
+  assert((pos == start || *(pos - 1)) != 0, "buffer overrun");
+
+  u_char c = *pos;
+  if (c != 0) {
+    pos++;
+  }
+  return c;
+}
+
+u_char JSON::peek() {
+  return *pos;
+}
+
+// Peek ahead i chars (0 is same as peek())
+u_char JSON::peek(size_t i) {
+  u_char c;
+  const char* p;
+
+  p = pos;
+  c = *p;
+  while (i > 0 && c != 0) {
+    i--;
+    p++;
+    c = *p;
+  }
+  return c;
+}
+
+/*
+ * Check that one of the expected characters is next in the stream.
+ * If not, it is an error.
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if the next character was not one of the expected.
+ * Otherwise consumes and returns the expected character that was encountered.
+ */
+int JSON::expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e) {
+  size_t len;
+  u_char c;
+
+  len = strlen(valid_chars);
+  assert(len > 0, "need non-empty string");
+
+  c = peek();
+  if (c == 0) {
+    error(e, "Got EOS when expecting %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+    return 0;
+  }
+  for (size_t i = 0; i < len; i++) {
+    if (c == valid_chars[i]) {
+      return next();
+    }
+  }
+  error(e, "Expected %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+  return -1;
+}
+
+/*
+ * Check that the expected string is next in the stream.
+ * If not, it is an error.
+ * Consumes the expected characters if they are present.
+ * Returns true if the expected characters were present, otherwise false.
+ */
+bool JSON::expect_string(const char* expected_string, const char* error_msg, JSON_ERROR e) {
+  u_char c, expected_char;
+  size_t len;
+
+  assert(expected_string != NULL, "need non-null string");
+  len = strlen(expected_string);
+  assert(len > 0, "need non-empty string");
+
+  for (size_t i = 0; i < len; i++) {
+    expected_char = expected_string[i];
+    assert(expected_char > ' ', "not sane for control characters");
+    if (expected_char <= ' ') {
+      error(INTERNAL_ERROR, "expect got a control char");
+    }
+    c = pos[i];
+    if (c == 0) {
+      error(e, "EOS encountered when expecting %s (\"%s\")", error_msg, expected_string);
+      return false;
+    } else if (c != expected_char) {
+      error(e, "Expected \"%s\" (%s)", expected_string, error_msg);
+      return false;
+    }
+  }
+  skip(len);
+  return true;
+}
+
+/*
+ * Skip i characters.
+ * Returns number of characters skipped.
+ */
+size_t JSON::skip(size_t i) {
+  u_char c;
+  size_t j;
+
+  c = peek();
+  for (j = i; c != 0 && j > 0; j--) {
+    c = next();
+  }
+  return i - j;
+}
+
+/*
+ * Skip whitespace and comments.
+ * Returns the first token after whitespace/comments without consuming it
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if there is an error
+ */
+int JSON::skip_to_token() {
+  for (;;) {
+    int c = peek(0);
+    if (c == '/') {
+      u_char c2 = peek(1);
+      if (c2 == '/') {
+        c = skip_line_comment();
+      } else if (c2 == '*') {
+        c = skip_block_comment();
+        if (c < 0) {
+          return -1;
+        }
+      }
+      // Fall through to keep checking if there
+      // are more whitespace / comments to skip
+    }
+    if (c == 0 || c > ' ') {
+      return c;
+    }
+    next();
+  }
+  return 0;
+}
+
+/*
+ * Skip to, and return the wanted char without consuming it
+ * Returns 0 if EOS is encountered.
+ */
+u_char JSON::skip_to(u_char want) {
+  // We want the bookkeeping done in next().
+  // Otherwise strchr could have been used.
+  u_char c;
+  for(;;) {
+    c = peek();
+    if (c == 0 || c == want) {
+      return c;
+    }
+    next();
+  }
+}
+
+/*
+ * Should only be called when we actually have a line comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Will return the first token after the line comment without consuming it.
+ * Returns 0 if EOS is encoutered.
+ */
+u_char JSON::skip_line_comment() {
+  u_char c;
+
+  // Check that we are not called in error
+  expect_any("/", "line comment start", INTERNAL_ERROR);
+  expect_any("/", "line comment start", INTERNAL_ERROR);
+
+  c = skip_to('\n');
+  if (c == 0) {
+    return 0;
+  }
+  next();
+  return next();
+}
+
+/*
+ * Should only be called when we actually have a block comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Returns the first token after the block comment without consuming it.
+ * Returns -1 if EOS is encountered in the middle of a comment.
+ */
+int JSON::skip_block_comment() {
+  const char* current;
+
+  // Check that we are not called in error.
+  if (peek() != '/' || peek(1) != '*') {
+    // Let expect handle EOS.
+    expect_string("/*", "block comment start", INTERNAL_ERROR);
+    return 0;
+  }
+
+  current = pos;
+  for (;;) {
+    current = strchrnul_(current, '*');
+
+    if (current[0] == 0 || current[1] == 0) {
+      // Advance error marker to start of block comment
+      mark_pos();
+      error(SYNTAX_ERROR, "Block comment started here never ended. Expected \"*/\" before EOS.");
+      return -1;
+    }
+
+    if (current[1] == '/') {
+      pos = current;
+      if (expect_string("*/", "block comment end", INTERNAL_ERROR) == false) {
+        return -1;
+      }
+      // Found block comment end
+      return peek();
+    }
+    current++;
+  }
+}
+
+const char* JSON::strerror(JSON_ERROR e) {
+  switch (e) {
+  case SYNTAX_ERROR:
+    return "Syntax error";
+  case INTERNAL_ERROR:
+    return "Internal error";
+  case KEY_ERROR:
+    return "Key error";
+  case VALUE_ERROR:
+    return "Value error";
+  default:
+    ShouldNotReachHere();
+    return "Unknown error";
+  }
+}
+
+void JSON::error(JSON_ERROR e, const char* format, ...) {
+  _valid = false;
+
+  if (!silent) {
+    const char* line_start;
+    const char* tmp;
+    size_t line_length;
+    va_list args;
+    u_char c;
+
+    _st->print("%s on line %u byte %u: ", JSON::strerror(e), line, column + 1);
+    va_start(args, format);
+    _st->vprint(format, args);
+    _st->cr();
+    va_end(args);
+
+    line_start = mark - column;
+    assert(line_start >= start, "out of bounds");
+    assert(line_start <= mark, "out of bounds");
+    assert(line_start == start || line_start[-1] == '\n', "line counting error");
+
+    c = *pos;
+    if (c == 0) {
+      _st->print("  Got ");
+      _st->print_cr("EOS.");
+    }
+    tmp = mark;
+    c = *tmp;
+    if (c > ' ') {
+      _st->print("  At ");
+      _st->print("'");
+      while (c > ' ') {
+        _st->print("%c", c);
+        tmp++;
+        c = *tmp;
+      }
+      _st->print_cr("'.");
+    }
+
+    // Skip to newline or EOS
+    tmp = strchrnul_(mark, '\n');
+    line_length = tmp - line_start;
+
+    _st->print_cr("%s", line_start);
+  }
+}
+
+#ifndef PRODUCT
+void JSONTest::test(const char* text, bool should_pass) {
+  JSONTest json(text);
+  if (should_pass) {
+    assert(json.valid() == true, "failed on a valid json string");
+    if (VerboseInternalVMTests) {
+      tty->print_cr("-- json test passed as expected --");
+    }
+  } else {
+    assert(json.valid() == false, "succeeded on an invalid json string");
+    if (VerboseInternalVMTests) {
+      tty->print_cr("-- json test failed as expected --");
+    }
+  }
+}
+
+JSONTest::JSONTest(const char* text) : JSON(text, !VerboseInternalVMTests, tty) {
+  prev = JSON_NONE;
+  parse();
+}
+
+bool JSONTest::test() {
+  JSONTest::test("{}", true);
+  JSONTest::test("[]", true);
+  JSONTest::test("  {  }  ", true);
+  JSONTest::test("  [  ]  ", true);
+
+  JSONTest::test("\"error\"", false);
+  JSONTest::test("error", false);
+  JSONTest::test("1", false);
+  JSONTest::test("1.2", false);
+  JSONTest::test("true", false);
+  JSONTest::test("false", false);
+  JSONTest::test("null", false);
+
+  JSONTest::test("[ 1 ]", true);
+  JSONTest::test("[ 1, ]", true);
+  JSONTest::test("[ true ]", true);
+  JSONTest::test("[ true, ]", true);
+  JSONTest::test("[ false ]", true);
+  JSONTest::test("[ false, ]", true);
+  JSONTest::test("[ null ]", true);
+  JSONTest::test("[ null, ]", true);
+  JSONTest::test("[ \"\" ]", true);
+  JSONTest::test("[ \"\", ]", true);
+  JSONTest::test("[ \"elem1\" ]", true);
+  JSONTest::test("[ \"elem1\", ]", true);
+  JSONTest::test("[ \"elem1\", ]", true);
+  JSONTest::test("[ \"elem1\" ]", true);
+  JSONTest::test("[ \"elem1\", \"elem2\" ]", true);
+  JSONTest::test("[ \"elem1\", \"elem2\", ]", true);
+
+
+  JSONTest::test("[ \"elem1\" ] { }", false);
+  JSONTest::test("[ elem1, \"elem2\" ]", false);
+  JSONTest::test("[ \"elem1\"", false);
+  JSONTest::test("[ \"elem1 ]", false);
+  JSONTest::test("[ \"elem1\", \"elem2\"", false);
+  JSONTest::test("[ truefoo ]", false);
+  JSONTest::test("[ falsefoo ]", false);
+  JSONTest::test("[ nullfoo ]", false);
+
+  JSONTest::test("{ key : 1 }", true);
+  JSONTest::test("{ key : 1, }", true);
+  JSONTest::test("{ key : 1.2 }", true);
+  JSONTest::test("{ key : true }", true);
+  JSONTest::test("{ key : true, }", true);
+  JSONTest::test("{ key : false }", true);
+  JSONTest::test("{ key : false, }", true);
+  JSONTest::test("{ key : null }", true);
+  JSONTest::test("{ key : null, }", true);
+  JSONTest::test("{ \"\" : \"\" }", true);
+  JSONTest::test("{ \"\" : \"\", }", true);
+  JSONTest::test("{ \"key1\" : \"val1\" }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true);
+
+  JSONTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false);
+  JSONTest::test("{ \"key\" : \"val\" ", false);
+
+  JSONTest::test("/**/ { }", true);
+  JSONTest::test("/* */ { }", true);
+  JSONTest::test("/*foo*/ { }", true);
+  JSONTest::test("/* *foo */ { }", true);
+  JSONTest::test("/* *foo* */ { }", true);
+  JSONTest::test("/* /*foo */ { }", true);
+  JSONTest::test("{ } /* foo */", true);
+  JSONTest::test("{ } /* foo */ ", true);
+  JSONTest::test("{ } //", true);
+  JSONTest::test("{ } // ", true);
+  JSONTest::test("{ } // foo", true);
+
+  JSONTest::test("/* * / { }", false);
+  JSONTest::test("/ * */ { }", false);
+  JSONTest::test("// { }", false);
+  JSONTest::test("/* { } */", false);
+  JSONTest::test("/* { } */ ", false);
+  JSONTest::test("/* { } ", false);
+  JSONTest::test("{ } /* ", false);
+  JSONTest::test("/* { } *", false);
+  JSONTest::test("{ /* } */", false);
+  JSONTest::test("[ /* ] */", false);
+  JSONTest::test("{ key : \"val\", /* } */", false);
+  JSONTest::test("[ \"val\", /* ] */", false);
+
+  JSONTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+  JSONTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+  JSONTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]},\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}", true);
+  JSONTest::test("/* comment */ { key1 error : { \"☃\" : { \"☃\" : [ \"☃\", \"☃\" ] }, \"☃\" : true }, \"baz\" : [ \"☃\" ], foo : \"☃\",}", false); // first key needs to be quoted since it contains a space
+
+
+  JSONTest::test("[\n]", true);
+
+  JSONTest::test(
+      "[" "\n"
+      "   {"
+      "         // pattern to match against class+method+signature" "\n"
+      "         // leading and trailing wildcard (*) allowed" "\n"
+      "         match: \"foo.bar.*\"," "\n"
+      " " "\n"
+      "         // override defaults for specified compiler" "\n"
+      "         // we may differentiate between levels too. TBD." "\n"
+      "         c1:  {" "\n"
+      "           //override c1 presets " "\n"
+      "           array_bounds_check_removal: false" "\n"
+      "         }," "\n"
+      "" "\n"
+      "         c2: {" "\n"
+      "           // control inlining of method" "\n"
+      "           // + force inline, - dont inline" "\n"
+      "           inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         }," "\n"
+      "" "\n"
+      "         // directives outside a specific preset applies to all compilers" "\n"
+      "         inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         print_assembly: true," "\n"
+      "         verify_oopmaps: true," "\n"
+      "         max_loop_unrolling: 5" "\n"
+      "   }," "\n"
+      "   {" "\n"
+      "         // matching several patterns require an array" "\n"
+      "         match: [\"baz.*\",\"frob*\"]," "\n"
+      "" "\n"
+      "         // only enable c1 for this directive" "\n"
+      "         // all enabled by default. Command disables all not listed" "\n"
+      "         enable: \"c1\"," "\n"
+      "" "\n"
+      "         // applies to all compilers" "\n"
+      "         // + force inline, - dont inline" "\n"
+      "         inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         print_inlining: true," "\n"
+      "" "\n"
+      "         // force matching compiles to be blocking/syncronous" "\n"
+      "         blocking_compile: true" "\n"
+      "   }," "\n"
+      "]" "\n", true);
+
+  return true;
+}
+
+void JSONTest::log(uint indent, const char* format, ...) {
+  if (VerboseInternalVMTests) {
+    if (prev != JSON_KEY) {
+      for (uint i = 0; i < indent; i++) {
+        _st->print("  ");
+      }
+    }
+    va_list args;
+    va_start(args, format);
+    _st->vprint(format, args);
+    va_end(args);
+  }
+}
+
+bool JSONTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) {
+  switch (t) {
+  case JSON_OBJECT_BEGIN:
+    log(rlevel, "{\n");
+    prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly
+    return true;
+
+  case JSON_OBJECT_END:
+    log(rlevel, "},\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_ARRAY_BEGIN:
+    log(rlevel, "[\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_ARRAY_END:
+    log(rlevel, "],\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_KEY:
+    if (VerboseInternalVMTests) {
+      for (uint i = 0; i < rlevel; i++) {
+        _st->print("  ");
+      }
+      _st->print("<key>");
+      for (size_t i = 0; i < v->str.length; i++) {
+        u_char c = v->str.start[i];
+        assert(c != 0, "string overrun");
+        if (c == 0) {
+          return false;
+        }
+        _st->print("%c", c);
+      }
+      _st->print(" : ");
+    }
+    prev = JSON_KEY;
+    return true;
+
+  case JSON_STRING:
+    if (VerboseInternalVMTests) {
+      if (prev != JSON_KEY) {
+        for (uint i = 0; i < rlevel; i++) {
+          _st->print("  ");
+        }
+      }
+      _st->print("<str>");
+      for (size_t i = 0; i < v->str.length; i++) {
+        u_char c = v->str.start[i];
+        assert(c != 0, "string overrun");
+        if (c == 0) {
+          return false;
+        }
+        _st->print("%c", c);
+      }
+      _st->print(",\n");
+    }
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NUMBER_INT:
+    log(rlevel, "<int>%" PRId64 ",\n", v->int_value);
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NUMBER_FLOAT:
+    log(rlevel, "<double>%lf,\n", v->double_value);
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_TRUE:
+    log(rlevel, "<true>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_FALSE:
+    log(rlevel, "<false>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NULL:
+    log(rlevel, "<null>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  default:
+    error(INTERNAL_ERROR, "unknown JSON type");
+    return false;
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.hpp	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_JSON_HPP
+#define SHARE_VM_UTILITIES_JSON_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+
+class JSON : public ResourceObj {
+ protected:
+  JSON(const char* text, bool silent, outputStream* st);
+  void parse();
+  bool valid();
+
+  typedef enum {
+    JSON_NONE,
+    JSON_OBJECT_BEGIN,
+    JSON_OBJECT_END,
+    JSON_ARRAY_BEGIN,
+    JSON_ARRAY_END,
+    JSON_KEY,
+    JSON_STRING,
+    JSON_NUMBER_INT,
+    JSON_NUMBER_FLOAT,
+    JSON_TRUE,
+    JSON_FALSE,
+    JSON_NULL
+  } JSON_TYPE;
+
+  typedef union {
+    int64_t int_value;
+    double double_value;
+
+    struct {
+      const char* start;
+      size_t length;
+    } str;
+  } JSON_VAL;
+
+  typedef enum {
+    INTERNAL_ERROR,
+    SYNTAX_ERROR,
+    KEY_ERROR,
+    VALUE_ERROR
+  } JSON_ERROR;
+
+  void error(JSON_ERROR e, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+  outputStream* _st;
+
+ private:
+  const char* start;
+  const char* pos;
+
+  // For error printing
+  const char* mark; // Error marker
+  uint level;
+  uint line;
+  uint column;
+
+  bool silent;
+  bool _valid;
+
+  bool parse_json_value();
+  bool parse_json_object();
+  bool parse_json_array();
+  bool parse_json_string(bool key = false);
+  bool parse_json_key();
+  bool parse_json_number();
+  bool parse_json_symbol(const char* name, JSON_TYPE symbol);
+
+  virtual bool callback(JSON_TYPE t, JSON_VAL* v, uint level) = 0;
+
+  void mark_pos();
+  u_char next();
+  u_char peek();
+  u_char peek(size_t i);
+  int expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e = SYNTAX_ERROR);
+  bool expect_string(const char* expected_string, const char* error_msg = "", JSON_ERROR e = SYNTAX_ERROR);
+  size_t skip(size_t i);
+  int skip_to_token();
+  u_char skip_to(u_char want);
+  u_char skip_line_comment();
+  int skip_block_comment();
+
+  const char* strerror(JSON_ERROR e);
+};
+
+#ifndef PRODUCT
+class JSONTest : public JSON {
+ public:
+  static bool test();
+
+ private:
+  JSONTest(const char* text);
+  static void test(const char* json, bool valid);
+
+  void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+
+  bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+  JSON_TYPE prev;
+};
+#endif
+
+#endif // SHARE_VM_UTILITIES_JSON_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test InlineMatcherTest
+ * @bug 8074095
+ * @library /testlibrary /../../test/lib
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI InlineMatcherTest
+ * @summary Testing of compiler/InlineMatcher
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import sun.hotspot.WhiteBox;
+
+public class InlineMatcherTest {
+
+    /** Instance of WhiteBox */
+    protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    Method helper;
+    Method getDate;
+    Method inner;
+    Method toString;
+
+    final public static int FORCE_INLINE = 2;
+    final public static int DONT_INLINE = 1;
+    final public static int NO_MATCH = 0;
+    final public static int PARSING_FAILURE = -1;
+
+    public InlineMatcherTest() {
+
+    }
+
+    public void test() throws Exception {
+        // instantiate before calling getMethod on innerHelper
+        TestCases testCases = new TestCases();
+
+        helper = getMethod(InlineMatcherTest.class, "helper");
+
+        testCases.add(helper, "*.*", PARSING_FAILURE);
+        testCases.add(helper, "+*.*", FORCE_INLINE);
+        testCases.add(helper, "++*.*", NO_MATCH); // + is a valid part of the
+                                                  // class name
+        testCases.add(helper, "-*.*", DONT_INLINE);
+        testCases.add(helper, "--*.*", NO_MATCH); // - is a valid part of the
+                                                  // class name
+
+        testCases.add(helper, "+InlineMatcherTest.*", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper()", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper()V", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper(", FORCE_INLINE);
+
+        testCases.add(helper, "-InlineMatcherTest.*", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper()", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper()V", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper(", DONT_INLINE);
+
+        testCases.add(helper, "+abc.*", NO_MATCH);
+        testCases.add(helper, "+*.abc", NO_MATCH);
+        testCases.add(helper, "-abc.*", NO_MATCH);
+        testCases.add(helper, "-*.abcls ", NO_MATCH);
+
+        int failures = 0;
+
+        for (TestCase t : testCases) {
+            System.out.println("Test case: " + t.pattern);
+            if (!t.test()) {
+                failures++;
+                System.out.println(" * FAILED");
+            }
+        }
+        if (failures != 0) {
+            throw new Exception("There where " + failures + " failures in this test");
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        InlineMatcherTest test = new InlineMatcherTest();
+        test.test();
+    }
+
+    public void helper() {
+
+    }
+
+    private static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+        try {
+            return klass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("exception on getting method Helper." + name, e);
+        }
+    }
+
+    class TestCase {
+        String pattern;
+        Method testTarget;
+        int expectedResult;
+
+        public TestCase(Method testTarget, String pattern, int expectedResult) {
+            this.testTarget = testTarget;
+            this.pattern = pattern;
+            this.expectedResult = expectedResult;
+        }
+
+        public String resultAsStr(int errorCode) {
+            switch (errorCode) {
+            case PARSING_FAILURE:
+                return "Parsing failed";
+            case NO_MATCH:
+                return "No match";
+            case DONT_INLINE:
+                return "Dont Inline";
+            case FORCE_INLINE:
+                return "Force Inline";
+            default:
+                return "Unknown error";
+            }
+        }
+
+        boolean test() {
+            int result = WHITE_BOX.matchesInline(testTarget, pattern);
+            if (result != expectedResult) {
+                System.out
+                        .println("FAIL Wrong result, Got: " + resultAsStr(result) + "\n TestCase: " + this.toString());
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "Method: '" + testTarget.toString() + "' Pattern: '" + pattern + "' Expected: "
+                    + resultAsStr(expectedResult);
+        }
+
+        public void innerHelper() {
+
+        }
+    }
+
+    class TestCases extends ArrayList<TestCase> {
+        private static final long serialVersionUID = 1L;
+
+        public boolean add(Method testTarget, String pattern, int expectedResult) {
+            return super.add(new TestCase(testTarget, pattern, expectedResult));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityBase
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityBase {
+
+    public static final WhiteBox WB = WhiteBox.getWhiteBox();
+    public static String control_on, control_off;
+    Method method, nomatch;
+
+    public void run(CommandExecutor executor) throws Exception {
+
+        control_on = System.getProperty("test.src", ".") + File.separator + "control_on.txt";
+        control_off = System.getProperty("test.src", ".") + File.separator + "control_off.txt";
+        method  = getMethod(TestCompilerDirectivesCompatibilityBase.class, "helper");
+        nomatch = getMethod(TestCompilerDirectivesCompatibilityBase.class, "another");
+
+        testCompatibility(executor);
+    }
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default off
+        expect(!WB.getBooleanVMFlag("PrintAssembly"));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it on
+        executor.execute("Compiler.directives_add " + control_on);
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+    }
+
+    public void expect(boolean test) throws Exception {
+        if (!test) {
+            throw new Exception("Test failed");
+        }
+    }
+
+    public void expect(boolean test, String msg) throws Exception {
+        if (!test) {
+            throw new Exception(msg);
+        }
+    }
+
+    @Test
+    public void jmx() throws Exception {
+        run(new JMXExecutor());
+    }
+
+    public void helper() {
+    }
+
+    public void another() {
+    }
+
+    public static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+        try {
+            return klass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("exception on getting method Helper." + name, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityCommandOff
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOff extends TestCompilerDirectivesCompatibilityBase {
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default off
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it on
+        executor.execute("Compiler.directives_add " + control_on);
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is false again
+        executor.execute("Compiler.directives_remove");
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityCommandOn
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOn
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOn extends TestCompilerDirectivesCompatibilityBase{
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default on
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it off
+        executor.execute("Compiler.directives_add " + control_off);
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCompilerDirectivesCompatibilityFlag
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityFlag extends TestCompilerDirectivesCompatibilityBase {
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default on
+        expect(WB.getBooleanVMFlag("PrintAssembly"));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it off
+        executor.execute("Compiler.directives_add " + control_off);
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=compileonly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.COMPILEONLY, Scenario.Type.FILE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=exclude
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.ExcludeTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.EXCLUDE, Scenario.Type.FILE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=log
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.LogTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.LOG, Scenario.Type.FILE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=print
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commandfile.PrintTest
+ */
+
+package compiler.compilercontrol.commandfile;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.PRINT, Scenario.Type.FILE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=compileonly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.COMPILEONLY, Scenario.Type.OPTION).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=exclude
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.ExcludeTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.EXCLUDE, Scenario.Type.OPTION).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/LogTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=log
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.LogTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.LOG, Scenario.Type.OPTION).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests CompileCommand=print
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.commands.PrintTest
+ */
+
+package compiler.compilercontrol.commands;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.PRINT, Scenario.Type.OPTION).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_off.txt	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,7 @@
+[
+  {    
+    match: "*.helper",
+    PrintAssembly: false,
+    DisableIntrinsic:"x"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_on.txt	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,7 @@
+[
+  {    
+    match: "*.helper",
+    PrintAssembly: true,
+    DisableIntrinsic:"_dsin"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to compile only specified  methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build CompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.CompileOnlyTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class CompileOnlyTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.COMPILEONLY, Scenario.Type.DIRECTIVE)
+                .test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to exclude methods from compilation
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.ExcludeTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class ExcludeTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.EXCLUDE, Scenario.Type.DIRECTIVE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/LogTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to turn on LogCompilation
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build LogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.LogTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class LogTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.LOG, Scenario.Type.DIRECTIVE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to turn on print_assembly
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build PrintTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.directives.PrintTest
+ */
+
+package compiler.compilercontrol.directives;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class PrintTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.PRINT, Scenario.Type.DIRECTIVE).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directives to be able to add and remove directives
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddAndRemoveTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddAndRemoveTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class AddAndRemoveTest extends AbstractTestBase {
+    private static final int AMOUNT = Integer.getInteger(
+            "compiler.compilercontrol.jcmd.AddAndRemoveTest.amount", 10);
+
+    public static void main(String[] args) {
+        new AddAndRemoveTest().test();
+    }
+
+    @Override
+    public void test() {
+        Scenario.Builder builder = Scenario.getBuilder();
+        // Add some commands with JCMD
+        for (int i = 0; i < AMOUNT; i++) {
+            Executable exec = Utils.getRandomElement(METHODS).first;
+            MethodDescriptor md = getValidMethodDescriptor(exec);
+            CompileCommand compileCommand = new JcmdCommand(Command.COMPILEONLY,
+                    md, null, Scenario.Type.JCMD, Scenario.JcmdType.ADD);
+            compileCommand.print();
+            builder.add(compileCommand);
+        }
+        // Remove half of them
+        for (int i = 0; i < AMOUNT / 2; i++) {
+            /* remove jcmd command doesn't need method, compiler etc.
+               command will be ignored */
+            builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                    Scenario.Type.JCMD, Scenario.JcmdType.REMOVE));
+        }
+        Scenario scenario = builder.build();
+        scenario.execute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to compile only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddCompileOnlyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddCompileOnlyTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddCompileOnlyTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.COMPILEONLY, Scenario.Type.JCMD)
+                .test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to exclude only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddExcludeTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddExcludeTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddExcludeTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.EXCLUDE, Scenario.Type.JCMD)
+                .test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to log only specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddLogTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddLogTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddLogTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.LOG, Scenario.Type.JCMD)
+                .test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests jcmd to be able to add a directive to print assembly
+ *          only for specified methods
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build AddPrintAssemblyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.AddPrintAssemblyTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.SingleCommand;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.Scenario;
+
+public class AddPrintAssemblyTest {
+    public static void main(String[] args) {
+        new SingleCommand(Command.PRINT, Scenario.Type.JCMD)
+                .test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @ignore 8140405
+ * @summary Tests jcmd to be able to clear directives added via options
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ClearDirectivesFileStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class ClearDirectivesFileStackTest extends AbstractTestBase {
+    private static final int AMOUNT = Utils.getRandomInstance().nextInt(100);
+    private final CommandGenerator cmdGen = new CommandGenerator();
+
+    public static void main(String[] args) {
+        new ClearDirectivesFileStackTest().test();
+    }
+
+    @Override
+    public void test() {
+        Scenario.Builder builder = Scenario.getBuilder();
+        // Add some commands with directives file
+        for (int i = 0; i < AMOUNT; i++) {
+            Executable exec = Utils.getRandomElement(METHODS).first;
+            MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec);
+            Command command = cmdGen.generateCommand();
+            if (command == Command.NONEXISTENT) {
+                // skip invalid command
+                command = Command.COMPILEONLY;
+            }
+            CompileCommand compileCommand = new CompileCommand(command,
+                    methodDescriptor, cmdGen.generateCompiler(),
+                    Scenario.Type.DIRECTIVE);
+            compileCommand.print();
+            builder.add(compileCommand);
+        }
+        // print all directives before
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+        // clear the stack
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));
+        // print all directives after the clear
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+        Scenario scenario = builder.build();
+        scenario.execute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests clear JCMD command
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build ClearDirectivesStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesStackTest
+ */
+
+package compiler.compilercontrol.jcmd;
+
+import compiler.compilercontrol.share.AbstractTestBase;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.JcmdCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class ClearDirectivesStackTest extends AbstractTestBase {
+    private static final int AMOUNT = Utils.getRandomInstance().nextInt(100);
+    private final CommandGenerator cmdGen = new CommandGenerator();
+
+    public static void main(String[] args) {
+        new ClearDirectivesStackTest().test();
+    }
+
+    @Override
+    public void test() {
+        Scenario.Builder builder = Scenario.getBuilder();
+        // Add some commands with JCMD
+        for (int i = 0; i < AMOUNT; i++) {
+            Executable exec = Utils.getRandomElement(METHODS).first;
+            MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec);
+            CompileCommand compileCommand = new JcmdCommand(
+                    cmdGen.generateCommand(), methodDescriptor,
+                    cmdGen.generateCompiler(), Scenario.Type.JCMD,
+                    Scenario.JcmdType.ADD);
+            compileCommand.print();
+            builder.add(compileCommand);
+        }
+        // print all directives before
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+        // clear the stack
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));
+        // print all directives after the clear
+        builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
+                Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
+        Scenario scenario = builder.build();
+        scenario.execute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Randomly generates commands with random types
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build RandomCommandsTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest
+ */
+
+package compiler.compilercontrol.mixed;
+
+import compiler.compilercontrol.share.MultiCommand;
+
+public class RandomCommandsTest {
+    public static void main(String[] args) {
+        MultiCommand.generateRandomTest(false).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @ignore 8140667
+ * @summary Randomly generates valid commands with random types
+ * @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
+ * @build RandomValidCommandsTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
+ *        compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomValidCommandsTest
+ */
+
+package compiler.compilercontrol.mixed;
+
+import compiler.compilercontrol.share.MultiCommand;
+
+public class RandomValidCommandsTest {
+    public static void main(String[] args) {
+        MultiCommand.generateRandomTest(true).test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8137167
+ * @summary Tests directive json parser
+ * @library /testlibrary /../../test/lib ../share /
+ * @run driver compiler.compilercontrol.parser.DirectiveParser
+ */
+
+package compiler.compilercontrol.parser;
+
+import compiler.compilercontrol.share.JSONFile;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+
+public class DirectiveParser {
+    private static final String ERROR_MSG = "VM should exit with error "
+            + "on incorrect JSON file: ";
+    private static final String EXPECTED_ERROR_STRING = "Parsing of compiler"
+            + " directives failed";
+
+    public static void main(String[] args) {
+        simpleTest();
+        nonMatchingBrackets();
+        arrayTest();
+        emptyObjectTest();
+        emptyFile();
+        noFile();
+        directory();
+    }
+
+    private static void simpleTest() {
+        String fileName = "simple.json";
+        try (JSONFile file = new JSONFile(fileName)) {
+            file.write(JSONFile.Element.ARRAY)
+                    .write(JSONFile.Element.OBJECT)
+                        .write(JSONFile.Element.PAIR, "match")
+                        .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"")
+                        .write(JSONFile.Element.PAIR, "c2")
+                        .write(JSONFile.Element.OBJECT)
+                            .write(JSONFile.Element.PAIR, "inline")
+                            .write(JSONFile.Element.ARRAY)
+                                .write(JSONFile.Element.VALUE, "\"+*.indexOf\"")
+                                .write(JSONFile.Element.VALUE, "\"-a.b\"")
+                            .end()
+                        .end()
+                    .end() // end object
+                    .write(JSONFile.Element.OBJECT)
+                        .write(JSONFile.Element.PAIR, "match")
+                        .write(JSONFile.Element.VALUE, "\"*.indexOf\"")
+                        .write(JSONFile.Element.PAIR, "c1")
+                        .write(JSONFile.Element.OBJECT)
+                            .write(JSONFile.Element.PAIR, "enable")
+                            .write(JSONFile.Element.VALUE, "false")
+                        .end()
+                    .end(); // end object
+            file.end();
+        }
+        OutputAnalyzer output = execute(fileName);
+        output.shouldHaveExitValue(0);
+        output.shouldNotContain(EXPECTED_ERROR_STRING);
+    }
+
+    private static void nonMatchingBrackets() {
+        String fileName = "non-matching.json";
+        try (JSONFile file = new JSONFile(fileName)) {
+            file.write(JSONFile.Element.ARRAY)
+                    .write(JSONFile.Element.OBJECT)
+                        .write(JSONFile.Element.PAIR, "match")
+                        .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"")
+                    .end();
+            // don't write matching }
+        }
+        OutputAnalyzer output = execute(fileName);
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non matching "
+                + "brackets");
+        output.shouldContain(EXPECTED_ERROR_STRING);
+    }
+
+    private static void arrayTest() {
+        String fileName = "array.json";
+        try (JSONFile file = new JSONFile(fileName)) {
+            file.write(JSONFile.Element.ARRAY);
+            file.end();
+        }
+        OutputAnalyzer output = execute(fileName);
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty array");
+    }
+
+    private static void emptyObjectTest() {
+        String fileName = "emptyObject.json";
+        try (JSONFile file = new JSONFile(fileName)) {
+            file.write(JSONFile.Element.OBJECT);
+            file.end();
+        }
+        OutputAnalyzer output = execute(fileName);
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty object "
+                + "without any match");
+        output.shouldContain(EXPECTED_ERROR_STRING);
+    }
+
+    private static void emptyFile() {
+        String fileName = "empty.json";
+        try (JSONFile file = new JSONFile(fileName)) {
+            // empty
+        }
+        OutputAnalyzer output = execute(fileName);
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty file");
+        output.shouldContain(EXPECTED_ERROR_STRING);
+    }
+
+    private static void noFile() {
+        OutputAnalyzer output = execute("nonexistent.json");
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non existing "
+                + "file");
+    }
+
+    private static void directory() {
+        OutputAnalyzer output = execute(Utils.TEST_SRC);
+        Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "directory as "
+                + "a name");
+    }
+
+    private static OutputAnalyzer execute(String fileName) {
+        OutputAnalyzer output;
+        try {
+            output = ProcessTools.executeTestJvm(
+                    "-XX:+UnlockDiagnosticVMOptions",
+                    "-XX:CompilerDirectivesFile=" + fileName,
+                    "-version");
+        } catch (Throwable thr) {
+            throw new Error("Execution failed", thr);
+        }
+        return output;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public abstract class AbstractTestBase {
+    protected static final MethodGenerator METHOD_GEN = new MethodGenerator();
+    protected static final int ATTEMPTS = 25;
+    protected static final List<Pair<Executable, Callable<?>>> METHODS
+            = new PoolHelper().getAllMethods(PoolHelper.METHOD_FILTER);
+
+    public abstract void test();
+
+    /**
+     * Generate random valid method descriptor
+     *
+     * @param exec method to make descriptor for
+     * @return a valid {@link MethodDescriptor#isValid()} descriptor instance
+     */
+    public static MethodDescriptor getValidMethodDescriptor(Executable exec) {
+        MethodDescriptor md = METHOD_GEN.generateRandomDescriptor(exec);
+        for (int i = 0; !md.isValid() && i < ATTEMPTS; i++) {
+            md = METHOD_GEN.generateRandomDescriptor(exec);
+        }
+        if (!md.isValid()) {
+            System.out.println("WARN: Using predefined pattern");
+            md = MethodGenerator.commandDescriptor(exec);
+        }
+        return md;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/JSONFile.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.Objects;
+import java.util.Stack;
+
+/**
+ * Simple JSON file writer
+ */
+public class JSONFile implements AutoCloseable {
+    private final Stack<Element> stack;
+    private final String fileName;
+    private final PrintStream out;
+    private int spaces;
+
+    /**
+     * JSON element
+     */
+    public enum Element {
+        OBJECT,
+        ARRAY,
+        PAIR,
+        VALUE
+    }
+
+    /**
+     * Constructor. Creates file with default name
+     */
+    public JSONFile() {
+        this("directives_file.json");
+    }
+
+    /**
+     * Constructor
+     *
+     * @param fileName file name
+     */
+    public JSONFile(String fileName) {
+        this.spaces = 0;
+        this.stack = new Stack<>();
+        this.fileName = fileName;
+        try {
+            out = new PrintStream(fileName);
+        } catch (FileNotFoundException e) {
+            throw new Error("TESTBUG: can't open/create file " + fileName, e);
+        }
+    }
+
+    /**
+     * Gets file name
+     *
+     * @return file name string
+     */
+    public String getFileName() {
+        return fileName;
+    }
+
+    /**
+     * Gets current JSON element in the file.
+     * The element is a current {@linkplain Element}
+     * that was written into a file.
+     *
+     * @return the type of the current element,
+     * or null if there are nothing written
+     */
+    public Element getElement() {
+        if (stack.empty()) {
+            return null;
+        }
+        return stack.peek();
+    }
+
+    /**
+     * Writes given type with a value to file.
+     * Note that only PAIR and VALUE types accept a single value parameter.
+     * OBJECT and ARRAY do not have a value
+     *
+     * @param element  JSON element type
+     * @param value element's value
+     * @return this file instance
+     */
+    public JSONFile write(Element element, String... value) {
+        if (value.length > 1) {
+            throw new Error("TESTBUG: Unexpected value length: "
+                    + value.length);
+        }
+        if (!stack.empty()) {
+            if (stack.peek() == Element.VALUE) {
+                out.print(", ");
+                stack.pop();
+            }
+        }
+        switch (element) {
+            case OBJECT:
+                out.print("{");
+                spaces++;
+                stack.push(Element.VALUE);
+                break;
+            case ARRAY:
+                out.print("[");
+                stack.push(Element.VALUE);
+                break;
+            case PAIR:
+                fillSpaces();
+                Objects.requireNonNull(value, "TESTBUG: " + element
+                        + "requires a value to be set");
+                out.print(value[0] + ": ");
+                break;
+            case VALUE:
+                Objects.requireNonNull(value, "TESTBUG: " + element
+                        + "requires a value to be set");
+                out.print(value[0]);
+                break;
+        }
+        stack.push(element);
+        return this;
+    }
+
+    private void fillSpaces() {
+        out.println();
+        for (int i = 0; i < spaces; i++) {
+            // Fill with spaces to be more readable
+            out.print("  ");
+        }
+    }
+
+    /**
+     * Ends current object or array of {@linkplain Element}
+     *
+     * @return this file instance
+     */
+    public JSONFile end() {
+        if (!stack.empty()) {
+            Element prev = stack.pop();
+            while (prev != Element.OBJECT && prev != Element.ARRAY
+                    && !stack.empty()) {
+                prev = stack.pop();
+            }
+            switch (prev) {
+                case OBJECT:
+                    spaces--;
+                    fillSpaces();
+                    out.print("}");
+                    break;
+                case ARRAY:
+                    out.print("]");
+                    break;
+                default:
+                    throw new Error("TESTBUG: Incorrect end. " +
+                            "Wrong type found: " + prev);
+            }
+        } else {
+            throw new Error("TESTBUG: Incorrect end. Empty stack");
+        }
+        return this;
+    }
+
+    /**
+     * Closes this file
+     */
+    @Override
+    public void close() {
+        out.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MultiCommand extends AbstractTestBase {
+    private final List<CompileCommand> testCases;
+
+    public MultiCommand(List<CompileCommand> testCases) {
+        this.testCases = testCases;
+    }
+
+    /**
+     * Generates a test containing multiple random commands
+     *
+     * @param validOnly shows that all commands should be valid
+     * @return test instance to run
+     */
+    public static AbstractTestBase generateRandomTest(boolean validOnly) {
+        CommandGenerator cmdGen = new CommandGenerator();
+        List<Command> commands = cmdGen.generateCommands();
+        List<CompileCommand> testCases = new ArrayList<>();
+        for (Command cmd : commands) {
+            if (validOnly && cmd == Command.NONEXISTENT) {
+                // skip invalid command
+                continue;
+            }
+            Executable exec = Utils.getRandomElement(METHODS).first;
+            MethodDescriptor md;
+            if (validOnly) {
+                md = AbstractTestBase.getValidMethodDescriptor(exec);
+            } else {
+                md = AbstractTestBase.METHOD_GEN.generateRandomDescriptor(exec);
+            }
+            CompileCommand cc = cmdGen.generateCompileCommand(cmd, md, null);
+            testCases.add(cc);
+        }
+        return new MultiCommand(testCases);
+    }
+
+    @Override
+    public void test() {
+        Scenario.Builder builder = Scenario.getBuilder();
+        for (CompileCommand cc : testCases) {
+            cc.print();
+            builder.add(cc);
+        }
+        Scenario scenario = builder.build();
+        scenario.execute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/SingleCommand.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.scenario.Command;
+import compiler.compilercontrol.share.scenario.CommandGenerator;
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import compiler.compilercontrol.share.scenario.Scenario;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+
+public class SingleCommand extends AbstractTestBase {
+    private final Command command;
+    private final Scenario.Type type;
+
+    public SingleCommand(Command command, Scenario.Type type) {
+        this.command = command;
+        this.type = type;
+    }
+
+    @Override
+    public void test() {
+        Scenario.Builder builder = Scenario.getBuilder();
+        Executable exec = Utils.getRandomElement(METHODS).first;
+        MethodDescriptor md = getValidMethodDescriptor(exec);
+        CommandGenerator cmdGen = new CommandGenerator();
+        CompileCommand compileCommand = cmdGen.generateCompileCommand(command,
+                md, type);
+        compileCommand.print();
+        builder.add(compileCommand);
+        Scenario scenario = builder.build();
+        scenario.execute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.actions;
+
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.Pair;
+import jdk.test.lib.ProcessTools;
+import pool.PoolHelper;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+import java.lang.reflect.Executable;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
+
+public class BaseAction {
+    private static final List<Pair<Executable, Callable<?>>> METHODS;
+    private static final Map<String, Executable> METHODS_NAMES;
+
+    static {
+        METHODS = new PoolHelper().getAllMethods();
+        METHODS_NAMES = METHODS.stream().collect(Collectors.toMap(
+                pair -> pair.first.toGenericString(),
+                pair -> pair.first));
+    }
+
+    public static void main(String[] args) {
+        if (args.length < 1) {
+            throw new Error("TESTBUG: requires port as parameter: "
+                    + Arrays.toString(args));
+        }
+        int pid;
+        try {
+            pid = ProcessTools.getProcessId();
+        } catch (Exception e) {
+            throw new Error("Could not determine own pid", e);
+        }
+        int port = Integer.parseInt(args[0]);
+        System.out.println("INFO: Client connection port = " + port);
+        List<String> lines;
+        try (
+                Socket socket = new Socket(InetAddress.getLocalHost(), port);
+                BufferedReader in = new BufferedReader(
+                        new InputStreamReader(socket.getInputStream()));
+                PrintWriter out = new PrintWriter(
+                        new OutputStreamWriter(socket.getOutputStream()))) {
+            // send own pid to execute jcmd if needed
+            out.println(String.valueOf(pid));
+            out.flush();
+            lines = in.lines().collect(Collectors.toList());
+        } catch (IOException e) {
+            throw new Error("Error on performing network operation", e);
+        }
+        check(decodeMap(lines));
+    }
+
+    private static Map<Executable, State> decodeMap(List<String> lines) {
+        if (lines == null || lines.size() == 0) {
+            throw new Error("TESTBUG: unexpected lines list");
+        }
+        Map<Executable, State> stateMap = new HashMap<>();
+        int startIndex = 0;
+        ListIterator<String> iterator = lines.listIterator();
+        while (iterator.hasNext()) {
+            int index = iterator.nextIndex();
+            String next = iterator.next();
+            switch (next) {
+                case "{" :
+                    startIndex = index;
+                    break;
+                case "}" :
+                    // method name goes after {
+                    Executable executable = METHODS_NAMES.get(lines.get(
+                            ++startIndex));
+                    // state description starts after method
+                    State state = State.fromString(lines.subList(++startIndex,
+                            index).toArray(new String[index - startIndex]));
+                    stateMap.put(executable, state);
+                    break;
+            }
+        }
+        return stateMap;
+    }
+
+    protected static void check(Map<Executable, State> methodStates) {
+        // Check each method from the pool
+        METHODS.forEach(pair -> {
+            Executable x = pair.first;
+            CompileAction.checkCompiled(x, methodStates.get(x));
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/actions/CompileAction.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.actions;
+
+import compiler.compilercontrol.share.scenario.State;
+import compiler.testlibrary.CompilerUtils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Pair;
+import jdk.test.lib.Utils;
+import pool.PoolHelper;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class CompileAction {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final int[] COMP_LEVELS;
+    private static final List<Pair<Executable, Callable<?>>> METHODS
+            = new PoolHelper().getAllMethods();
+    private static final int EXEC_AMOUNT = 100;
+
+    static {
+        COMP_LEVELS = CompilerUtils.getAvailableCompilationLevels();
+        if (COMP_LEVELS.length == 0) {
+            throw new Error("TESTBUG: test requires JIT " +
+                    "compiler to be available");
+        }
+    }
+
+    /**
+     * Checks executable if it could be compiled
+     *
+     * @param executable given executable to check
+     * @param state method compilation state
+     */
+    public static void checkCompiled(Executable executable,
+                                     State state) {
+        int first = COMP_LEVELS[0];
+        if (first < 4) {
+            checkCompilation(executable, first, state.isC1Compilable());
+        }
+        int last = COMP_LEVELS[COMP_LEVELS.length - 1];
+        if (last == 4) {
+            checkCompilation(executable, last, state.isC2Compilable());
+        }
+    }
+
+    private static void checkCompilation(Executable executable,
+                                         int level,
+                                         boolean expectedCompiled) {
+        execute(executable);
+        WHITE_BOX.enqueueMethodForCompilation(executable, level);
+        Utils.waitForCondition(
+                () -> {
+                    execute(executable);
+                    return !WHITE_BOX.isMethodQueuedForCompilation(executable);
+                }, 100L);
+        execute(executable);
+        boolean isCompilable = WHITE_BOX.isMethodCompilable(executable, level);
+        Asserts.assertEQ(isCompilable, expectedCompiled,
+                String.format("FAILED: method %s compilable: %b, but should: %b"
+                        + " on required level: %d", executable, isCompilable,
+                        expectedCompiled, level));
+    }
+
+    private static void execute(Executable executable) {
+        Callable<?> callable = getCallableFor(executable);
+        try {
+            for (int i = 0; i < EXEC_AMOUNT; i++) {
+                callable.call();
+            }
+        } catch (Exception e) {
+            throw new Error("Got exception during execution", e);
+        }
+    }
+
+    private static Callable<?> getCallableFor(Executable executable) {
+        for (Pair<Executable, Callable<?>> pair : METHODS) {
+            if (pair.first == executable) {
+                return pair.second;
+            }
+        }
+        throw new Error("TESTBUG: wrong executable: " + executable);
+    }
+}
--- a/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java	Wed Jul 05 20:58:59 2017 +0200
@@ -124,6 +124,23 @@
     }
 
     /**
+     * Method descriptor that matches any method. Its full signature is *.*
+     *
+     * @param executable executable used to generate descriptor
+     * @return MethodDescriptor instance
+     */
+    public static MethodDescriptor anyMatchDescriptor(Executable executable) {
+        MethodDescriptor md = new MethodDescriptor(executable);
+        Combination<PatternType> patterns = new Combination<>(PatternType.ANY,
+                PatternType.ANY, PatternType.ANY);
+        md.aClass.setSeparator(Separator.SLASH);
+        md.aMethod.setSeparator(Separator.DOT);
+        md.aSignature.setSeparator(Separator.NONE);
+        md.setPatterns(patterns);
+        return md;
+    }
+
+    /**
      * Generates a list of method patterns from the pool of methods
      *
      * @return a list of test cases
@@ -206,6 +223,8 @@
         elements.add(input -> "_" + input);
         elements.add(input -> "$" + input);
         elements.add(input -> "0" + input);
+
+        /* TODO: uncomment this together with the fix for 8140631
         // Unicode characters
         elements.add(input -> embed(input, "\u0001"));
         elements.add(input -> embed(input, "\u007F"));
@@ -214,6 +233,7 @@
         elements.add(input -> embed(input, "\u0306"));
         // Supplementary character
         elements.add(input -> new String(Character.toChars(0x1F64C)));
+        */
         return elements;
     }
 
--- a/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java	Wed Jul 05 20:58:59 2017 +0200
@@ -29,6 +29,7 @@
 import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.regex.Pattern;
 
 /**
  * This class represents a signature of the method
@@ -66,7 +67,8 @@
         if (element.isEmpty()) {
             setPattern(MethodDescriptor.PatternType.ANY);
         } else {
-            super.setElement(element);
+            this.element = element;
+            this.regexp = element;
         }
     }
 
@@ -148,4 +150,12 @@
                         + patternType);
         }
     }
+
+    @Override
+    public String getRegexp() {
+        if ("\\(.*\\).*".equals(regexp)) {
+            return regexp;
+        }
+        return Pattern.quote(regexp);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import jdk.test.lib.OutputAnalyzer;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Checks that output contains a string with commands and full method pattern
+ */
+public class CommandProcessor implements Consumer<OutputAnalyzer> {
+    protected final List<CompileCommand> commands;
+
+    public CommandProcessor(List<CompileCommand> commands) {
+        this.commands = commands;
+    }
+
+    @Override
+    public void accept(OutputAnalyzer outputAnalyzer) {
+        for (CompileCommand command : commands) {
+            if (command.isValid()) {
+                outputAnalyzer.shouldContain("CompileCommand: "
+                        + command.command.name + " "
+                        + command.methodDescriptor.getCanonicalString());
+                outputAnalyzer.shouldNotContain("CompileCommand: An error "
+                        + "occurred during parsing");
+            } else {
+                outputAnalyzer.shouldMatch("(CompileCommand: )"
+                        + "(unrecognized command)|(Bad pattern)|"
+                        + "(An error occurred during parsing)");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Log compilation file processor
+ */
+public class LogProcessor implements Consumer<OutputAnalyzer> {
+    public static final String LOG_FILE = "compilation.log";
+    private static final String TASK_ELEMENT = "<task [^>]*>";
+    private static final String TASK_DONE_ELEMENT = "<task_done [^>]*>";
+    private static final String TASK_END_ELEMENT = "</task>";
+    private static final String ANY_ELEMENT = "<[^>]*>";
+    private static final Pattern METHOD_PATTERN = Pattern.compile(
+            "method='([^']+)'");
+    private final List<String> loggedMethods;
+    private final List<String> testMethods;
+    private Scanner scanner = null;
+
+    public LogProcessor(Map<Executable, State> states) {
+        loggedMethods = states.keySet().stream()
+                .filter(x -> states.get(x).isLog())
+                .map(MethodGenerator::logDescriptor)
+                .map(MethodDescriptor::getString)
+                .collect(Collectors.toList());
+        testMethods = new PoolHelper().getAllMethods()
+                .stream()
+                .map(pair -> pair.first)
+                .map(MethodGenerator::logDescriptor)
+                .map(MethodDescriptor::getString)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void accept(OutputAnalyzer outputAnalyzer) {
+        if (loggedMethods.isEmpty()) {
+            return;
+        }
+        getScanner();
+        matchTasks();
+    }
+
+    /*
+     * Gets scanner for log file of the test case
+     */
+    private Scanner getScanner() {
+        File logFile = new File(LOG_FILE);
+        try {
+            scanner = new Scanner(logFile);
+        } catch (FileNotFoundException e) {
+            throw new Error("TESTBUG: file not found: " + logFile, e);
+        }
+        return scanner;
+    }
+
+    /*
+     * Parses for &lt;task method='java.lang.String indexOf (I)I' &gt;
+     * and finds if there is a compilation log for this task
+     */
+    private void matchTasks() {
+        String task = scanner.findWithinHorizon(TASK_ELEMENT, 0);
+        while (task != null) {
+            String element = scanner.findWithinHorizon(ANY_ELEMENT, 0);
+            if (Pattern.matches(TASK_DONE_ELEMENT, element)
+                    || Pattern.matches(TASK_END_ELEMENT, element)) {
+                /* If there is nothing between <task> and </task>
+                   except <task done /> then compilation log is empty */
+                Asserts.assertTrue(matchMethod(task), "Compilation log "
+                        + "expected. Met: " + element);
+            }
+            task = scanner.findWithinHorizon(TASK_ELEMENT, 0);
+        }
+    }
+
+    // Matches given string to regular expression
+    private boolean matchMethod(String input) {
+        Matcher matcher = METHOD_PATTERN.matcher(input);
+        Asserts.assertTrue(matcher.find(), "Wrong matcher or input");
+        // Get method and normalize it
+        String method = normalize(matcher.group(1));
+        // Check that this method matches regexp
+        return loggedMethods.contains(method) || !testMethods.contains(method);
+    }
+
+    // Normalize given signature to conform regular expression used in tests
+    private String normalize(String method) {
+        return method.replaceAll("\\.", "/") // replace dots in a class string
+                .replaceFirst(" ", ".")      // replace space between class and method
+                .replaceFirst(" ", "")       // remove space between method and signature
+                .replace("&lt;", "<")
+                .replace("&gt;", ">");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/PrintProcessor.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import compiler.compilercontrol.share.scenario.State;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Process output to find compiled methods assemblies printed by print command
+ */
+public class PrintProcessor implements Consumer<OutputAnalyzer> {
+    /**
+     * Compiled method string pattern.
+     * Capturing groups are
+     * 1. Compiler used to compile this method
+     * 2. Time stamp
+     * 3. Compile ID
+     * 4. Method attributes
+     * 5. Compilation level
+     * 6. Method name
+     */
+    private static final Pattern COMPILED_METHOD
+            = Pattern.compile("Compiled method (?<compiler>\\(.*\\))[ ]+"
+            + "(?<time>[0-9]+)[ ]+(?<id>[0-9]+) (?<attr>[ !%sbn]{6})"
+            + "(?<level>[0-9]+)[ ]+(?<name>[^ ]+).*");
+    private final List<String> printMethods;
+    private final List<String> testMethods;
+
+    public PrintProcessor(Map<Executable, State> states) {
+        printMethods = states.keySet().stream()
+                .filter(x -> states.get(x).isPrintAssembly())
+                .map(MethodGenerator::logDescriptor)
+                .map(MethodDescriptor::getString)
+                .map(s -> s.replaceFirst("\\(.*", "")) // remove signature
+                .collect(Collectors.toList());
+        testMethods = new PoolHelper().getAllMethods()
+                .stream()
+                .map(pair -> pair.first)
+                .map(MethodGenerator::logDescriptor)
+                .map(MethodDescriptor::getString)
+                .map(s -> s.replaceFirst("\\(.*", "")) // remove signature
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void accept(OutputAnalyzer outputAnalyzer) {
+        boolean wizardMode = false;
+        try {
+            wizardMode = Boolean.parseBoolean(ManagementFactory
+                    .getPlatformMXBean(HotSpotDiagnosticMXBean.class)
+                    .getVMOption("WizardMode").getValue());
+        } catch (IllegalArgumentException e) {
+            // ignore exception because WizardMode exists in debug only builds
+        }
+        if (wizardMode) {
+            System.out.println("SKIP: WizardMode's output are not supported");
+            return;
+        }
+        for (String line : outputAnalyzer.asLines()) {
+            Matcher matcher = COMPILED_METHOD.matcher(line);
+            if (matcher.matches()) {
+                String method = normalize(matcher.group("name"));
+                if (!printMethods.contains(normalize(method))
+                        && testMethods.contains(method)) {
+                    System.out.println(outputAnalyzer.getOutput());
+                    throw new AssertionError("FAILED: wrong method "
+                            + "was printed: " + method + " LINE: " + line);
+                }
+            }
+        }
+    }
+
+    // Normalize given signature to conform regular expression used in tests
+    private String normalize(String method) {
+        return method.replaceAll("\\.", "/") // replace dots in a class string
+                .replaceFirst("::", ".")     // replace :: between class and method
+                .replace("&lt;", "<")
+                .replace("&gt;", ">");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/processors/QuietProcessor.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.processors;
+
+import compiler.compilercontrol.share.scenario.CompileCommand;
+import jdk.test.lib.OutputAnalyzer;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class QuietProcessor implements Consumer<OutputAnalyzer> {
+    private final List<CompileCommand> commands;
+
+    public QuietProcessor(List<CompileCommand> compileCommands) {
+        commands = compileCommands;
+    }
+
+    @Override
+    public void accept(OutputAnalyzer outputAnalyzer) {
+        for (CompileCommand command : commands) {
+            if (command.isValid()) {
+                outputAnalyzer.shouldNotContain("CompileCommand: "
+                        + command.command.name + " "
+                        + command.methodDescriptor.getCanonicalString());
+                outputAnalyzer.shouldNotContain("CompileCommand: An error "
+                        + "occurred during parsing");
+            } else {
+                outputAnalyzer.shouldMatch("(CompileCommand: )"
+                        + "(unrecognized command)|(Bad pattern)|"
+                        + "(An error occurred during parsing)");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/AbstractCommandBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * An abstract class that builds states by applying
+ * commands one after another
+ */
+public abstract class AbstractCommandBuilder
+        implements StateBuilder<CompileCommand> {
+    protected static final List<Pair<Executable, Callable<?>>> METHODS
+            = new PoolHelper().getAllMethods();
+    protected final List<CompileCommand> compileCommands = new ArrayList<>();
+
+    @Override
+    public void add(CompileCommand command) {
+        compileCommands.add(command);
+    }
+
+    @Override
+    public Map<Executable, State> getStates() {
+        Map<Executable, State> states = new HashMap<>();
+        for (CompileCommand compileCommand : compileCommands) {
+            if (compileCommand.isValid()) {
+                CompileCommand cc = new CompileCommand(compileCommand.command,
+                        compileCommand.methodDescriptor,
+                        /* CompileCommand option and file doesn't support
+                           compiler setting */
+                        null,
+                        compileCommand.type);
+                MethodDescriptor md = cc.methodDescriptor;
+                for (Pair<Executable, Callable<?>> pair: METHODS) {
+                    Executable exec = pair.first;
+                    State state = states.getOrDefault(exec, new State());
+                    MethodDescriptor execDesc = new MethodDescriptor(exec);
+                    // if executable matches regex then apply the state
+                    if (execDesc.getCanonicalString().matches(md.getRegexp())) {
+                        state.apply(cc);
+                    } else {
+                        if (cc.command == Command.COMPILEONLY) {
+                            state.setC1Compilable(false);
+                            state.setC2Compilable(false);
+                        }
+                    }
+                    states.put(exec, state);
+                }
+            }
+        }
+        return states;
+    }
+
+    @Override
+    public List<CompileCommand> getCompileCommands() {
+        return Collections.unmodifiableList(compileCommands);
+    }
+
+    @Override
+    public boolean isValid() {
+        // CompileCommand ignores invalid items
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/Command.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.processors.LogProcessor;
+import java.util.Arrays;
+
+/**
+ * Represents a CompileCommand command set
+ */
+public enum Command {
+    COMPILEONLY("compileonly", ".*", "-Xbatch"),
+    EXCLUDE("exclude", "", "-Xbatch"),
+    INLINE("inline", ".*"),
+    DONTINLINE("dontinline", ""),
+    LOG("log", "", "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:+LogCompilation", "-XX:LogFile=" + LogProcessor.LOG_FILE),
+    PRINT("print", ""),
+    QUIET("quiet", ""),
+    NONEXISTENT("nonexistent", ""); // wrong command for a negative case
+
+    /**
+     * Command name
+     */
+    public final String name;
+
+    /**
+     * Base regular expression
+     */
+    public final String regex;
+
+    /**
+     * Additional VM options for this command
+     */
+    public final String[] vmOpts;
+
+    private Command(String name, String regex, String... vmOptions) {
+        this.name = name;
+        this.regex = regex;
+        String[] wbOpts = new String[] { "-Xbootclasspath/a:.",
+                "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI" };
+        int length = (vmOptions != null) ? vmOptions.length : 0;
+        this.vmOpts = Arrays.copyOf(wbOpts, wbOpts.length + length);
+        if (vmOptions != null) {
+            System.arraycopy(vmOptions, 0, vmOpts, wbOpts.length, length);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandFileBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Creates CompileCommandFile from the given array of commands
+ */
+public class CommandFileBuilder extends AbstractCommandBuilder {
+    private final String fileName;
+
+    public CommandFileBuilder(String fileName) {
+        this.fileName = fileName;
+    }
+
+    @Override
+    public List<String> getOptions() {
+        // Create CommandFile
+        try (PrintWriter pw = new PrintWriter(fileName)) {
+            compileCommands.stream()
+                    .map(cc -> cc.command.name + " "
+                            + cc.methodDescriptor.getString())
+                    .forEach(pw::println);
+            if (pw.checkError()) {
+                throw new Error("TESTBUG: write error");
+            }
+        } catch (IOException e) {
+            throw new Error("TESTBUG: can't write a file", e);
+        }
+        List<String> opt = new ArrayList<>();
+        opt.add("-XX:CompileCommandFile=" + fileName);
+        return opt;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandGenerator.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import jdk.test.lib.Utils;
+
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Generates random commands
+ */
+public class CommandGenerator {
+    private static final int MAX_COMMANDS = Integer.getInteger(
+            "compiler.compilercontrol.share.scenario.CommandGenerator.commands",
+            100);
+    private static final Random RANDOM = Utils.getRandomInstance();
+
+    /**
+     * Generates random command
+     *
+     * @return command
+     */
+    public Command generateCommand() {
+        return Utils.getRandomElement(Command.values());
+    }
+
+    /**
+     * Generates random number of random command
+     *
+     * @return a list of random commands
+     */
+    public List<Command> generateCommands() {
+        int amount = 1 + RANDOM.nextInt(MAX_COMMANDS - 1);
+        return generateCommands(amount);
+    }
+
+    /**
+     * Generates specified amount of random command
+     *
+     * @param amount amount of commands to generate
+     * @return a list of random commands
+     */
+    public List<Command> generateCommands(int amount) {
+        return Stream.generate(this::generateCommand)
+                .limit(amount)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Generates random compile command {@link CompileCommand} with specified
+     * command and method descriptor
+     *
+     * @param command a command type
+     * @param md      a method descriptor
+     * @param type    a type of the command, or null to generate any
+     * @return the generated compile command
+     */
+    public CompileCommand generateCompileCommand(Command command,
+            MethodDescriptor md, Scenario.Type type) {
+        if (type == null) {
+            type = Utils.getRandomElement(Scenario.Type.values());
+        }
+        return type.createCompileCommand(command, md, generateCompiler());
+    }
+
+    /**
+     * Generates type of compiler that should be used for the command, or null
+     * if any or all compilers should be used
+     *
+     * @return Compiler value, or null
+     */
+    public Scenario.Compiler generateCompiler() {
+        Scenario.Compiler[] compilers = Scenario.Compiler.values();
+        int compiler = RANDOM.nextInt(compilers.length + 1) - 1;
+        return (compiler != -1) ? compilers[compiler] : null;
+    }
+
+    /**
+     * Generates random diagnostic command
+     * {@link Scenario.Type}
+     */
+    public Scenario.JcmdType generateJcmdType() {
+        return Utils.getRandomElement(Scenario.JcmdType.values());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CommandOptionsBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Creates VM options by adding CompileCommand prefix to commands
+ */
+public class CommandOptionsBuilder extends AbstractCommandBuilder {
+    @Override
+    public List<String> getOptions() {
+        return compileCommands.stream()
+                .map(cc -> "-XX:CompileCommand="
+                        + cc.command.name
+                        + MethodDescriptor.Separator.COMMA.symbol
+                        + cc.methodDescriptor.getString())
+                .collect(Collectors.toList());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/CompileCommand.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+/**
+ * Compile Command description interface
+ */
+public class CompileCommand {
+    public final Command command;
+    public final MethodDescriptor methodDescriptor;
+    public final Scenario.Compiler compiler;
+    public final Scenario.Type type;
+
+    public CompileCommand(Command command,
+                          MethodDescriptor methodDescriptor,
+                          Scenario.Compiler compiler,
+                          Scenario.Type type) {
+        this.command = command;
+        this.methodDescriptor = methodDescriptor;
+        this.compiler = compiler;
+        this.type = type;
+    }
+
+    /**
+     * Shows that this compile command is valid
+     *
+     * @return true if this is a valid command
+     */
+    public boolean isValid() {
+        if (command == Command.NONEXISTENT) {
+            return false;
+        }
+        return methodDescriptor.isValid();
+    }
+
+    /**
+     * Prints compile command to the system output
+     */
+    public void print() {
+        System.out.printf("%s (type: %s): %s (valid: %b)%n", command.name(),
+                type.name(), methodDescriptor.getString(), isValid());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.JSONFile;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import jdk.test.lib.Pair;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.concurrent.Callable;
+
+/**
+ * Directive file and state builder class
+ */
+public class DirectiveBuilder implements StateBuilder<CompileCommand> {
+    private static final List<Pair<Executable, Callable<?>>> METHODS
+            = new PoolHelper().getAllMethods();
+    private final Map<Executable, State> stateMap = new HashMap<>();
+    private final String fileName;
+    private Map<MethodDescriptor, List<CompileCommand>> matchBlocks
+            = new LinkedHashMap<>();
+    private List<String> inlineMatch = new ArrayList<>();
+    private boolean isFileValid = true;
+
+    public DirectiveBuilder(String fileName) {
+        this.fileName = fileName;
+    }
+
+    @Override
+    public List<String> getOptions() {
+        List<String> options = new ArrayList<>();
+        if (!matchBlocks.isEmpty()) {
+            // add option only if there are any directive available
+            options.add("-XX:CompilerDirectivesFile=" + fileName);
+        }
+        return options;
+    }
+
+    @Override
+    public List<CompileCommand> getCompileCommands() {
+        throw new Error("TESTBUG: isn't applicable for directives");
+    }
+
+    @Override
+    public boolean isValid() {
+        // Invalid directives file makes VM exit with error code
+        return isFileValid;
+    }
+
+    @Override
+    public Map<Executable, State> getStates() {
+        try (DirectiveWriter dirFile = new DirectiveWriter(fileName)) {
+            for (MethodDescriptor matchDescriptor : matchBlocks.keySet()) {
+                // Write match block with all options converted from commands
+                dirFile.match(matchDescriptor);
+                for (CompileCommand compileCommand :
+                        matchBlocks.get(matchDescriptor)) {
+                    isFileValid &= compileCommand.isValid();
+                    handleCommand(dirFile, compileCommand);
+                }
+                if ("Inlinee.caller".matches((matchDescriptor.getRegexp()))) {
+                    // Got a *.* match block, where inline would be written
+                    dirFile.inline(inlineMatch.toArray(
+                            new String[inlineMatch.size()]));
+                    inlineMatch.clear();
+                }
+                dirFile.end(); // ends match block
+            }
+
+            /*
+             * Write inline directive in the end to the latest match block
+             * if we didn't do this before
+             * Inlinee caller methods should match this block only
+             */
+            if (!inlineMatch.isEmpty()) {
+                Pair<Executable, Callable<?>> pair = METHODS.get(0);
+                MethodDescriptor md = MethodGenerator.anyMatchDescriptor(
+                        pair.first);
+                CompileCommand cc = new CompileCommand(Command.QUIET, md, null,
+                        Scenario.Type.DIRECTIVE);
+                List<CompileCommand> commands = new ArrayList<>();
+
+                // Add appropriate "*.*" match block
+                commands.add(cc);
+                matchBlocks.put(md, commands);
+                // Add match block for this descriptor with inlines
+                dirFile.match(md);
+                dirFile.inline(inlineMatch.toArray(
+                        new String[inlineMatch.size()]));
+                dirFile.end();
+            }
+            if (!matchBlocks.isEmpty()) {
+                // terminates file
+                dirFile.end();
+            }
+
+            // Build states for each method according to match blocks
+            for (Pair<Executable, Callable<?>> pair : METHODS) {
+                State state = getState(pair);
+                if (state != null) {
+                    stateMap.put(pair.first, state);
+                }
+            }
+        }
+        if (isFileValid) {
+            return stateMap;
+        } else {
+            // return empty map because invalid file doesn't change states
+            return new HashMap<>();
+        }
+    }
+
+    private State getState(Pair<Executable, Callable<?>> pair) {
+        State state = null;
+        MethodDescriptor execDesc = MethodGenerator.commandDescriptor(
+                pair.first);
+        boolean isMatchFound = false;
+
+        if (stateMap.containsKey(pair.first)) {
+            state = stateMap.get(pair.first);
+        }
+        for (MethodDescriptor matchDesc : matchBlocks.keySet()) {
+            if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) {
+                /*
+                 * if executable matches regex
+                 * then apply commands from this match to the state
+                 */
+                for (CompileCommand cc : matchBlocks.get(matchDesc)) {
+                    state = new State();
+                    if (!isMatchFound) {
+                        // this is a first found match, apply all commands
+                        state.apply(cc);
+                    } else {
+                        // apply only inline directives
+                        switch (cc.command) {
+                            case INLINE:
+                            case DONTINLINE:
+                                state.apply(cc);
+                                break;
+                        }
+                    }
+                }
+                isMatchFound = true;
+            }
+        }
+        return state;
+    }
+
+    private void handleCommand(DirectiveWriter dirFile, CompileCommand cmd) {
+        Command command = cmd.command;
+
+        switch (command) {
+            case COMPILEONLY:
+                dirFile.excludeCompile(cmd.compiler, false);
+                break;
+            case EXCLUDE:
+                dirFile.excludeCompile(cmd.compiler, true);
+                break;
+            case INLINE:
+            case DONTINLINE:
+                // Inline commands will be written later
+                break;
+            case LOG:
+                dirFile.option(DirectiveWriter.Option.LOG, true);
+                break;
+            case QUIET:
+                // there are no appropriate directive for this
+                break;
+            case PRINT:
+                dirFile.option(DirectiveWriter.Option.PRINT_ASSEMBLY, true);
+                break;
+            case NONEXISTENT:
+                dirFile.write(JSONFile.Element.PAIR, command.name);
+                dirFile.write(JSONFile.Element.OBJECT);
+                dirFile.write(JSONFile.Element.PAIR, command.name);
+                dirFile.write(JSONFile.Element.VALUE,
+                        cmd.methodDescriptor.getString());
+                dirFile.end(); // ends object
+                break;
+            default:
+                throw new Error("TESTBUG: wrong command: " + command);
+        }
+    }
+
+    @Override
+    public void add(CompileCommand compileCommand) {
+        MethodDescriptor methodDescriptor = compileCommand.methodDescriptor;
+
+        switch (compileCommand.command) {
+            case INLINE:
+                inlineMatch.add("+" + methodDescriptor.getString());
+                break;
+            case DONTINLINE:
+                inlineMatch.add("-" + methodDescriptor.getString());
+                break;
+        }
+        for (MethodDescriptor md: matchBlocks.keySet()) {
+            if (methodDescriptor.getCanonicalString().matches(md.getRegexp())) {
+                matchBlocks.get(md).add(compileCommand);
+            }
+        }
+        if (!matchBlocks.containsKey(compileCommand.methodDescriptor)) {
+            List<CompileCommand> commands = new ArrayList<>();
+            commands.add(compileCommand);
+            matchBlocks.put(compileCommand.methodDescriptor, commands);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveWriter.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.JSONFile;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+/**
+ * Simple directive file writer.
+ */
+public class DirectiveWriter implements AutoCloseable {
+    private final JSONFile jsonFile;
+
+    /**
+     * Builds directive file for the given name
+     *
+     * @param fileName name the file to be created
+     */
+    public DirectiveWriter(String fileName) {
+        jsonFile = new JSONFile(fileName);
+    }
+
+    /**
+     * Emits match block with a given methods
+     *
+     * @param methods methods used for the match
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter match(String... methods) {
+        if (jsonFile.getElement() == null) {
+            write(JSONFile.Element.ARRAY);
+        }
+        write(JSONFile.Element.OBJECT);
+        write(JSONFile.Element.PAIR, "match");
+        writeMethods(methods);
+        return this;
+    }
+
+    /**
+     * Emits match block with a given methods
+     *
+     * @param methodDescriptors method descriptors used for the match
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter match(MethodDescriptor... methodDescriptors) {
+        String[] methods = new String[methodDescriptors.length];
+        for (int i = 0; i < methodDescriptors.length; i++) {
+            methods[i] = methodDescriptors[i].getString();
+        }
+        match(methods);
+        return this;
+    }
+
+    /**
+     * Emits inline block with a given methods to be inlined or not.
+     * Each method should be prepended with + or - to show if it should be
+     * inlined or not.
+     *
+     * @param methods methods used for the inline
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter inline(String... methods) {
+        write(JSONFile.Element.PAIR, "inline");
+        writeMethods(methods);
+        return this;
+    }
+
+    private void writeMethods(String[] methods) {
+        if (methods.length == 0) {
+            throw new IllegalArgumentException("ERROR: empty methods array");
+        }
+        if (methods.length > 1) {
+            write(JSONFile.Element.ARRAY);
+            for (String method : methods) {
+                write(JSONFile.Element.VALUE, "\"" + method + "\"");
+            }
+            end(); // ends array
+        } else {
+            write(JSONFile.Element.VALUE, "\"" + methods[0] + "\"");
+        }
+    }
+
+    /**
+     * Emits compiler blocks that makes current match to be excluded or not
+     * from compilation with specified compiler
+     *
+     * @param compiler compiler to be excluded or null, for all
+     * @param exclude  shows if compiler should be disabled for this match
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter excludeCompile(Scenario.Compiler compiler,
+                                          boolean exclude) {
+        if (compiler != null) {
+            emitCompiler(compiler);
+            option(Option.EXCLUDE, exclude);
+            end();
+        } else {
+            for (Scenario.Compiler comp : Scenario.Compiler.values()) {
+                emitCompiler(comp);
+                option(Option.EXCLUDE, exclude);
+                end(); // end compiler block
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Emits compiler directive block
+     *
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter emitCompiler(Scenario.Compiler compiler) {
+        write(JSONFile.Element.PAIR, compiler.name);
+        write(JSONFile.Element.OBJECT);
+        return this;
+    }
+
+    @Override
+    public void close() {
+        jsonFile.close();
+    }
+
+    /**
+     * Ends current object element. It could be either a
+     * c1 or c2 block, or a whole match block
+     *
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter end() {
+        jsonFile.end();
+        return this;
+    }
+
+    public DirectiveWriter write(JSONFile.Element element, String... value) {
+        jsonFile.write(element, value);
+        return this;
+    }
+
+    /**
+     * Emits directive option with a given value
+     *
+     * @param option directive to be set
+     * @param value value of the directive
+     * @return this DirectiveWriter instance
+     */
+    public DirectiveWriter option(Option option, Object value) {
+        write(JSONFile.Element.PAIR, option.string);
+        write(JSONFile.Element.VALUE, String.valueOf(value));
+        return this;
+    }
+
+    /**
+     * Directive option list
+     */
+    public enum Option {
+        PRINT_ASSEMBLY("PrintAssembly"),
+        LOG("Log"),
+        EXCLUDE("Exclude");
+
+        public final String string;
+
+        private Option(String directive) {
+            this.string = directive;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/JcmdCommand.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+
+public class JcmdCommand extends CompileCommand {
+    public final Scenario.JcmdType jcmdType;
+
+    public JcmdCommand(Command command,
+                       MethodDescriptor methodDescriptor,
+                       Scenario.Compiler compiler,
+                       Scenario.Type type,
+                       Scenario.JcmdType jcmdType) {
+        super(command, methodDescriptor, compiler, type);
+        this.jcmdType = jcmdType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/JcmdStateBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import pool.PoolHelper;
+import jdk.test.lib.Pair;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
+    private static final List<Pair<Executable, Callable<?>>> METHODS
+            = new PoolHelper().getAllMethods();
+    private final Map<Executable, State> stateMap = new HashMap<>();
+    private final DirectiveBuilder directiveBuilder;
+    private Map<MethodDescriptor, List<CompileCommand>> matchBlocks
+            = new LinkedHashMap<>();
+    private List<JcmdCommand> commands = new ArrayList<>();
+    private boolean isFileValid = true;
+
+    public JcmdStateBuilder(String fileName) {
+        directiveBuilder = new DirectiveBuilder(fileName);
+    }
+
+    @Override
+    public void add(JcmdCommand compileCommand) {
+        commands.add(compileCommand);
+        switch (compileCommand.jcmdType) {
+            case ADD:
+                directiveBuilder.add(compileCommand);
+                addCommand(compileCommand);
+                break;
+            case PRINT:
+                // doesn't change the state
+                break;
+            case CLEAR:
+                matchBlocks.clear();
+                break;
+            case REMOVE:
+                removeDirective();
+                break;
+        }
+    }
+
+    private void addCommand(JcmdCommand compileCommand) {
+        isFileValid &= compileCommand.isValid();
+        for (MethodDescriptor md: matchBlocks.keySet()) {
+            if (compileCommand.methodDescriptor.getCanonicalString()
+                    .matches(md.getRegexp())) {
+                matchBlocks.get(md).add(compileCommand);
+            }
+        }
+        List<CompileCommand> commands = new ArrayList<>();
+        commands.add(compileCommand);
+        matchBlocks.put(compileCommand.methodDescriptor, commands);
+    }
+
+    private void removeDirective() {
+        Iterator<MethodDescriptor> iterator = matchBlocks.keySet().iterator();
+        if (iterator.hasNext()) {
+            MethodDescriptor md = iterator.next();
+            matchBlocks.remove(md);
+        }
+    }
+
+    @Override
+    public boolean isValid() {
+        // VM skips invalid directive file added via jcmd command
+        return true;
+    }
+
+    @Override
+    public Map<Executable, State> getStates() {
+        directiveBuilder.getStates();
+        // Build states for each method according to match blocks
+        for (Pair<Executable, Callable<?>> pair : METHODS) {
+            State state = getState(pair);
+            if (state != null) {
+                stateMap.put(pair.first, state);
+            }
+        }
+        if (isFileValid) {
+            return stateMap;
+        } else {
+            // return empty map because invalid file doesn't change states
+            return new HashMap<>();
+        }
+    }
+
+    private State getState(Pair<Executable, Callable<?>> pair) {
+        State state = null;
+        MethodDescriptor execDesc = MethodGenerator.commandDescriptor(
+                pair.first);
+        boolean isMatchFound = false;
+
+        if (stateMap.containsKey(pair.first)) {
+            state = stateMap.get(pair.first);
+        }
+        for (MethodDescriptor matchDesc : matchBlocks.keySet()) {
+            if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) {
+                /*
+                 * if executable matches regex
+                 * then apply commands from this match to the state
+                 */
+                for (CompileCommand cc : matchBlocks.get(matchDesc)) {
+                    state = new State();
+                    if (!isMatchFound) {
+                        // this is a first found match, apply all commands
+                        state.apply(cc);
+                    } else {
+                        // apply only inline directives
+                        switch (cc.command) {
+                            case INLINE:
+                            case DONTINLINE:
+                                state.apply(cc);
+                                break;
+                        }
+                    }
+                }
+                isMatchFound = true;
+            }
+        }
+        return state;
+    }
+
+    @Override
+    public List<String> getOptions() {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<JcmdCommand> getCompileCommands() {
+        return commands;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import compiler.compilercontrol.share.actions.BaseAction;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.processors.CommandProcessor;
+import compiler.compilercontrol.share.processors.LogProcessor;
+import compiler.compilercontrol.share.processors.PrintProcessor;
+import compiler.compilercontrol.share.processors.QuietProcessor;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Pair;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.dcmd.CommandExecutorException;
+import jdk.test.lib.dcmd.JcmdExecutor;
+import pool.PoolHelper;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.reflect.Executable;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+
+/**
+ * Test scenario
+ */
+public final class Scenario {
+    private final boolean isValid;
+    private final List<String> vmopts;
+    private final Map<Executable, State> states;
+    private final List<Consumer<OutputAnalyzer>> processors;
+    private final List<String> jcmdExecCommands;
+
+    private Scenario(boolean isValid,
+                     List<String> vmopts,
+                     Map<Executable, State> states,
+                     List<CompileCommand> compileCommands,
+                     List<JcmdCommand> jcmdCommands) {
+        this.isValid = isValid;
+        this.vmopts = vmopts;
+        this.states = states;
+        processors = new ArrayList<>();
+        processors.add(new LogProcessor(states));
+        processors.add(new PrintProcessor(states));
+        List<CompileCommand> nonQuieted = new ArrayList<>();
+        List<CompileCommand> quieted = new ArrayList<>();
+        boolean metQuiet = false;
+        for (CompileCommand cc : compileCommands) {
+            metQuiet |= cc.command == Command.QUIET;
+            if (metQuiet) {
+                quieted.add(cc);
+            } else {
+                nonQuieted.add(cc);
+            }
+        }
+        processors.add(new CommandProcessor(nonQuieted));
+        processors.add(new QuietProcessor(quieted));
+        jcmdExecCommands = new ArrayList<>();
+        boolean addCommandMet = false;
+        for (JcmdCommand cmd : jcmdCommands) {
+            switch (cmd.jcmdType) {
+                case ADD:
+                    if (!addCommandMet) {
+                        jcmdExecCommands.add(JcmdType.ADD.command);
+                    }
+                    addCommandMet = true;
+                    break;
+                default:
+                    jcmdExecCommands.add(cmd.jcmdType.command);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Executes scenario
+     */
+    public void execute() {
+        // Construct execution command with CompileCommand and class
+        List<String> argsList = new ArrayList<>();
+        // Add VM options
+        argsList.addAll(vmopts);
+        // Add class name that would be executed in a separate VM
+        String classCmd = BaseAction.class.getName();
+        argsList.add(classCmd);
+        OutputAnalyzer output;
+        try (ServerSocket serverSocket = new ServerSocket(0)) {
+            if (isValid) {
+                // Get port test VM will connect to
+                int port = serverSocket.getLocalPort();
+                if (port == -1) {
+                    throw new Error("Socket is not bound: " + port);
+                }
+                argsList.add(String.valueOf(port));
+                // Start separate thread to connect with test VM
+                new Thread(() -> connectTestVM(serverSocket)).start();
+            }
+            // Start test VM
+            output = ProcessTools.executeTestJvmAllArgs(
+                    argsList.toArray(new String[argsList.size()]));
+        } catch (Throwable thr) {
+            throw new Error("Execution failed", thr);
+        }
+        if (isValid) {
+            output.shouldHaveExitValue(0);
+            for (Consumer<OutputAnalyzer> processor : processors) {
+                processor.accept(output);
+            }
+        } else {
+            Asserts.assertNE(output.getExitValue(), 0, "VM should exit with "
+                    + "error for incorrect directives");
+            output.shouldContain("Parsing of compiler directives failed");
+        }
+    }
+
+    /*
+     * Performs connection with a test VM, sends method states and performs
+     * JCMD operations on a test VM.
+     */
+    private void connectTestVM(ServerSocket serverSocket) {
+        /*
+         * There are no way to prove that accept was invoked before we started
+         * test VM that connects to this serverSocket. Connection timeout is
+         * enough
+         */
+        try (
+                Socket socket = serverSocket.accept();
+                PrintWriter pw = new PrintWriter(socket.getOutputStream(),
+                        true);
+                BufferedReader in = new BufferedReader(new InputStreamReader(
+                        socket.getInputStream()))) {
+            // Get pid of the executed process
+            int pid = Integer.parseInt(in.readLine());
+            Asserts.assertNE(pid, 0, "Got incorrect pid");
+            executeJCMD(pid);
+            // serialize and send state map
+            for (Executable x : states.keySet()) {
+                pw.println("{");
+                pw.println(x.toGenericString());
+                pw.println(states.get(x).toString());
+                pw.println("}");
+            }
+        } catch (IOException e) {
+            throw new Error("Failed to write data", e);
+        }
+    }
+
+    // Executes all diagnostic commands
+    private void executeJCMD(int pid) {
+        for (String command : jcmdExecCommands) {
+            new JcmdExecutor() {
+                @Override
+                protected List<String> createCommandLine(String cmd)
+                        throws CommandExecutorException {
+                    return Arrays.asList(jcmdBinary, Integer.toString(pid),
+                            cmd);
+                }
+            }.execute(command);
+        }
+    }
+
+    /**
+     * Gets states of methods for this scenario
+     *
+     * @return pairs of executable and its state
+     */
+    public Map<Executable, State> getStates() {
+        return states;
+    }
+
+    public static enum Compiler {
+        C1("c1"),
+        C2("c2");
+
+        public final String name;
+
+        Compiler(String name) {
+            this.name = name;
+        }
+    }
+
+    /**
+     * Type of diagnostic (jcmd) command
+     */
+    public static enum JcmdType {
+        ADD("Compiler.directives_add " + Type.JCMD.fileName),
+        PRINT("Compiler.directives_print"),
+        CLEAR("Compiler.directives_clear"),
+        REMOVE("Compiler.directives_remove");
+
+        public final String command;
+        private JcmdType(String command) {
+            this.command = command;
+        }
+    }
+
+    /**
+     * Type of the compile command
+     */
+    public static enum Type {
+        OPTION(""),
+        FILE("command_file"),
+        DIRECTIVE("directives.json"),
+        JCMD("jcmd_directives.json") {
+            @Override
+            public CompileCommand createCompileCommand(Command command,
+                    MethodDescriptor md, Compiler compiler) {
+                return new JcmdCommand(command, md, compiler, this,
+                        JcmdType.ADD);
+            }
+        };
+
+        public final String fileName;
+
+        public CompileCommand createCompileCommand(Command command,
+                MethodDescriptor md, Compiler compiler) {
+            return new CompileCommand(command, md, compiler, this);
+        }
+
+        private Type(String fileName) {
+            this.fileName = fileName;
+        }
+    }
+
+    public static Builder getBuilder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private final Set<String> vmopts = new LinkedHashSet<>();
+        private final Map<Type, StateBuilder<CompileCommand>> builders
+                = new HashMap<>();
+        private final JcmdStateBuilder jcmdStateBuilder;
+
+        public Builder() {
+            builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName));
+            builders.put(Type.OPTION, new CommandOptionsBuilder());
+            builders.put(Type.DIRECTIVE, new DirectiveBuilder(
+                    Type.DIRECTIVE.fileName));
+            jcmdStateBuilder = new JcmdStateBuilder(Type.JCMD.fileName);
+        }
+
+        public void add(CompileCommand compileCommand) {
+            String[] vmOptions = compileCommand.command.vmOpts;
+            Collections.addAll(vmopts, vmOptions);
+            if (compileCommand.type == Type.JCMD) {
+                jcmdStateBuilder.add((JcmdCommand) compileCommand);
+            } else {
+                StateBuilder<CompileCommand> builder = builders.get(
+                        compileCommand.type);
+                if (builder == null) {
+                    throw new Error("TESTBUG: Missing builder for the type: "
+                            + compileCommand.type);
+                }
+                builder.add(compileCommand);
+            }
+        }
+
+        public Scenario build() {
+            boolean isValid = true;
+
+            // Get states from each of the state builders
+            Map<Executable, State> commandFileStates
+                    = builders.get(Type.FILE).getStates();
+            Map<Executable, State> commandOptionStates
+                    = builders.get(Type.OPTION).getStates();
+            Map<Executable, State> directiveFileStates
+                    = builders.get(Type.DIRECTIVE).getStates();
+
+            // get all jcmd commands
+            List<JcmdCommand> jcmdCommands = jcmdStateBuilder
+                    .getCompileCommands();
+            boolean isClearedState = false;
+            if (jcmdClearedState(jcmdCommands)) {
+                isClearedState = true;
+            }
+
+            // Merge states
+            List<Pair<Executable, Callable<?>>> methods = new PoolHelper()
+                    .getAllMethods();
+            Map<Executable, State> finalStates = new HashMap<>();
+            Map<Executable, State> jcmdStates = jcmdStateBuilder.getStates();
+            for (Pair<Executable, Callable<?>> pair : methods) {
+                Executable x = pair.first;
+                State commandOptionState = commandOptionStates.get(x);
+                State commandFileState = commandFileStates.get(x);
+                State st = State.merge(commandOptionState, commandFileState);
+                if (!isClearedState) {
+                    State directiveState = directiveFileStates.get(x);
+                    if (directiveState != null) {
+                        st = directiveState;
+                    }
+                }
+                State jcmdState = jcmdStates.get(x);
+                st = State.merge(st, jcmdState);
+
+                finalStates.put(x, st);
+            }
+
+            /*
+             * Create a list of commands from options and file
+             * to handle quiet command
+             */
+            List<CompileCommand> ccList = new ArrayList<>();
+            ccList.addAll(builders.get(Type.OPTION).getCompileCommands());
+            ccList.addAll(builders.get(Type.FILE).getCompileCommands());
+
+            // Get all VM options after we build all states and files
+            List<String> options = new ArrayList<>();
+            options.addAll(vmopts);
+            for (StateBuilder<?> builder : builders.values()) {
+                options.addAll(builder.getOptions());
+                isValid &= builder.isValid();
+            }
+            options.addAll(jcmdStateBuilder.getOptions());
+            return new Scenario(isValid, options, finalStates, ccList,
+                    jcmdCommands);
+        }
+
+        // shows if jcmd have passed a clear command
+        private boolean jcmdClearedState(List<JcmdCommand> jcmdCommands) {
+            for (JcmdCommand jcmdCommand : jcmdCommands) {
+                if (jcmdCommand.jcmdType == JcmdType.CLEAR) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/State.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import jdk.test.lib.Asserts;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Represents method compilation state
+ */
+public class State {
+    // Each of the two-elements array contains a state for each compiler
+    private Optional<Boolean>[] compile =
+            (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+    private Optional<Boolean>[] forceInline =
+            (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+    private Optional<Boolean>[] dontInline =
+            (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+    private Optional<Boolean> printAssembly = Optional.empty();
+    private Optional<Boolean> printInline = Optional.empty();
+    private Optional<Boolean> log = Optional.empty();
+
+    public State() {
+        Arrays.fill(compile, Optional.empty());
+        Arrays.fill(forceInline, Optional.empty());
+        Arrays.fill(dontInline, Optional.empty());
+    }
+
+    /**
+     * Creates state from the string
+     *
+     * @param strings array of strings that represent the state
+     * @return State instance
+     * @see #toString()
+     */
+    public static State fromString(String[] strings) {
+        Asserts.assertNotNull(strings, "Non null array is required");
+        Asserts.assertNE(strings.length, 0, "Non empty array is required");
+        State st = new State();
+        for (String string : strings) {
+            int i = string.indexOf(' ');
+            String command = string.substring(0, i);
+            String values = string.substring(i + 1); // skip space symbol
+            switch (command) {
+                case "compile" :
+                    parseArray(st.compile, values);
+                    break;
+                case "force_inline" :
+                    parseArray(st.forceInline, values);
+                    break;
+                case "dont_inline" :
+                    parseArray(st.dontInline, values);
+                    break;
+                case "log" :
+                    st.log = parseElement(values);
+                    break;
+                case "print_assembly" :
+                    st.printAssembly = parseElement(values);
+                    break;
+                case "print_inline" :
+                    st.printInline = parseElement(values);
+                    break;
+                default:
+                    throw new Error("TESTBUG: ");
+            }
+        }
+        return  st;
+    }
+
+    private static void parseArray(Optional<Boolean>[] array, String str) {
+        Asserts.assertNotNull(str);
+        int beginBrace = 0;
+        int endBrace = str.length() - 1;
+        if (str.charAt(beginBrace) != '[' || str.charAt(endBrace) != ']') {
+            throw new Error("TESTBUG: not an array type: " + str);
+        }
+        // Get all elements divided with comma as an array
+        String[] strValues = str.substring(beginBrace + 1, endBrace)
+                .split(", ");
+        Asserts.assertEQ(strValues.length, array.length, "Different amount of "
+                + "elements in the string");
+        for (int i = 0; i < strValues.length; i++) {
+            array[i] = parseElement(strValues[i]);
+        }
+    }
+
+    private static Optional<Boolean> parseElement(String str) {
+        Asserts.assertNotNull(str);
+        Asserts.assertTrue(str.startsWith(Optional.class.getSimpleName()),
+                "String is not of type Optional: " + str);
+        if ("Optional.empty".equals(str)) {
+            return Optional.empty();
+        }
+        int begin = str.indexOf('[');
+        Asserts.assertNE(begin, -1, "TEST BUG: Wrong Optional string");
+        int end = str.indexOf(']');
+        Asserts.assertEQ(end, str.length() - 1);
+        boolean b = Boolean.parseBoolean(str.substring(begin + 1, end));
+        return Optional.of(b);
+    }
+
+    /**
+     * Gets string representation of this state
+     */
+    @Override
+    public String toString() {
+        return "compile " + Arrays.toString(compile)
+                + "\nforce_inline " + Arrays.toString(forceInline)
+                + "\ndont_inline " + Arrays.toString(dontInline)
+                + "\nlog " + log
+                + "\nprint_assembly " + printAssembly
+                + "\nprint_inline " + printInline;
+    }
+
+    public boolean isC1Compilable() {
+        return compile[Scenario.Compiler.C1.ordinal()].orElse(true);
+    }
+
+    public boolean isC2Compilable() {
+        return compile[Scenario.Compiler.C2.ordinal()].orElse(true);
+    }
+
+    public boolean isCompilable() {
+        return isC1Compilable() && isC2Compilable();
+    }
+
+    public void setC1Compilable(boolean value) {
+        setCompilable(Scenario.Compiler.C1.ordinal(), value);
+    }
+
+    public void setC2Compilable(boolean value) {
+        setCompilable(Scenario.Compiler.C2.ordinal(), value);
+    }
+
+    public void setCompilable(Scenario.Compiler compiler, boolean value) {
+        if (compiler == null) {
+            setC1Compilable(value);
+            setC2Compilable(value);
+            return;
+        }
+        switch (compiler) {
+            case C1:
+                setC1Compilable(value);
+                break;
+            case C2:
+                setC2Compilable(value);
+                break;
+            default:
+                throw new Error("Unknown compiler");
+        }
+    }
+
+    private void setCompilable(int level, boolean value) {
+        check(level);
+        compile[level] = Optional.of(value);
+        if (!value) {
+            setDontInline(level);
+        }
+    }
+
+    public boolean isC1Inlinable() {
+        return ! dontInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+    }
+
+    public boolean isC2Inlinable() {
+        return ! dontInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+    }
+
+    public boolean isInlinable() {
+        return isC1Inlinable() && isC2Inlinable();
+    }
+
+    private void setDontInline(int level) {
+        check(level);
+        dontInline[level] = Optional.of(true);
+        forceInline[level] = Optional.of(false);
+    }
+
+    private void setForceInline(int level) {
+        check(level);
+        dontInline[level] = Optional.of(false);
+        forceInline[level] = Optional.of(true);
+    }
+
+    public boolean isC1ForceInline() {
+        return forceInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+    }
+
+    public boolean isC2ForceInline() {
+        return forceInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+    }
+
+    public boolean isForceInline() {
+        return isC1ForceInline() && isC2ForceInline();
+    }
+
+    public void setC1Inline(boolean value) {
+        if (value && isC1Compilable()) {
+            setForceInline(Scenario.Compiler.C1.ordinal());
+        } else {
+            setDontInline(Scenario.Compiler.C1.ordinal());
+        }
+    }
+
+    public void setC2Inline(boolean value) {
+        if (value && isC2Compilable()) {
+            setForceInline(Scenario.Compiler.C2.ordinal());
+        } else {
+            setDontInline(Scenario.Compiler.C1.ordinal());
+        }
+    }
+
+    public void setInline(Scenario.Compiler compiler, boolean value) {
+        if (compiler == null) {
+            setC1Inline(value);
+            setC2Inline(value);
+            return;
+        }
+        switch (compiler) {
+            case C1:
+                setC1Inline(value);
+                break;
+            case C2:
+                setC2Inline(value);
+                break;
+            default:
+                throw new Error("Unknown compiler");
+        }
+    }
+
+    public boolean isPrintAssembly() {
+        return printAssembly.orElse(false);
+    }
+
+    public void setPrintAssembly(boolean value) {
+        printAssembly = Optional.of(value);
+    }
+
+    public boolean isPrintInline() {
+        return printInline.orElse(false);
+    }
+
+    public void setPrintInline(boolean value) {
+        printInline = Optional.of(value);
+    }
+
+    public boolean isLog() {
+        return log.orElse(false);
+    }
+
+    public void setLog(boolean log) {
+        this.log = Optional.of(log);
+    }
+
+    private void check(int level) {
+        if (level < 0 || level > compile.length) {
+            throw new IllegalArgumentException("TESTBUG: Wrong level " + level);
+        }
+    }
+
+    /**
+     * Applies given command to the state.
+     *
+     * @param compileCommand command to be applied
+     */
+    public void apply(CompileCommand compileCommand) {
+        switch (compileCommand.command) {
+            case COMPILEONLY:
+                setCompilable(compileCommand.compiler, true);
+                break;
+            case EXCLUDE:
+                setCompilable(compileCommand.compiler, false);
+                break;
+            case INLINE:
+                setInline(compileCommand.compiler, true);
+                break;
+            case DONTINLINE:
+                setInline(compileCommand.compiler, false);
+                break;
+            case LOG:
+                setLog(true);
+                break;
+            case PRINT:
+                setPrintAssembly(true);
+                break;
+            case QUIET:
+            case NONEXISTENT:
+                // doesn't apply the state
+                break;
+            default:
+                throw new Error("Wrong command: " + compileCommand.command);
+        }
+    }
+
+    /**
+     * Merges two given states with different priority
+     *
+     * @param low  state with lower merge priority
+     * @param high state with higher merge priority
+     */
+    public static State merge(State low, State high) {
+        if (high == null) {
+            if (low == null) {
+                return new State();
+            }
+            return low;
+        }
+        if (low == null) {
+            return high;
+        }
+        State result = new State();
+        // Compilable
+        result.compile[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+                high.compile[Scenario.Compiler.C1.ordinal()],
+                low.compile[Scenario.Compiler.C1.ordinal()]);
+        result.compile[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+                high.compile[Scenario.Compiler.C2.ordinal()],
+                low.compile[Scenario.Compiler.C2.ordinal()]);
+        // Force inline
+        result.forceInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+                high.forceInline[Scenario.Compiler.C1.ordinal()],
+                low.forceInline[Scenario.Compiler.C1.ordinal()]);
+        result.forceInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+                high.forceInline[Scenario.Compiler.C2.ordinal()],
+                low.forceInline[Scenario.Compiler.C2.ordinal()]);
+        // Don't inline
+        result.dontInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+                high.dontInline[Scenario.Compiler.C1.ordinal()],
+                low.dontInline[Scenario.Compiler.C1.ordinal()]);
+        result.dontInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+                high.dontInline[Scenario.Compiler.C2.ordinal()],
+                low.dontInline[Scenario.Compiler.C2.ordinal()]);
+        // set PrintAssembly
+        result.printAssembly = mergeOptional(high.printAssembly,
+                low.printAssembly);
+        // set PrintInline
+        result.printInline = mergeOptional(high.printInline, low.printInline);
+        // set LogCompilation
+        result.log = mergeOptional(high.log, low.log);
+        return result;
+    }
+
+    private static <T> Optional<T> mergeOptional(Optional<T> high,
+                                                 Optional<T> low) {
+        T val = high.orElse(low.orElse(null));
+        return Optional.ofNullable(val);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/StateBuilder.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+
+public interface StateBuilder<T extends CompileCommand> {
+    /**
+     * Adds CompileCommand to builder
+     *
+     * @param command command used to build states
+     */
+    void add(T command);
+
+    /**
+     * Gets final states of methods
+     *
+     * @return a map with pairs of executables and their states
+     */
+    Map<Executable, State> getStates();
+
+    /**
+     * Gets list of VM options that will change states of methods
+     *
+     * @return a list of VM options
+     */
+    List<String> getOptions();
+
+    /**
+     * Gets list of passed commands {@link CompileCommand}
+     *
+     * @return a list of compile commands
+     */
+    List<T> getCompileCommands();
+
+    /**
+     * Shows that this state builder created a valid input for the test vm
+     *
+     * @return true if this is a valid input
+     */
+    boolean isValid();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8138651
+ * @library /testlibrary /../../test/lib
+ * @build IntrinsicDisabledTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   -XX:DisableIntrinsic=_putCharVolatile,_putInt
+ *                   -XX:DisableIntrinsic=_putIntVolatile
+ *                   -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
+ *                   -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
+ *                   IntrinsicDisabledTest
+ */
+
+import java.lang.reflect.Executable;
+import java.util.Objects;
+
+import sun.hotspot.WhiteBox;
+
+import jdk.test.lib.Platform;
+
+public class IntrinsicDisabledTest {
+
+    private static final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    /* Compilation level corresponding to C1. */
+    private static final int COMP_LEVEL_SIMPLE = 1;
+
+    /* Compilation level corresponding to C2. */
+    private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
+    /* Determine if tiered compilation is enabled. */
+    private static boolean isTieredCompilationEnabled() {
+        return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation")));
+    }
+
+    /* This test uses several methods from sun.misc.Unsafe. The method
+     * getMethod() returns a different Executable for each different
+     * combination of its input parameters. There are eight possible
+     * combinations, getMethod can return an Executable representing
+     * the following methods: putChar, putCharVolatile, getChar,
+     * getCharVolatile, putInt, putIntVolatile, getInt,
+     * getIntVolatile. These methods were selected because they can
+     * be intrinsified by both the C1 and the C2 compiler.
+     */
+    static Executable getMethod(boolean isChar, boolean isPut, boolean isVolatile) throws RuntimeException {
+        Executable aMethod;
+        String methodTypeName = isChar ? "Char" : "Int";
+
+        try {
+            Class aClass = Class.forName("sun.misc.Unsafe");
+            if (isPut) {
+                aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""),
+                                                   Object.class,
+                                                   long.class,
+                                                   isChar ? char.class : int.class);
+            } else {
+                aMethod = aClass.getDeclaredMethod("get" + methodTypeName + (isVolatile ? "Volatile" : ""),
+                                                   Object.class,
+                                                   long.class);
+            }
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException("Test bug, method is unavailable. " + e);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Test bug, class is unavailable. " + e);
+        }
+
+        return aMethod;
+    }
+
+    public static void test(int compLevel) {
+
+        Executable putChar = getMethod(true, /*isPut =*/ true, /*isVolatile = */ false);
+        Executable getChar = getMethod(true, /*isPut =*/ false, /*isVolatile = */ false);
+        Executable putCharVolatile = getMethod(true, /*isPut =*/ true, /*isVolatile = */ true);
+        Executable getCharVolatile = getMethod(true, /*isPut =*/ false, /*isVolatile = */ true);
+        Executable putInt = getMethod(false, /*isPut =*/ true, /*isVolatile = */ false);
+        Executable getInt = getMethod(false, /*isPut =*/ false, /*isVolatile = */ false);
+        Executable putIntVolatile = getMethod(false, /*isPut =*/ true, /*isVolatile = */ true);
+        Executable getIntVolatile = getMethod(false, /*isPut =*/ false, /*isVolatile = */ true);
+
+        /* Test if globally disabling intrinsics works. */
+        if (!wb.isIntrinsicAvailable(putChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
+                                       "] is not available globally although it should be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putCharVolatile, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
+                                       "] is available globally although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putInt, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
+                                       "] is available globally although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putIntVolatile, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
+                                       "] is available globally although it should not be.");
+        }
+
+        /* Test if disabling intrinsics on a per-method level
+         * works. The method for which intrinsics are
+         * disabled (the compilation context) is putChar. */
+        if (!wb.isIntrinsicAvailable(getChar, putChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getChar.toGenericString() +
+                                       "] is not available for intrinsification in [" +
+                                       putChar.toGenericString() + "] although it should be.");
+        }
+
+        if (wb.isIntrinsicAvailable(getCharVolatile, putChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       putChar.toGenericString() + "] although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(getInt, putChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       putChar.toGenericString() + "] although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(getIntVolatile, putCharVolatile, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       putCharVolatile.toGenericString() + "] although it should not be.");
+        }
+
+        /* Test if disabling intrinsics on a per-method level
+         * leaves those intrinsics enabled globally. */
+        if (!wb.isIntrinsicAvailable(getCharVolatile, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
+                                       "] is not available globally although it should be.");
+        }
+
+        if (!wb.isIntrinsicAvailable(getInt, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
+                                       "] is not available globally although it should be.");
+        }
+
+
+        if (!wb.isIntrinsicAvailable(getIntVolatile, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
+                                       "] is not available globally although it should be.");
+        }
+
+        /* Test if disabling an intrinsic globally disables it on a
+         * per-method level as well. */
+        if (!wb.isIntrinsicAvailable(putChar, getChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
+                                       "] is not available for intrinsification in [" +
+                                       getChar.toGenericString() + "] although it should be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putCharVolatile, getChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       getChar.toGenericString() + "] although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putInt, getChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       getChar.toGenericString() + "] although it should not be.");
+        }
+
+        if (wb.isIntrinsicAvailable(putIntVolatile, getChar, compLevel)) {
+            throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
+                                       "] is available for intrinsification in [" +
+                                       getChar.toGenericString() + "] although it should not be.");
+        }
+    }
+
+    public static void main(String args[]) {
+        if (Platform.isServer()) {
+            if (isTieredCompilationEnabled()) {
+                test(COMP_LEVEL_SIMPLE);
+            }
+            test(COMP_LEVEL_FULL_OPTIMIZATION);
+        } else {
+            test(COMP_LEVEL_SIMPLE);
+        }
+    }
+}
--- a/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -27,21 +27,36 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.Random;
 
+import sun.hotspot.WhiteBox;
+
+import jdk.test.lib.Platform;
+
 /**
  * @test
- * @bug 8130150
+ * @bug 8130150 8131779 8139907
+ * @summary Verify that the Montgomery multiply and square intrinsic works and correctly checks their arguments.
+ * @library /testlibrary /../../test/lib
  * @library /testlibrary
- * @summary Verify that the Montgomery multiply intrinsic works and correctly checks its arguments.
+ * @build MontgomeryMultiplyTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MontgomeryMultiplyTest
  */
 
 public class MontgomeryMultiplyTest {
 
+    private static final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    /* Compilation level corresponding to C2. */
+    private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
     static final MethodHandles.Lookup lookup = MethodHandles.lookup();
 
     static final MethodHandle montgomeryMultiplyHandle, montgomerySquareHandle;
@@ -76,6 +91,37 @@
         }
     }
 
+    /* Obtain executable for the intrinsics tested. Depending on the
+     * value of 'isMultiply', the executable corresponding to either
+     * implMontgomerMultiply or implMontgomerySqure is returned. */
+    static Executable getExecutable(boolean isMultiply) throws RuntimeException {
+        try {
+            Class aClass = Class.forName("java.math.BigInteger");
+            Method aMethod;
+            if (isMultiply) {
+                aMethod = aClass.getDeclaredMethod("implMontgomeryMultiply",
+                                                   int[].class,
+                                                   int[].class,
+                                                   int[].class,
+                                                   int.class,
+                                                   long.class,
+                                                   int[].class);
+            } else {
+                aMethod = aClass.getDeclaredMethod("implMontgomerySquare",
+                                                   int[].class,
+                                                   int[].class,
+                                                   int.class,
+                                                   long.class,
+                                                   int[].class);
+            }
+            return aMethod;
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException("Test bug, method is unavailable. " + e);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Test bug, class is unavailable. " + e);
+        }
+    }
+
     // Invoke either BigInteger.montgomeryMultiply or BigInteger.montgomerySquare.
     int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv,
                              int[] product) throws Throwable {
@@ -267,11 +313,15 @@
     }
 
     public static void main(String args[]) {
-        try {
-            new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
-            new MontgomeryMultiplyTest().testResultValues();
-        } catch (Throwable ex) {
-            throw new RuntimeException(ex);
+        if (Platform.isServer() &&
+            wb.isIntrinsicAvailable(getExecutable(true), COMP_LEVEL_FULL_OPTIMIZATION) &&
+            wb.isIntrinsicAvailable(getExecutable(false), COMP_LEVEL_FULL_OPTIMIZATION)) {
+            try {
+                new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
+                new MontgomeryMultiplyTest().testResultValues();
+            } catch (Throwable ex) {
+                throw new RuntimeException(ex);
+            }
         }
-     }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CompilerDirectivesDCMDTest
+ * @bug 8137167
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @run main ClassFileInstaller jdk.test.lib.Platform
+ * @run testng/othervm CompilerDirectivesDCMDTest
+ * @summary Test of diagnostic command
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+import jdk.test.lib.Platform;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+
+public class CompilerDirectivesDCMDTest {
+
+    public static String filename;
+
+    public void run(CommandExecutor executor) {
+
+        if (Platform.isServer()) {
+            filename = System.getProperty("test.src", ".") + File.separator + "control2.txt";
+        } else {
+            filename = System.getProperty("test.src", ".") + File.separator + "control1.txt";
+        }
+        testPrintCommand(executor);
+        testAddAndRemoveCommand(executor);
+    }
+
+    public static void testPrintCommand(CommandExecutor executor) {
+
+        // Get output from dcmd (diagnostic command)
+        OutputAnalyzer output = executor.execute("Compiler.directives_print");
+        int count = find(output, "Directive:");
+        if (count < 1) {
+            Assert.fail("Expected at least one directive - found " + count);
+        }
+    }
+
+    public static void testAddAndRemoveCommand(CommandExecutor executor) {
+        OutputAnalyzer output;
+        int count = 0;
+
+        // Start with clearing stack - expect only default directive left
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test that we can not remove the default directive
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test adding some directives from file
+        output = executor.execute("Compiler.directives_add " + filename);
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 3) {
+            Assert.fail("Expected three directives - found " + count);
+        }
+
+        // Test remove one directive
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 2) {
+            Assert.fail("Expected two directives - found " + count);
+        }
+
+        // Test adding directives again
+        output = executor.execute("Compiler.directives_add " + filename);
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 4) {
+            Assert.fail("Expected four directives - found " + count);
+        }
+
+        // Test clearing
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test clear when already cleared
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test remove one directive when empty
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directive - found " + count);
+        }
+    }
+
+    public static int find(OutputAnalyzer output, String find) {
+        int count = 0;
+
+        for (String line : output.asLines()) {
+            if (line.startsWith(find)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    @Test
+    public void jmx() {
+        run(new JMXExecutor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control1.txt	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,17 @@
+[
+  {    
+    match: "foo/bar.*",
+    PrintAssembly: false,
+    c1:  {
+      BreakAtExecute: false,
+    },
+    inline : [ "+javax/util.*", "-comx/sun.*"],
+    PrintAssembly: false,
+  },
+  {
+    match: ["baz.*","frob.*"],     
+    inline : [ "+java/util.*", "-com/sun.*" ],
+    PrintAssembly: false,
+    BreakAtExecute: false,    
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control2.txt	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,22 @@
+[
+  {    
+    match: "foo/bar.*",
+    PrintAssembly: false,
+    c1:  {
+      BreakAtExecute: false,
+    },
+    c2: {
+      inline : "+java/util.*",
+      BreakAtCompile: true      
+    },
+    inline : [ "+javax/util.*", "-comx/sun.*"],
+    PrintAssembly: false,
+    IGVPrintLevel: 2
+  },
+  {
+    match: ["baz.*","frob.*"],     
+    inline : [ "+java/util.*", "-com/sun.*" ],
+    PrintAssembly: false,
+    BreakAtExecute: false,    
+  }
+]
--- a/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java	Wed Jul 05 20:58:59 2017 +0200
@@ -39,7 +39,7 @@
   /**
    * Pumps stdout and stderr from running the process into a String.
    *
-   * @param processHandler ProcessHandler to run.
+   * @param processBuilder ProcessBuilder to run.
    * @return Output from process.
    * @throws IOException If an I/O error occurs.
    */
@@ -109,6 +109,17 @@
   }
 
   /**
+   * Gets the array of strings containing input arguments passed to the VM
+   *
+   * @return arguments
+   */
+  public static String[] getVmInputArgs() {
+    RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+    List<String> args = runtime.getInputArguments();
+    return args.toArray(new String[args.size()]);
+  }
+
+  /**
    * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
    *
    * @return String[] with platform specific arguments, empty if there are none
@@ -172,6 +183,26 @@
     return executeProcess(pb);
   }
 
+  /**
+   * Executes a test jvm process, waits for it to finish and returns the process output.
+   * The default jvm options from the test's run command, jtreg, test.vm.opts and test.java.opts, are added.
+   * The java from the test.jdk is used to execute the command.
+   *
+   * The command line will be like:
+   * {test.jdk}/bin/java {test.fromRun.opts} {test.vm.opts} {test.java.opts} cmds
+   *
+   * @param cmds User specifed arguments.
+   * @return The output from the process.
+   */
+  public static OutputAnalyzer executeTestJvmAllArgs(String... cmds) throws Throwable {
+    List<String> argsList = new ArrayList<>();
+    String[] testArgs = getVmInputArgs();
+    Collections.addAll(argsList, testArgs);
+    Collections.addAll(argsList, Utils.addTestJavaOpts(cmds));
+    ProcessBuilder pb = createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+    return executeProcess(pb);
+  }
+
     /**
      * Executes a process, waits for it to finish and returns the process output.
      * The process will have exited before this method returns.
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Wed Jul 05 20:58:59 2017 +0200
@@ -78,7 +78,7 @@
     /**
      * Returns the value of 'test.src' system property.
      */
-    public static final String TEST_SRC = System.getProperty("test.src", "").trim();
+    public static final String TEST_SRC = System.getProperty("test.src", ".").trim();
 
     private static Unsafe unsafe = null;
 
@@ -412,6 +412,23 @@
     }
 
     /**
+     * Returns random element of non empty array
+     *
+     * @param <T> a type of array element
+     * @param array array of elements
+     * @return random element of array
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static <T> T getRandomElement(T[] array)
+            throws IllegalArgumentException {
+        if (array == null || array.length == 0) {
+            throw new IllegalArgumentException("Empty or null array");
+        }
+        Random random = getRandomInstance();
+        return array[random.nextInt(array.length)];
+    }
+
+    /**
      * Wait for condition to be true
      *
      * @param condition, a condition to wait for
--- a/make/Images.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/Images.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -40,7 +40,7 @@
 MAIN_MODULES += java.se java.smartcardio jdk.httpserver jdk.sctp \
                jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \
                jdk.accessibility jdk.internal.le jdk.scripting.nashorn.shell \
-               jdk.vm.ci
+               jdk.vm.ci jdk.management
 
 # providers
 PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk.localedata \
@@ -435,7 +435,7 @@
 # directories will always trigger the rule for recompile since
 # _the.list_of_packages files are touched.
 ifneq ($(findstring images, $(MAKECMDGOALS)), )
-  $(JDK_IMAGE_DIR)/demo/%: $(SUPPORT_OUTPUTDIR)/demo/image/%
+  $(JDK_IMAGE_DIR)/demo/%: $(SUPPORT_OUTPUTDIR)/demos/image/%
 	if [ ! -d "$@" ]; then \
 	  $(ECHO) $(LOG_INFO) Copying '$(patsubst $(OUTPUT_ROOT)/%,%,$@)'; \
 	  $(MKDIR) -p $(@D); \
@@ -443,9 +443,9 @@
 	fi
 
   # Find all files including directories
-  JDK_DEMO_TARGETS := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demo/image), \
-      $(patsubst $(SUPPORT_OUTPUTDIR)/demo/image/%, $(JDK_IMAGE_DIR)/demo/%, \
-      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demo/image \
+  JDK_DEMO_TARGETS := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demos/image), \
+      $(patsubst $(SUPPORT_OUTPUTDIR)/demos/image/%, $(JDK_IMAGE_DIR)/demo/%, \
+      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \
           ! \( -name "_the*" -o -name "javac_state" \) )))
 
   JDK_TARGETS += $(JDK_DEMO_TARGETS)
--- a/make/JrtfsJar.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/JrtfsJar.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -27,7 +27,7 @@
 
 include $(SPEC)
 include MakeBase.gmk
-include JavaCompilation.gmk
+include JarArchive.gmk
 include TextFileProcessing.gmk
 
 # This rule will be depended on due to the MANIFEST line
@@ -39,9 +39,10 @@
       @@COMPANY_NAME@@ => $(COMPANY_NAME) , \
 ))
 
-$(eval $(call SetupArchive,JRTFS_JAR, , \
+$(eval $(call SetupJarArchive, JRTFS_JAR, \
     SRCS := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \
     JAR := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar, \
-    MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf))
+    MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+))
 
 all: $(JRTFS_JAR)
--- a/make/Main.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/Main.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -452,6 +452,8 @@
 
   test-make: clean-test-make
 
+  build-test-lib: java
+
   build-test-hotspot-jtreg-native: buildtools-jdk
 
   build-test-jdk-jtreg-native: buildtools-jdk
@@ -558,6 +560,8 @@
 CLEAN_DIRS += hotspot jdk bootcycle-build test buildtools support \
     images make-support test-make bundles
 CLEAN_DIR_TARGETS := $(addprefix clean-, $(CLEAN_DIRS))
+CLEAN_SUPPORT_DIRS += demos
+CLEAN_SUPPORT_DIR_TARGETS := $(addprefix clean-, $(CLEAN_SUPPORT_DIRS))
 CLEAN_TESTS += hotspot-jtreg-native jdk-jtreg-native lib
 CLEAN_TEST_TARGETS += $(addprefix clean-test-, $(CLEAN_TESTS))
 CLEAN_PHASES := gensrc java native include docs
@@ -575,6 +579,9 @@
 $(CLEAN_DIR_TARGETS):
 	$(call CleanDir,$(patsubst clean-%, %, $@))
 
+$(CLEAN_SUPPORT_DIR_TARGETS):
+	$(call CleanSupportDir,$(patsubst clean-%, %, $@))
+
 $(CLEAN_TEST_TARGETS):
 	$(call CleanTest,$(patsubst clean-test-%, %, $@))
 
@@ -608,8 +615,9 @@
 	)
 	$(ECHO) Cleaned everything, you will have to re-run configure.
 
-ALL_TARGETS += clean dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_TEST_TARGETS) \
-    $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) $(CLEAN_MODULE_PHASE_TARGETS)
+ALL_TARGETS += clean dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_SUPPORT_DIR_TARGETS) \
+    $(CLEAN_TEST_TARGETS) $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) \
+    $(CLEAN_MODULE_PHASE_TARGETS)
 
 ################################################################################
 # Declare *-only targets for each normal target
--- a/make/MainSupport.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/MainSupport.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -46,6 +46,13 @@
 	@$(PRINTF) " done\n"
 endef
 
+define CleanSupportDir
+	@$(PRINTF) "Cleaning $(strip $1) build artifacts ..."
+	@$(PRINTF) "\n" $(LOG_DEBUG)
+	$(RM) -r $(SUPPORT_OUTPUTDIR)/$(strip $1)
+	@$(PRINTF) " done\n"
+endef
+
 define CleanTest
 	@$(PRINTF) "Cleaning test $(strip $1) ..."
 	@$(PRINTF) "\n" $(LOG_DEBUG)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/common/JarArchive.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -0,0 +1,276 @@
+#
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+ifndef _JAR_ARCHIVE_GMK
+_JAR_ARCHIVE_GMK := 1
+
+ifeq (,$(_MAKEBASE_GMK))
+  $(error You must include MakeBase.gmk prior to including JarArchive.gmk)
+endif
+
+FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST
+
+# Setup make rules for creating a jar archive.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+#   DEPENDENCIES:=List of dependencies for the jar target. If left empty,
+#       dependencies are calculated automatically from the source files found.
+#       For this to work, the source files must exist when the makefile is
+#       parsed.
+#   SRCS:=List of directories in where to find files to add to archive
+#   SUFFIXES:=File suffixes to include in jar
+#   INCLUDES:=List of directories/packages in SRCS that should be included
+#   EXCLUDES:=List of directories/packages in SRCS that should be excluded
+#   EXCLUDE_FILES:=List of files in SRCS that should be excluded
+#   EXTRA_FILES:=List of files in SRCS that should be included regardless of suffix match.
+#   JAR:=Jar file to create
+#   MANIFEST:=Optional manifest file template.
+#   JARMAIN:=Optional main class to add to manifest
+#   JARINDEX:=true means generate the index in the jar file.
+#   SKIP_METAINF:=Set to prevent contents of an META-INF directory to be automatically
+#       added to the archive.
+#   EXTRA_MANIFEST_ATTR:=Extra attribute to add to manifest.
+#   CHECK_COMPRESS_JAR Check the COMPRESS_JAR variable
+SetupJarArchive = $(NamedParamsMacroTemplate)
+define SetupJarArchiveBody
+
+  $1_JARMAIN:=$(strip $$($1_JARMAIN))
+  $1_JARNAME:=$$(notdir $$($1_JAR))
+  $1_MANIFEST_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_manifest
+  $1_DELETESS_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletess
+  $1_DELETES_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletes
+  $1_BIN:=$$(dir $$($1_JAR))
+
+  ifeq (,$$($1_SUFFIXES))
+    # No suffix was set, default to classes.
+    $1_SUFFIXES:=.class
+  endif
+  # Convert suffixes to a find expression
+  $1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
+  # On windows, a lot of includes/excludes risk making the command line too long, so
+  # writing the grep patterns to files.
+  # Grep returns 1 if nothing is matched. Do not fail the build for this.
+  ifneq (,$$($1_INCLUDES))
+    $1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
+        $$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
+    # If there are a lot of include patterns, output to file to shorten command lines
+    ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
+      $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
+          || test "$$$$?" = "1" )
+    else
+      $1_GREP_INCLUDE_OUTPUT = \
+          $$(eval $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS, \
+              $$($1_BIN)/_the.$$($1_JARNAME)_include))
+      $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
+          || test "$$$$?" = "1" )
+    endif
+  endif
+  ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
+    $1_GREP_EXCLUDE_PATTERNS:=$$(call EscapeDollar, \
+        $$(foreach src,$$($1_SRCS),$$(addprefix $$(src)/, \
+        $$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
+    # If there are a lot of include patterns, output to file to shorten command lines
+    ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
+      $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
+          || test "$$$$?" = "1" )
+    else
+      $1_GREP_EXCLUDE_OUTPUT = \
+          $$(eval $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS, \
+              $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
+      $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
+          || test "$$$$?" = "1" )
+    endif
+  endif
+
+  # Check if this jar needs to have its index generated.
+  ifneq (,$$($1_JARINDEX))
+    $1_JARINDEX = (cd $$(dir $$@) && $(JAR) -i $$(notdir $$@))
+  else
+    $1_JARINDEX = true
+  endif
+  # When this macro is run in the same makefile as the java compilation, dependencies are
+  # transfered in make variables. When the macro is run in a different makefile than the
+  # java compilation, the dependencies need to be found in the filesystem.
+  $1_ORIG_DEPS := $$($1_DEPENDENCIES)
+  ifeq ($$($1_DEPENDENCIES), )
+    # Add all source roots to the find cache since we are likely going to run find
+    # on these more than once. The cache will only be updated if necessary.
+    $$(eval $$(call FillCacheFind, $$($1_FIND_LIST)))
+    $1_DEPENDENCIES:=$$(filter $$(addprefix %,$$($1_SUFFIXES)), \
+        $$(call CacheFind,$$($1_SRCS)))
+    ifneq (,$$($1_GREP_INCLUDE_PATTERNS))
+      $1_DEPENDENCIES:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
+    endif
+    ifneq (,$$($1_GREP_EXCLUDE_PATTERNS))
+      $1_DEPENDENCIES:=$$(filter-out $$(addsuffix %,$$($1_GREP_EXCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
+    endif
+    # Look for EXTRA_FILES in all SRCS dirs and as absolute paths.
+    $1_DEPENDENCIES+=$$(wildcard $$(foreach src, $$($1_SRCS), \
+        $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES))
+    ifeq (,$$($1_SKIP_METAINF))
+      $1_DEPENDENCIES+=$$(call CacheFind,$$(wildcard $$(addsuffix /META-INF,$$($1_SRCS))))
+    endif
+  endif
+  # The dependency list should never be empty
+  ifeq ($$(strip $$($1_DEPENDENCIES)), )
+    $$(warning No dependencies found for $1)
+  endif
+
+  # Utility macros, to make the shell script receipt somewhat easier to decipher.
+
+  # Capture extra files is the same for both CAPTURE_CONTENTS and SCAPTURE_CONTENTS so
+  # only define it once to avoid duplication.
+  # The list of extra files might be long, so need to use ListPathsSafely to print
+  # them out to a separte file. Then process the contents of that file to rewrite
+  # into -C <dir> <file> lines.
+  # The EXTRA_FILES_RESOLVED varible must be set in the macro so that it's evaluated
+  # in the recipe when the files are guaranteed to exist.
+  $1_CAPTURE_EXTRA_FILES=\
+      $$(eval $1_EXTRA_FILES_RESOLVED:=$$(call DoubleDollar, \
+          $$(wildcard $$(foreach src, $$($1_SRCS), \
+          $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES)))) \
+      $$(if $$($1_EXTRA_FILES_RESOLVED), \
+        $$(eval $$(call ListPathsSafely,$1_EXTRA_FILES_RESOLVED, \
+            $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra)) \
+        $(SED) $$(foreach src,$$($1_SRCS), -e 's|$$(src)/|-C $$(src) |g') \
+            $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra \
+            >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE))
+
+  # The capture contents macro finds all files (matching the patterns, typically
+  # .class and .prp) that are newer than the jar-file, ie the new content to be put into the jar.
+  # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
+  $1_CAPTURE_CONTENTS=\
+      $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
+      $$(foreach src,$$($1_SRCS), \
+        $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) -a -newer $$@ $$($1_GREP_INCLUDES) \
+          $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
+        >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
+      $$($1_CAPTURE_EXTRA_FILES)
+
+  # The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
+  # Find returns non zero if the META-INF dir does not exist, ignore this.
+  ifeq (,$$($1_SKIP_METAINF))
+    $1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
+        ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
+            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+        $$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
+  endif
+  # The capture deletes macro finds all deleted files and concatenates them. The resulting file
+  # tells us what to remove from the jar-file.
+  $1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ \
+      -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
+  # The update contents macro updates the jar file with the previously capture contents.
+  # Use 'wc -w' to see if the contents file is empty.
+  $1_UPDATE_CONTENTS=\
+      if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
+        $(ECHO) "  updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
+        $(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
+      fi $$(NEWLINE)
+  # The s-variants of the above macros are used when the jar is created from scratch.
+  # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
+  $1_SCAPTURE_CONTENTS=\
+      $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
+      $$(foreach src,$$($1_SRCS), \
+        $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) $$($1_GREP_INCLUDES) \
+            $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
+            >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
+      $$($1_CAPTURE_EXTRA_FILES)
+
+  # Find returns non zero if the META-INF dir does not exist, ignore this.
+  ifeq (,$$($1_SKIP_METAINF))
+    $1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
+        ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
+            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+        $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
+  endif
+  $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
+
+  # Use a slightly shorter name for logging, but with enough path to identify this jar.
+  $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_JAR))
+
+  ifneq (,$$($1_CHECK_COMPRESS_JAR))
+    $1_JAR_CREATE_OPTIONS := c0fm
+    $1_JAR_UPDATE_OPTIONS := u0f
+    ifeq ($(COMPRESS_JARS), true)
+      $1_JAR_CREATE_OPTIONS := cfm
+      $1_JAR_UPDATE_OPTIONS := uf
+    endif
+  else
+    $1_JAR_CREATE_OPTIONS := cfm
+    $1_JAR_UPDATE_OPTIONS := uf
+  endif
+
+  # Include all variables of significance in the vardeps file
+  $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
+      $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
+      $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
+  $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
+
+  # Here is the rule that creates/updates the jar file.
+  $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
+	$(MKDIR) -p $$($1_BIN)
+	$$($1_GREP_INCLUDE_OUTPUT)
+	$$($1_GREP_EXCLUDE_OUTPUT)
+        # If the vardeps file is part of the newer prereq list, it means that
+        # either the jar file does not exist, or we need to recreate it from
+        # from scratch anyway since a simple update will not catch all the
+        # potential changes.
+	$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
+	  $$(if $$($1_MANIFEST), \
+	    $(SED) -e '$(DOLLAR)$(DOLLAR)a\' $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
+	  , \
+	    $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $$(if $$($1_JARMAIN), \
+	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+	  $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+	  $$($1_SCAPTURE_CONTENTS) \
+	  $$($1_SCAPTURE_METAINF) \
+	  $$($1_SUPDATE_CONTENTS) \
+	  $$($1_JARINDEX) && true \
+	, \
+	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+	  $$($1_CAPTURE_CONTENTS) \
+	  $$($1_CAPTURE_METAINF) \
+	  $(RM) $$($1_DELETES_FILE) $$(NEWLINE) \
+	  $$($1_CAPTURE_DELETES) \
+	  $(CAT) $$($1_DELETES_FILE) > $$($1_DELETESS_FILE) $$(NEWLINE) \
+	  if [ -s $$($1_DELETESS_FILE) ]; then \
+	    $(ECHO) "  deleting" `$(WC) -l $$($1_DELETESS_FILE) | $(AWK) '{ print $$$$1 }'` files && \
+	    $(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
+	  fi $$(NEWLINE) \
+	  $$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
+	  $$($1_JARINDEX) && true )
+
+  # Add jar to target list
+  $1 += $$($1_JAR)
+endef
+
+endif # _JAR_ARCHIVE_GMK
--- a/make/common/JavaCompilation.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/common/JavaCompilation.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -23,14 +23,6 @@
 # questions.
 #
 
-# This makefile is much simpler now that it can use the smart javac wrapper
-# for dependency tracking between java packages and incremental compiles.
-# It could be even more simple if we added support for incremental jar updates
-# directly from the smart javac wrapper.
-
-# Cleaning/copying properties here is not a good solution. The properties
-# should be cleaned/copied by a annotation processor in sjavac.
-
 # When you read this source. Remember that $(sort ...) has the side effect
 # of removing duplicates. It is actually this side effect that is
 # desired whenever sort is used below!
@@ -42,11 +34,11 @@
   $(error You must include MakeBase.gmk prior to including JavaCompilation.gmk)
 endif
 
-# Java compilation needs SetupZipArchive if we're generating a source zip.
+# Java compilation needs SetupJarArchive and/or SetupZipArchive, if we're
+# generating a jar file or a source zip.
+include JarArchive.gmk
 include ZipArchive.gmk
 
-FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST
-
 # Setup make rules for defining a Java compiler, which is needed to compile
 # Java code. This rule generates no output.
 #
@@ -72,248 +64,6 @@
   endif
 endef
 
-# Setup make rules for creating a jar archive.
-#
-# Parameter 1 is the name of the rule. This name is used as variable prefix,
-# and the targets generated are listed in a variable by that name.
-#
-# Remaining parameters are named arguments. These include:
-#   DEPENDENCIES:=List of dependencies for the jar target. If left empty,
-#       dependencies are calculated automatically from the source files found.
-#       For this to work, the source files must exist when the makefile is
-#       parsed.
-#   SRCS:=List of directories in where to find files to add to archive
-#   SUFFIXES:=File suffixes to include in jar
-#   INCLUDES:=List of directories/packages in SRCS that should be included
-#   EXCLUDES:=List of directories/packages in SRCS that should be excluded
-#   EXCLUDE_FILES:=List of files in SRCS that should be excluded
-#   EXTRA_FILES:=List of files in SRCS that should be included regardless of suffix match.
-#   JAR:=Jar file to create
-#   MANIFEST:=Optional manifest file template.
-#   JARMAIN:=Optional main class to add to manifest
-#   JARINDEX:=true means generate the index in the jar file.
-#   SKIP_METAINF:=Set to prevent contents of an META-INF directory to be automatically
-#       added to the archive.
-#   EXTRA_MANIFEST_ATTR:=Extra attribute to add to manifest.
-#   CHECK_COMPRESS_JAR Check the COMPRESS_JAR variable
-SetupArchive = $(NamedParamsMacroTemplate)
-define SetupArchiveBody
-
-  $1_JARMAIN:=$(strip $$($1_JARMAIN))
-  $1_JARNAME:=$$(notdir $$($1_JAR))
-  $1_MANIFEST_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_manifest
-  $1_DELETESS_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletess
-  $1_DELETES_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletes
-  $1_BIN:=$$(dir $$($1_JAR))
-
-  ifeq (,$$($1_SUFFIXES))
-    # No suffix was set, default to classes.
-    $1_SUFFIXES:=.class
-  endif
-  # Convert suffixes to a find expression
-  $1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
-  # On windows, a lot of includes/excludes risk making the command line too long, so
-  # writing the grep patterns to files.
-  # Grep returns 1 if nothing is matched. Do not fail the build for this.
-  ifneq (,$$($1_INCLUDES))
-    $1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
-        $$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
-    # If there are a lot of include patterns, output to file to shorten command lines
-    ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
-      $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
-          || test "$$$$?" = "1" )
-    else
-      $1_GREP_INCLUDE_OUTPUT = \
-          $$(eval $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS, \
-              $$($1_BIN)/_the.$$($1_JARNAME)_include))
-      $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
-          || test "$$$$?" = "1" )
-    endif
-  endif
-  ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
-    $1_GREP_EXCLUDE_PATTERNS:=$$(call EscapeDollar, \
-        $$(foreach src,$$($1_SRCS),$$(addprefix $$(src)/, \
-        $$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
-    # If there are a lot of include patterns, output to file to shorten command lines
-    ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
-      $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
-          || test "$$$$?" = "1" )
-    else
-      $1_GREP_EXCLUDE_OUTPUT = \
-          $$(eval $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS, \
-              $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
-      $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
-          || test "$$$$?" = "1" )
-    endif
-  endif
-
-  # Check if this jar needs to have its index generated.
-  ifneq (,$$($1_JARINDEX))
-    $1_JARINDEX = (cd $$(dir $$@) && $(JAR) -i $$(notdir $$@))
-  else
-    $1_JARINDEX = true
-  endif
-  # When this macro is run in the same makefile as the java compilation, dependencies are
-  # transfered in make variables. When the macro is run in a different makefile than the
-  # java compilation, the dependencies need to be found in the filesystem.
-  $1_ORIG_DEPS := $$($1_DEPENDENCIES)
-  ifeq ($$($1_DEPENDENCIES), )
-    # Add all source roots to the find cache since we are likely going to run find
-    # on these more than once. The cache will only be updated if necessary.
-    $$(eval $$(call FillCacheFind, $$($1_FIND_LIST)))
-    $1_DEPENDENCIES:=$$(filter $$(addprefix %,$$($1_SUFFIXES)), \
-        $$(call CacheFind,$$($1_SRCS)))
-    ifneq (,$$($1_GREP_INCLUDE_PATTERNS))
-      $1_DEPENDENCIES:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
-    endif
-    ifneq (,$$($1_GREP_EXCLUDE_PATTERNS))
-      $1_DEPENDENCIES:=$$(filter-out $$(addsuffix %,$$($1_GREP_EXCLUDE_PATTERNS)),$$($1_DEPENDENCIES))
-    endif
-    # Look for EXTRA_FILES in all SRCS dirs and as absolute paths.
-    $1_DEPENDENCIES+=$$(wildcard $$(foreach src, $$($1_SRCS), \
-        $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES))
-    ifeq (,$$($1_SKIP_METAINF))
-      $1_DEPENDENCIES+=$$(call CacheFind,$$(wildcard $$(addsuffix /META-INF,$$($1_SRCS))))
-    endif
-  endif
-  # The dependency list should never be empty
-  ifeq ($$(strip $$($1_DEPENDENCIES)), )
-    $$(warning No dependencies found for $1)
-  endif
-
-  # Utility macros, to make the shell script receipt somewhat easier to decipher.
-
-  # Capture extra files is the same for both CAPTURE_CONTENTS and SCAPTURE_CONTENTS so
-  # only define it once to avoid duplication.
-  # The list of extra files might be long, so need to use ListPathsSafely to print
-  # them out to a separte file. Then process the contents of that file to rewrite
-  # into -C <dir> <file> lines.
-  # The EXTRA_FILES_RESOLVED varible must be set in the macro so that it's evaluated
-  # in the recipe when the files are guaranteed to exist.
-  $1_CAPTURE_EXTRA_FILES=\
-      $$(eval $1_EXTRA_FILES_RESOLVED:=$$(call DoubleDollar, \
-          $$(wildcard $$(foreach src, $$($1_SRCS), \
-          $$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES)))) \
-      $$(if $$($1_EXTRA_FILES_RESOLVED), \
-        $$(eval $$(call ListPathsSafely,$1_EXTRA_FILES_RESOLVED, \
-            $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra)) \
-        $(SED) $$(foreach src,$$($1_SRCS), -e 's|$$(src)/|-C $$(src) |g') \
-            $$($1_BIN)/_the.$$($1_JARNAME)_contents.extra \
-            >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE))
-
-  # The capture contents macro finds all files (matching the patterns, typically
-  # .class and .prp) that are newer than the jar-file, ie the new content to be put into the jar.
-  # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
-  $1_CAPTURE_CONTENTS=\
-      $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
-      $$(foreach src,$$($1_SRCS), \
-        $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) -a -newer $$@ $$($1_GREP_INCLUDES) \
-          $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
-        >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
-      $$($1_CAPTURE_EXTRA_FILES)
-
-  # The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
-  # Find returns non zero if the META-INF dir does not exist, ignore this.
-  ifeq (,$$($1_SKIP_METAINF))
-    $1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
-        ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
-            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
-        $$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
-  endif
-  # The capture deletes macro finds all deleted files and concatenates them. The resulting file
-  # tells us what to remove from the jar-file.
-  $1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ \
-      -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
-  # The update contents macro updates the jar file with the previously capture contents.
-  # Use 'wc -w' to see if the contents file is empty.
-  $1_UPDATE_CONTENTS=\
-      if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
-        $(ECHO) "  updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
-        $(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
-      fi $$(NEWLINE)
-  # The s-variants of the above macros are used when the jar is created from scratch.
-  # NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
-  $1_SCAPTURE_CONTENTS=\
-      $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
-      $$(foreach src,$$($1_SRCS), \
-        $(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) $$($1_GREP_INCLUDES) \
-            $$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
-            >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
-      $$($1_CAPTURE_EXTRA_FILES)
-
-  # Find returns non zero if the META-INF dir does not exist, ignore this.
-  ifeq (,$$($1_SKIP_METAINF))
-    $1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
-        ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
-            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
-        $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
-  endif
-  $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
-
-  # Use a slightly shorter name for logging, but with enough path to identify this jar.
-  $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_JAR))
-
-  ifneq (,$$($1_CHECK_COMPRESS_JAR))
-    $1_JAR_CREATE_OPTIONS := c0fm
-    $1_JAR_UPDATE_OPTIONS := u0f
-    ifeq ($(COMPRESS_JARS), true)
-      $1_JAR_CREATE_OPTIONS := cfm
-      $1_JAR_UPDATE_OPTIONS := uf
-    endif
-  else
-    $1_JAR_CREATE_OPTIONS := cfm
-    $1_JAR_UPDATE_OPTIONS := uf
-  endif
-
-  # Include all variables of significance in the vardeps file
-  $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
-      $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
-      $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
-  $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
-
-  # Here is the rule that creates/updates the jar file.
-  $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
-	$(MKDIR) -p $$($1_BIN)
-	$$($1_GREP_INCLUDE_OUTPUT)
-	$$($1_GREP_EXCLUDE_OUTPUT)
-        # If the vardeps file is part of the newer prereq list, it means that
-        # either the jar file does not exist, or we need to recreate it from
-        # from scratch anyway since a simple update will not catch all the
-        # potential changes.
-	$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
-	  $$(if $$($1_MANIFEST), \
-	    $(SED) -e '$(DOLLAR)$(DOLLAR)a\' $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
-	  , \
-	    $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
-	  $$(if $$($1_JARMAIN), \
-	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
-	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
-	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
-	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
-	  $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
-	  $$($1_SCAPTURE_CONTENTS) \
-	  $$($1_SCAPTURE_METAINF) \
-	  $$($1_SUPDATE_CONTENTS) \
-	  $$($1_JARINDEX) && true \
-	, \
-	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
-	  $$($1_CAPTURE_CONTENTS) \
-	  $$($1_CAPTURE_METAINF) \
-	  $(RM) $$($1_DELETES_FILE) $$(NEWLINE) \
-	  $$($1_CAPTURE_DELETES) \
-	  $(CAT) $$($1_DELETES_FILE) > $$($1_DELETESS_FILE) $$(NEWLINE) \
-	  if [ -s $$($1_DELETESS_FILE) ]; then \
-	    $(ECHO) "  deleting" `$(WC) -l $$($1_DELETESS_FILE) | $(AWK) '{ print $$$$1 }'` files && \
-	    $(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
-	  fi $$(NEWLINE) \
-	  $$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
-	  $$($1_JARINDEX) && true )
-
-  # Add jar to target list
-  $1 += $$($1_JAR)
-endef
-
-
 define add_file_to_copy
   # param 1 = BUILD_MYPACKAGE
   # parma 2 = The source file to copy.
@@ -335,7 +85,6 @@
   endif
 endef
 
-
 # This macro is used only for properties files that are to be
 # copied over to the classes directory in cleaned form:
 # Previously this was inconsistently done in different repositories.
@@ -442,17 +191,16 @@
   $1_SERVER_JVM := $$($$($1_SETUP)_SERVER_JVM)
   $1_DISABLE_SJAVAC := $$($$($1_SETUP)_DISABLE_SJAVAC)
 
-  # Handle addons and overrides.
-  $1_SRC:=$$(call ADD_SRCS,$$($1_SRC))
   # Make sure the dirs exist.
   $$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupJavaCompilation $1 contains missing directory >$$d<)))
   $$(call MakeDir,$$($1_BIN))
   # Add all source roots to the find cache since we are likely going to run find
   # on these more than once. The cache will only be updated if necessary.
   $$(eval $$(call FillCacheFind,$$($1_SRC)))
-  # Find all files in the source trees. Preserve order of source roots for overrides to
-  # work correctly. CacheFind does not preserve order so need to call it for each root.
-  $1_ALL_SRCS += $$(filter-out $(OVR_SRCS),$$(foreach s,$$($1_SRC),$$(call CacheFind,$$(s))))
+  # Find all files in the source trees. Preserve order of source roots so that
+  # the first version in case of multiple instances of the same file is selected.
+  # CacheFind does not preserve order so need to call it for each root.
+  $1_ALL_SRCS += $$(foreach s, $$($1_SRC), $$(call CacheFind, $$(s)))
   # Extract the java files.
   ifneq ($$($1_EXCLUDE_FILES),)
     $1_EXCLUDE_FILES_PATTERN:=$$(addprefix %,$$($1_EXCLUDE_FILES))
@@ -665,7 +413,7 @@
       $1_SUFFIXES:=.class $$($1_CLEAN) $$($1_COPY)
     endif
 
-    $$(eval $$(call SetupArchive,ARCHIVE_$1, \
+    $$(eval $$(call SetupJarArchive, ARCHIVE_$1, \
         DEPENDENCIES:=$$($1), \
         SRCS:=$$($1_BIN), \
         SUFFIXES:=$$($1_SUFFIXES), \
@@ -678,7 +426,8 @@
         EXTRA_MANIFEST_ATTR:=$$($1_EXTRA_MANIFEST_ATTR), \
         JARINDEX:=$$($1_JARINDEX), \
         HEADERS:=$$($1_HEADERS), \
-        SETUP:=$$($1_SETUP)))
+        SETUP:=$$($1_SETUP), \
+    ))
 
     # Add jar to target list
     $1 += $$($1_JAR)
@@ -686,7 +435,7 @@
 
   # Check if a srczip was specified, then setup the rules for the srczip.
   ifneq (,$$($1_SRCZIP))
-    $$(eval $$(call SetupZipArchive,ARCHIVE_$1, \
+    $$(eval $$(call SetupZipArchive, ZIP_ARCHIVE_$1, \
         SRC:=$$($1_SRC), \
         ZIP:=$$($1_SRCZIP), \
         INCLUDES:=$$($1_INCLUDES), \
--- a/make/devkit/createMacosxDevkit.sh	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/devkit/createMacosxDevkit.sh	Wed Jul 05 20:58:59 2017 +0200
@@ -29,7 +29,7 @@
 # and the aux tools need to be available.
 # erik.joelsson@oracle.com
 
-USAGE="$0 <Xcode.dmg> <XQuartz.dmg> [<auxtools.dmg>]"
+USAGE="$0 <Xcode.dmg> <XQuartz.dmg> <gnu make binary> [<auxtools.dmg>]"
 
 if [ "$1" = "" ] || [ "$2" = "" ]; then
     echo $USAGE
@@ -38,7 +38,8 @@
 
 XCODE_DMG="$1"
 XQUARTZ_DMG="$2"
-AUXTOOLS_DMG="$3"
+GNU_MAKE="$3"
+AUXTOOLS_DMG="$4"
 
 SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
 BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
@@ -52,8 +53,13 @@
 # Find the version of Xcode
 XCODE_VERSION="$(/Volumes/Xcode/Xcode.app/Contents/Developer/usr/bin/xcodebuild -version \
     | awk '/Xcode/ { print $2 }' )"
+SDK_VERSION="MacOSX10.9"
+if [ ! -e "/Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/${SDK_VERSION}.sdk" ]; then
+    echo "Expected SDK version not found: ${SDK_VERSION}"
+    exit 1
+fi
 
-DEVKIT_ROOT="${BUILD_DIR}/Xcode${XCODE_VERSION}-devkit"
+DEVKIT_ROOT="${BUILD_DIR}/Xcode${XCODE_VERSION}-${SDK_VERSION}"
 DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz"
 
 echo "Xcode version: $XCODE_VERSION"
@@ -71,10 +77,9 @@
 rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/iPhone*
 rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Documentation
 rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/usr/share/man
-if [ -e $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk ]; then
-    rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk
-    rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/share/man
-fi
+( cd $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs \
+    && rm -rf `ls | grep -v ${SDK_VERSION}` )
+rm -rf $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/${SDK_VERSION}.sdk/usr/share/man
 
 hdiutil detach /Volumes/Xcode
 
@@ -91,20 +96,27 @@
 rm -rf /tmp/x11
 mkdir /tmp/x11
 cd /tmp/x11
-cat /tmp/XQuartz-*/x11.pkg/Payload | gunzip -dc |cpio -i
+cat /tmp/XQuartz/x11.pkg/Payload | gunzip -dc | cpio -i
 
+mkdir -p $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
+mkdir -p $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/lib/
 cp -RH opt/X11/include/freetype2 \
-    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/
+    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
 cp -RH opt/X11/include/ft2build.h \
-    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/
+    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/include/
 cp -RH opt/X11/lib/libfreetype.* \
-    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/
+    $DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/X11/lib/
 
 cd -
 
 hdiutil detach /Volumes/XQuartz-*
 
 ################################################################################
+# Copy gnu make
+mkdir -p $DEVKIT_ROOT/bin
+cp $GNU_MAKE $DEVKIT_ROOT/bin
+
+################################################################################
 # Optionally copy PackageMaker
 
 if [ -e "$AUXTOOLS_DMG" ]; then
@@ -129,10 +141,12 @@
 echo "Generating devkit.info..."
 rm -f $DEVKIT_ROOT/devkit.info
 echo-info "# This file describes to configure how to interpret the contents of this devkit"
+echo-info "# The parameters used to create this devkit were:"
+echo-info "# $*"
 echo-info "DEVKIT_NAME=\"Xcode $XCODE_VERSION (devkit)\""
 echo-info "DEVKIT_TOOLCHAIN_PATH=\"\$DEVKIT_ROOT/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:\$DEVKIT_ROOT/Xcode.app/Contents/Developer/usr/bin\""
 echo-info "DEVKIT_SYSROOT=\"\$DEVKIT_ROOT/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk\""
-echo-info "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/PackageMaker.app/Contents/MacOS:\$DEVKIT_TOOLCHAIN_PATH\""
+echo-info "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/bin:\$DEVKIT_ROOT/PackageMaker.app/Contents/MacOS:\$DEVKIT_TOOLCHAIN_PATH\""
 
 ################################################################################
 # Copy this script
--- a/make/jprt.properties	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/jprt.properties	Wed Jul 05 20:58:59 2017 +0200
@@ -128,13 +128,13 @@
     ${jprt.i586.build.configure.args}
 jprt.linux_x64.build.configure.args=					\
     --with-devkit=$GCC492_OEL64_HOME
+jprt.macosx_x64.build.configure.args=					\
+    --with-devkit=$XCODE63_MACOSX109_HOME
 jprt.windows_i586.build.configure.args=					\
     --with-devkit=$VS2013SP4_HOME					\
     ${jprt.i586.build.configure.args}
 jprt.windows_x64.build.configure.args=					\
     --with-devkit=$VS2013SP4_HOME
-jprt.macosx_x64.build.configure.args=                    \
-    --with-devkit=$XCODE_511_HOME
 
 ########
 #
--- a/make/test/BuildTestLib.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/make/test/BuildTestLib.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -35,25 +35,19 @@
 TEST_LIB_SOURCE_DIR := $(TOPDIR)/test/lib
 TEST_LIB_SUPPORT := $(SUPPORT_OUTPUTDIR)/test/lib
 
-# Unfortunately, test-lib.jar does not compile properly without warnings.
-$(eval $(call SetupJavaCompiler, BOOT_JAVAC_NOWARNINGS, \
-    JAVAC := $(JAVAC), \
-    FLAGS := -XDignore.symbol.file=true -g, \
-    DISABLE_SJAVAC := true, \
-))
-
 $(eval $(call SetupJavaCompilation, BUILD_WB_JAR, \
-    SETUP := BOOT_JAVAC, \
+    SETUP := GENERATE_USINGJDKBYTECODE, \
     SRC := $(TEST_LIB_SOURCE_DIR)/sun, \
     BIN := $(TEST_LIB_SUPPORT), \
     JAR := $(TEST_LIB_SUPPORT)/wb.jar, \
+    ADD_JAVAC_FLAGS := $(JAVAC_WARNINGS), \
 ))
 
 TARGETS += $(BUILD_WB_JAR)
 
 # test-lib.jar will contain only hprof classes until JDK-8081381 is resolved
 $(eval $(call SetupJavaCompilation, BUILD_TEST_LIB_JAR, \
-    SETUP := BOOT_JAVAC_NOWARNINGS, \
+    SETUP := GENERATE_USINGJDKBYTECODE, \
     SRC := $(TEST_LIB_SOURCE_DIR)/share/classes/jdk/test/lib/hprof, \
     BIN := $(TEST_LIB_SUPPORT), \
     JAR := $(TEST_LIB_SUPPORT)/test-lib.jar, \
--- a/test/lib/sun/hotspot/WhiteBox.java	Thu Nov 05 13:42:47 2015 -0800
+++ b/test/lib/sun/hotspot/WhiteBox.java	Wed Jul 05 20:58:59 2017 +0200
@@ -166,6 +166,8 @@
 
   // Compiler
   public native int     matchesMethod(Executable method, String pattern);
+  public native int     matchesInline(Executable method, String pattern);
+  public native boolean shouldPrintAssembly(Executable method);
   public native int     deoptimizeFrames(boolean makeNotEntrant);
   public native void    deoptimizeAll();
   public        boolean isMethodCompiled(Executable method) {
--- a/test/make/TestJavaCompilation.gmk	Thu Nov 05 13:42:47 2015 -0800
+++ b/test/make/TestJavaCompilation.gmk	Wed Jul 05 20:58:59 2017 +0200
@@ -27,6 +27,7 @@
 
 include $(SPEC)
 include MakeBase.gmk
+include JarArchive.gmk
 include JavaCompilation.gmk
 
 THIS_FILE := $(SRC_ROOT)/test/make/TestJavaCompilation.gmk
@@ -66,11 +67,12 @@
 	$(TOUCH) $(JAR1_SRC_ROOT)/META-INF/metafile
 	$(TOUCH) $@
 
-$(eval $(call SetupArchive,BUILD_JAR1, \
+$(eval $(call SetupJarArchive, BUILD_JAR1, \
     DEPENDENCIES := $(OUTPUT_DIR)/_jar1_created, \
     SRCS := $(JAR1_SRC_ROOT), \
     MANIFEST := $(JAR1_MANIFEST), \
-    JAR := $(JAR1_FILE)))
+    JAR := $(JAR1_FILE), \
+))
 
 $(OUTPUT_DIR)/_jar1_verified: $(BUILD_JAR1)
 	$(RM) -r $(JAR1_UNZIP)
@@ -142,10 +144,11 @@
 	$(TOUCH) $(JAR2_SRC_ROOT2)/dir2/file2.class
 	$(TOUCH) $@
 
-$(eval $(call SetupArchive,BUILD_JAR2, \
+$(eval $(call SetupJarArchive, BUILD_JAR2, \
     DEPENDENCIES := $(OUTPUT_DIR)/_jar2_created, \
     SRCS := $(JAR2_SRC_ROOT1) $(JAR2_SRC_ROOT2), \
-    JAR := $(JAR2_FILE)))
+    JAR := $(JAR2_FILE), \
+))
 
 $(OUTPUT_DIR)/_jar2_verified: $(BUILD_JAR2)
 	$(RM) -r $(JAR2_UNZIP)
@@ -195,14 +198,15 @@
 	$(TOUCH) $(JAR3_SRC_ROOT2)/dir2/file\$$foo.dollar
 	$(TOUCH) $@
 
-$(eval $(call SetupArchive,BUILD_JAR3, \
+$(eval $(call SetupJarArchive, BUILD_JAR3, \
     DEPENDENCIES := $(OUTPUT_DIR)/_jar3_created, \
     SRCS := $(JAR3_SRC_ROOT1) $(JAR3_SRC_ROOT2), \
     EXTRA_FILES := extra-file \
         dir2/file$$$$foo.dollar \
         $(JAR3_SRC_ROOT2)/extra-file-abs, \
     EXCLUDE_FILES := dir1/file1$$$$foo.class, \
-    JAR := $(JAR3_FILE)))
+    JAR := $(JAR3_FILE), \
+))
 
 $(OUTPUT_DIR)/_jar3_verified: $(BUILD_JAR3)
 	$(RM) -r $(JAR3_UNZIP)