Merge
authorduke
Wed, 05 Jul 2017 19:35:40 +0200
changeset 23747 dd2bb932a0ff
parent 23746 ce60f7b62312 (current diff)
parent 23549 8415322d9792 (diff)
child 23758 8194e17854ea
Merge
hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.cpp
hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.hpp
--- a/.hgtags-top-repo	Fri Apr 11 14:07:25 2014 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 19:35:40 2017 +0200
@@ -249,3 +249,4 @@
 cb4c3440bc2748101923e2488506e61009ab1bf5 jdk9-b04
 8c63f0b6ada282f27e3a80125e53c3be603f9af7 jdk9-b05
 d0b525cd31b87abeb6d5b7e3516953eeb13b323c jdk9-b06
+0ea015c298b201c07fa33990f2445b6d0ef3566d jdk9-b07
--- a/common/autoconf/basics.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/basics.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -46,10 +46,24 @@
 # Appends a string to a path variable, only adding the : when needed.
 AC_DEFUN([BASIC_APPEND_TO_PATH],
 [
-  if test "x[$]$1" = x; then
-    $1="$2"
-  else
-    $1="[$]$1:$2"
+  if test "x$2" != x; then
+    if test "x[$]$1" = x; then
+      $1="$2"
+    else
+      $1="[$]$1:$2"
+    fi
+  fi
+])
+
+# Prepends a string to a path variable, only adding the : when needed.
+AC_DEFUN([BASIC_PREPEND_TO_PATH],
+[
+  if test "x$2" != x; then
+    if test "x[$]$1" = x; then
+      $1="$2"
+    else
+      $1="$2:[$]$1"
+    fi
   fi
 ])
 
@@ -442,43 +456,95 @@
 
   # Locate the directory of this script.
   AUTOCONF_DIR=$TOPDIR/common/autoconf
+])
+
+AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
+[
+  AC_ARG_WITH([devkit], [AS_HELP_STRING([--with-devkit],
+      [use this devkit for compilers, tools and resources])],
+      [
+        BASIC_FIXUP_PATH([with_devkit])
+        DEVKIT_ROOT="$with_devkit"
+        # Check for a meta data info file in the root of the devkit
+        if test -f "$DEVKIT_ROOT/devkit.info"; then
+          # This potentially sets the following:
+          # DEVKIT_NAME: A descriptive name of the devkit
+          # DEVKIT_TOOLCHAIN_PATH: Corresponds to --with-toolchain-path
+          # DEVKIT_EXTRA_PATH: Corresponds to --with-extra-path
+          # DEVKIT_SYSROOT: Corresponds to --with-sysroot
+          . $DEVKIT_ROOT/devkit.info
+        fi
+
+        AC_MSG_CHECKING([for devkit])
+        if test "x$DEVKIT_NAME" != x; then
+          AC_MSG_RESULT([$DEVKIT_NAME in $DEVKIT_ROOT])
+        else
+          AC_MSG_RESULT([$DEVKIT_ROOT])
+        fi
+
+        if test "x$DEVKIT_EXTRA_PATH" != x; then
+          BASIC_PREPEND_TO_PATH([EXTRA_PATH],$DEVKIT_EXTRA_PATH)
+        fi
+
+        # Fallback default of just /bin if DEVKIT_PATH is not defined
+        if test "x$DEVKIT_TOOLCHAIN_PATH" = x; then
+          DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/bin"
+        fi
+        BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$DEVKIT_TOOLCHAIN_PATH)
+
+        # If DEVKIT_SYSROOT is set, use that, otherwise try a couple of known
+        # places for backwards compatiblity.
+        if test "x$DEVKIT_SYSROOT" != x; then
+          SYSROOT="$DEVKIT_SYSROOT"
+        elif test -d "$DEVKIT_ROOT/$host_alias/libc"; then
+          SYSROOT="$DEVKIT_ROOT/$host_alias/libc"
+        elif test -d "$DEVKIT_ROOT/$host/sys-root"; then
+          SYSROOT="$DEVKIT_ROOT/$host/sys-root"
+        fi
+      ]
+  )
+
+  # You can force the sysroot if the sysroot encoded into the compiler tools
+  # is not correct.
+  AC_ARG_WITH(sys-root, [AS_HELP_STRING([--with-sys-root],
+      [alias for --with-sysroot for backwards compatability])],
+      [SYSROOT=$with_sys_root]
+  )
+
+  AC_ARG_WITH(sysroot, [AS_HELP_STRING([--with-sysroot],
+      [use this directory as sysroot)])],
+      [SYSROOT=$with_sysroot]
+  )
+
+  AC_ARG_WITH([tools-dir], [AS_HELP_STRING([--with-tools-dir],
+      [alias for --with-toolchain-path for backwards compatibility])],
+      [BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_tools_dir)]
+  )
+
+  AC_ARG_WITH([toolchain-path], [AS_HELP_STRING([--with-toolchain-path],
+      [prepend these directories when searching for toolchain binaries (compilers etc)])],
+      [BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_toolchain_path)]
+  )
+
+  AC_ARG_WITH([extra-path], [AS_HELP_STRING([--with-extra-path],
+      [prepend these directories to the default path])],
+      [BASIC_PREPEND_TO_PATH([EXTRA_PATH],$with_extra_path)]
+  )
+
+  # Prepend the extra path to the global path
+  BASIC_PREPEND_TO_PATH([PATH],$EXTRA_PATH)
 
   if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
     # Add extra search paths on solaris for utilities like ar and as etc...
     PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin"
   fi
 
-  # You can force the sys-root if the sys-root encoded into the cross compiler tools
-  # is not correct.
-  AC_ARG_WITH(sys-root, [AS_HELP_STRING([--with-sys-root],
-      [pass this sys-root to the compilers and tools (for cross-compiling)])])
-
-  if test "x$with_sys_root" != x; then
-    SYS_ROOT=$with_sys_root
-  else
-    SYS_ROOT=/
-  fi
-  AC_SUBST(SYS_ROOT)
-
-  AC_ARG_WITH([tools-dir], [AS_HELP_STRING([--with-tools-dir],
-      [search this directory for compilers and tools (for cross-compiling)])],
-      [TOOLS_DIR=$with_tools_dir]
-  )
-
-  AC_ARG_WITH([devkit], [AS_HELP_STRING([--with-devkit],
-      [use this directory as base for tools-dir and sys-root (for cross-compiling)])],
-      [
-        if test "x$with_sys_root" != x; then
-          AC_MSG_ERROR([Cannot specify both --with-devkit and --with-sys-root at the same time])
-        fi
-        BASIC_FIXUP_PATH([with_devkit])
-        BASIC_APPEND_TO_PATH([TOOLS_DIR],$with_devkit/bin)
-        if test -d "$with_devkit/$host_alias/libc"; then
-          SYS_ROOT=$with_devkit/$host_alias/libc
-        elif test -d "$with_devkit/$host/sys-root"; then
-          SYS_ROOT=$with_devkit/$host/sys-root
-        fi
-      ])
+  AC_MSG_CHECKING([for sysroot])
+  AC_MSG_RESULT([$SYSROOT])
+  AC_MSG_CHECKING([for toolchain path])
+  AC_MSG_RESULT([$TOOLCHAIN_PATH])
+  AC_MSG_CHECKING([for extra path])
+  AC_MSG_RESULT([$EXTRA_PATH])
 ])
 
 AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
@@ -648,10 +714,10 @@
     fi
 
     if test "x$FOUND_MAKE" = x; then
-      if test "x$TOOLS_DIR" != x; then
-        # We have a tools-dir, check that as well before giving up.
+      if test "x$TOOLCHAIN_PATH" != x; then
+        # We have a toolchain path, check that as well before giving up.
         OLD_PATH=$PATH
-        PATH=$TOOLS_DIR:$PATH
+        PATH=$TOOLCHAIN_PATH:$PATH
         AC_PATH_PROGS(CHECK_TOOLSDIR_GMAKE, gmake)
         BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_GMAKE", [gmake in tools-dir])
         if test "x$FOUND_MAKE" = x; then
--- a/common/autoconf/build-aux/config.guess	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/build-aux/config.guess	Wed Jul 05 19:35:40 2017 +0200
@@ -76,4 +76,14 @@
   OUT=powerpc$KERNEL_BITMODE`echo $OUT | sed -e 's/[^-]*//'`
 fi
 
+# Test and fix little endian PowerPC64.
+# TODO: should be handled by autoconf-config.guess. 
+if [ "x$OUT" = x ]; then
+  if [ `uname -m` = ppc64le ]; then
+    if [ `uname -s` = Linux ]; then
+      OUT=powerpc64le-unknown-linux-gnu
+    fi
+  fi
+fi
+
 echo $OUT
--- a/common/autoconf/build-performance.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/build-performance.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -169,8 +169,8 @@
   if test "x$enable_ccache" = xyes; then
     AC_MSG_RESULT([yes])
     OLD_PATH="$PATH"
-    if test "x$TOOLS_DIR" != x; then
-      PATH=$TOOLS_DIR:$PATH
+    if test "x$TOOLCHAIN_PATH" != x; then
+      PATH=$TOOLCHAIN_PATH:$PATH
     fi
     BASIC_REQUIRE_PROGS(CCACHE, ccache)
     CCACHE_STATUS="enabled"
--- a/common/autoconf/configure.ac	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/configure.ac	Wed Jul 05 19:35:40 2017 +0200
@@ -100,6 +100,9 @@
 # With basic setup done, call the custom early hook.
 CUSTOM_EARLY_HOOK
 
+# Check if we have devkits, extra paths or sysroot set.
+BASIC_SETUP_DEVKIT
+
 # To properly create a configuration name, we need to have the OpenJDK target
 # and options (variants and debug level) parsed.
 BASIC_SETUP_OUTPUT_DIR
--- a/common/autoconf/flags.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/flags.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -119,6 +119,32 @@
     # FIXME: likely bug, should be CCXXFLAGS_JDK? or one for C or CXX.
     CCXXFLAGS="$CCXXFLAGS -nologo"
   fi
+
+  if test "x$SYSROOT" != "x"; then
+    if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
+      if test "x$OPENJDK_TARGET_OS" = xsolaris; then
+        # Solaris Studio does not have a concept of sysroot. Instead we must
+        # make sure the default include and lib dirs are appended to each 
+        # compile and link command line.
+        SYSROOT_CFLAGS="-I$SYSROOT/usr/include"
+        SYSROOT_LDFLAGS="-L$SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
+            -L$SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
+            -L$SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
+      fi
+    elif test "x$TOOLCHAIN_TYPE" = xgcc; then
+      SYSROOT_CFLAGS="--sysroot=\"$SYSROOT\""
+      SYSROOT_LDFLAGS="--sysroot=\"$SYSROOT\""
+    elif test "x$TOOLCHAIN_TYPE" = xclang; then
+      SYSROOT_CFLAGS="-isysroot \"$SYSROOT\""
+      SYSROOT_LDFLAGS="-isysroot \"$SYSROOT\""
+    fi
+    # Propagate the sysroot args to hotspot
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $SYSROOT_CFLAGS"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $SYSROOT_CFLAGS"
+    LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $SYSROOT_LDFLAGS"
+  fi
+  AC_SUBST(SYSROOT_CFLAGS)
+  AC_SUBST(SYSROOT_LDFLAGS)
 ])
 
 AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS],
@@ -421,9 +447,9 @@
   LDFLAGS_JDK="${LDFLAGS_JDK} $with_extra_ldflags"
 
   # Hotspot needs these set in their legacy form
-  LEGACY_EXTRA_CFLAGS=$with_extra_cflags
-  LEGACY_EXTRA_CXXFLAGS=$with_extra_cxxflags
-  LEGACY_EXTRA_LDFLAGS=$with_extra_ldflags
+  LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $with_extra_cflags"
+  LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $with_extra_cxxflags"
+  LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $with_extra_ldflags"
 
   AC_SUBST(LEGACY_EXTRA_CFLAGS)
   AC_SUBST(LEGACY_EXTRA_CXXFLAGS)
@@ -521,7 +547,13 @@
       CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_LITTLE_ENDIAN"
     fi
   else
-    CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN"
+    # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they
+    # are defined in the system?
+    if test "x$OPENJDK_TARGET_OS" = xsolaris; then
+      CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN="
+    else
+      CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN"
+    fi
   fi
   
   # Setup target OS define. Use OS target name but in upper case.
@@ -735,4 +767,20 @@
       [COMPILER_SUPPORTS_TARGET_BITS_FLAG=true],
       [COMPILER_SUPPORTS_TARGET_BITS_FLAG=false])
   AC_SUBST(COMPILER_SUPPORTS_TARGET_BITS_FLAG)
+
+  case "${TOOLCHAIN_TYPE}" in
+    microsoft)
+      CFLAGS_WARNINGS_ARE_ERRORS="/WX"
+      ;;
+    solstudio)
+      CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all"
+      ;;
+    gcc)
+      CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
+      ;;
+    clang)
+      CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
+      ;;
+  esac
+  AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
 ])
--- a/common/autoconf/generated-configure.sh	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 19:35:40 2017 +0200
@@ -664,7 +664,6 @@
 FREETYPE_LIBS
 FREETYPE_CFLAGS
 CUPS_CFLAGS
-OPENWIN_HOME
 X_EXTRA_LIBS
 X_LIBS
 X_PRE_LIBS
@@ -673,6 +672,7 @@
 FIXPATH
 ZIP_DEBUGINFO_FILES
 ENABLE_DEBUG_SYMBOLS
+CFLAGS_WARNINGS_ARE_ERRORS
 COMPILER_SUPPORTS_TARGET_BITS_FLAG
 ZERO_ARCHFLAG
 LDFLAGS_CXX_JDK
@@ -707,6 +707,8 @@
 SHARED_LIBRARY_FLAGS
 CXX_FLAG_REORDER
 C_FLAG_REORDER
+SYSROOT_LDFLAGS
+SYSROOT_CFLAGS
 RC_FLAGS
 AR_OUT_OPTION
 LD_OUT_OPTION
@@ -759,7 +761,7 @@
 CXX
 ac_ct_PROPER_COMPILER_CXX
 PROPER_COMPILER_CXX
-TOOLS_DIR_CXX
+TOOLCHAIN_PATH_CXX
 POTENTIAL_CXX
 OBJEXT
 EXEEXT
@@ -770,11 +772,11 @@
 CC
 ac_ct_PROPER_COMPILER_CC
 PROPER_COMPILER_CC
-TOOLS_DIR_CC
+TOOLCHAIN_PATH_CC
 POTENTIAL_CC
-VS_PATH
 VS_LIB
 VS_INCLUDE
+VS_PATH
 CYGWIN_LINK
 EXE_SUFFIX
 OBJ_SUFFIX
@@ -886,7 +888,6 @@
 BUILD_LOG_WRAPPER
 BUILD_LOG_PREVIOUS
 BUILD_LOG
-SYS_ROOT
 TOPDIR
 PATH_SEP
 ZERO_ARCHDEF
@@ -1019,9 +1020,6 @@
 ac_user_opts='
 enable_option_checking
 with_target_bits
-with_sys_root
-with_tools_dir
-with_devkit
 enable_openjdk_only
 with_custom_make_dir
 with_jdk_variant
@@ -1029,6 +1027,12 @@
 with_jvm_variants
 enable_debug
 with_debug_level
+with_devkit
+with_sys_root
+with_sysroot
+with_tools_dir
+with_toolchain_path
+with_extra_path
 with_conf_name
 with_builddeps_conf
 with_builddeps_server
@@ -1847,12 +1851,6 @@
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --with-target-bits      build 32-bit or 64-bit binaries (for platforms that
                           support it), e.g. --with-target-bits=32 [guessed]
-  --with-sys-root         pass this sys-root to the compilers and tools (for
-                          cross-compiling)
-  --with-tools-dir        search this directory for compilers and tools (for
-                          cross-compiling)
-  --with-devkit           use this directory as base for tools-dir and
-                          sys-root (for cross-compiling)
   --with-custom-make-dir  Deprecated. Option is kept for backwards
                           compatibility and is ignored
   --with-jdk-variant      JDK variant to build (normal) [normal]
@@ -1860,8 +1858,16 @@
   --with-jvm-variants     JVM variants (separated by commas) to build (server,
                           client, minimal1, kernel, zero, zeroshark, core)
                           [server]
-  --with-debug-level      set the debug level (release, fastdebug, slowdebug)
-                          [release]
+  --with-debug-level      set the debug level (release, fastdebug, slowdebug,
+                          optimized (HotSpot build only)) [release]
+  --with-devkit           use this devkit for compilers, tools and resources
+  --with-sys-root         alias for --with-sysroot for backwards compatability
+  --with-sysroot          use this directory as sysroot)
+  --with-tools-dir        alias for --with-toolchain-path for backwards
+                          compatibility
+  --with-toolchain-path   prepend these directories when searching for
+                          toolchain binaries (compilers etc)
+  --with-extra-path       prepend these directories to the default path
   --with-conf-name        use this as the name of the configuration [generated
                           from important configuration options]
   --with-builddeps-conf   use this configuration file for the builddeps
@@ -3324,6 +3330,9 @@
 # Appends a string to a path variable, only adding the : when needed.
 
 
+# Prepends a string to a path variable, only adding the : when needed.
+
+
 # This will make sure the given variable points to a full and proper
 # path. This means:
 # 1) There will be no spaces in the path. On posix platforms,
@@ -3406,6 +3415,8 @@
 
 
 
+
+
 #%%% Simple tools %%%
 
 # Check if we have found a usable version of make
@@ -4232,7 +4243,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1394794899
+DATE_WHEN_GENERATED=1396624161
 
 ###############################################################################
 #
@@ -13507,6 +13518,12 @@
       VAR_CPU_BITS=64
       VAR_CPU_ENDIAN=big
       ;;
+    powerpc64le)
+      VAR_CPU=ppc64
+      VAR_CPU_ARCH=ppc
+      VAR_CPU_BITS=64
+      VAR_CPU_ENDIAN=little
+      ;;
     s390)
       VAR_CPU=s390
       VAR_CPU_ARCH=s390
@@ -13632,6 +13649,12 @@
       VAR_CPU_BITS=64
       VAR_CPU_ENDIAN=big
       ;;
+    powerpc64le)
+      VAR_CPU=ppc64
+      VAR_CPU_ARCH=ppc
+      VAR_CPU_BITS=64
+      VAR_CPU_ENDIAN=little
+      ;;
     s390)
       VAR_CPU=s390
       VAR_CPU_ARCH=s390
@@ -14239,180 +14262,6 @@
   # Locate the directory of this script.
   AUTOCONF_DIR=$TOPDIR/common/autoconf
 
-  if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
-    # Add extra search paths on solaris for utilities like ar and as etc...
-    PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin"
-  fi
-
-  # You can force the sys-root if the sys-root encoded into the cross compiler tools
-  # is not correct.
-
-# Check whether --with-sys-root was given.
-if test "${with_sys_root+set}" = set; then :
-  withval=$with_sys_root;
-fi
-
-
-  if test "x$with_sys_root" != x; then
-    SYS_ROOT=$with_sys_root
-  else
-    SYS_ROOT=/
-  fi
-
-
-
-# Check whether --with-tools-dir was given.
-if test "${with_tools_dir+set}" = set; then :
-  withval=$with_tools_dir; TOOLS_DIR=$with_tools_dir
-
-fi
-
-
-
-# Check whether --with-devkit was given.
-if test "${with_devkit+set}" = set; then :
-  withval=$with_devkit;
-        if test "x$with_sys_root" != x; then
-          as_fn_error $? "Cannot specify both --with-devkit and --with-sys-root at the same time" "$LINENO" 5
-        fi
-
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-
-  # Input might be given as Windows format, start by converting to
-  # unix format.
-  path="$with_devkit"
-  new_path=`$CYGPATH -u "$path"`
-
-  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
-  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
-  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
-  # "foo.exe" is OK but "foo" is an error.
-  #
-  # This test is therefore slightly more accurate than "test -f" to check for file precense.
-  # It is also a way to make sure we got the proper file name for the real test later on.
-  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
-  if test "x$test_shortpath" = x; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of with_devkit, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of with_devkit, which resolves as \"$path\", is invalid." >&6;}
-    as_fn_error $? "Cannot locate the the path of with_devkit" "$LINENO" 5
-  fi
-
-  # Call helper function which possibly converts this using DOS-style short mode.
-  # If so, the updated path is stored in $new_path.
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
-    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
-    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
-      # Going to short mode and back again did indeed matter. Since short mode is
-      # case insensitive, let's make it lowercase to improve readability.
-      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-      # Now convert it back to Unix-stile (cygpath)
-      input_path=`$CYGPATH -u "$shortmode_path"`
-      new_path="$input_path"
-    fi
-  fi
-
-  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
-  if test "x$test_cygdrive_prefix" = x; then
-    # As a simple fix, exclude /usr/bin since it's not a real path.
-    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
-      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
-      # a path prefixed by /cygdrive for fixpath to work.
-      new_path="$CYGWIN_ROOT_PATH$input_path"
-    fi
-  fi
-
-
-  if test "x$path" != "x$new_path"; then
-    with_devkit="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting with_devkit to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting with_devkit to \"$new_path\"" >&6;}
-  fi
-
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-
-  path="$with_devkit"
-  has_colon=`$ECHO $path | $GREP ^.:`
-  new_path="$path"
-  if test "x$has_colon" = x; then
-    # Not in mixed or Windows style, start by that.
-    new_path=`cmd //c echo $path`
-  fi
-
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-  fi
-
-
-  windows_path="$new_path"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    unix_path=`$CYGPATH -u "$windows_path"`
-    new_path="$unix_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
-    new_path="$unix_path"
-  fi
-
-  if test "x$path" != "x$new_path"; then
-    with_devkit="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting with_devkit to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting with_devkit to \"$new_path\"" >&6;}
-  fi
-
-  # Save the first 10 bytes of this path to the storage, so fixpath can work.
-  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
-
-  else
-    # We're on a posix platform. Hooray! :)
-    path="$with_devkit"
-    has_space=`$ECHO "$path" | $GREP " "`
-    if test "x$has_space" != x; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of with_devkit, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of with_devkit, which resolves as \"$path\", is invalid." >&6;}
-      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
-    fi
-
-    # Use eval to expand a potential ~
-    eval path="$path"
-    if test ! -f "$path" && test ! -d "$path"; then
-      as_fn_error $? "The path of with_devkit, which resolves as \"$path\", is not found." "$LINENO" 5
-    fi
-
-    with_devkit="`cd "$path"; $THEPWDCMD -L`"
-  fi
-
-
-  if test "x$TOOLS_DIR" = x; then
-    TOOLS_DIR="$with_devkit/bin"
-  else
-    TOOLS_DIR="$TOOLS_DIR:$with_devkit/bin"
-  fi
-
-        if test -d "$with_devkit/$host_alias/libc"; then
-          SYS_ROOT=$with_devkit/$host_alias/libc
-        elif test -d "$with_devkit/$host/sys-root"; then
-          SYS_ROOT=$with_devkit/$host/sys-root
-        fi
-
-fi
-
-
 
   # Setup default logging of stdout and stderr to build.log in the output root.
   BUILD_LOG='$(OUTPUT_ROOT)/build.log'
@@ -14647,6 +14496,7 @@
   #
   # Set the debug level
   #    release: no debug information, all optimizations, no asserts.
+  #    optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
   #    fastdebug: debug information (-g), all optimizations, all asserts
   #    slowdebug: debug information (-g), no optimizations, all asserts
   #
@@ -14679,6 +14529,7 @@
 $as_echo "$DEBUG_LEVEL" >&6; }
 
   if test "x$DEBUG_LEVEL" != xrelease && \
+      test "x$DEBUG_LEVEL" != xoptimized && \
       test "x$DEBUG_LEVEL" != xfastdebug && \
       test "x$DEBUG_LEVEL" != xslowdebug; then
     as_fn_error $? "Allowed debug levels are: release, fastdebug and slowdebug" "$LINENO" 5
@@ -14715,8 +14566,30 @@
       HOTSPOT_DEBUG_LEVEL="jvmg"
       HOTSPOT_EXPORT="debug"
       ;;
+    optimized )
+      VARIANT="OPT"
+      FASTDEBUG="false"
+      DEBUG_CLASSFILES="false"
+      BUILD_VARIANT_RELEASE="-optimized"
+      HOTSPOT_DEBUG_LEVEL="optimized"
+      HOTSPOT_EXPORT="optimized"
+      ;;
   esac
 
+  # The debug level 'optimized' is a little special because it is currently only
+  # applicable to the HotSpot build where it means to build a completely
+  # optimized version of the VM without any debugging code (like for the
+  # 'release' debug level which is called 'product' in the HotSpot build) but
+  # with the exception that it can contain additional code which is otherwise
+  # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to
+  # test new and/or experimental features which are not intended for customer
+  # shipment. Because these new features need to be tested and benchmarked in
+  # real world scenarios, we want to build the containing JDK at the 'release'
+  # debug level.
+  if test "x$DEBUG_LEVEL" = xoptimized; then
+    DEBUG_LEVEL="release"
+  fi
+
   #####
   # Generate the legacy makefile targets for hotspot.
   # The hotspot api for selecting the build artifacts, really, needs to be improved.
@@ -14775,6 +14648,291 @@
 # With basic setup done, call the custom early hook.
 
 
+# Check if we have devkits, extra paths or sysroot set.
+
+
+# Check whether --with-devkit was given.
+if test "${with_devkit+set}" = set; then :
+  withval=$with_devkit;
+
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$with_devkit"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of with_devkit, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of with_devkit, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of with_devkit" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-stile (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    with_devkit="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting with_devkit to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting with_devkit to \"$new_path\"" >&6;}
+  fi
+
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$with_devkit"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    with_devkit="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting with_devkit to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting with_devkit to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+  else
+    # We're on a posix platform. Hooray! :)
+    path="$with_devkit"
+    has_space=`$ECHO "$path" | $GREP " "`
+    if test "x$has_space" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of with_devkit, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of with_devkit, which resolves as \"$path\", is invalid." >&6;}
+      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+    fi
+
+    # Use eval to expand a potential ~
+    eval path="$path"
+    if test ! -f "$path" && test ! -d "$path"; then
+      as_fn_error $? "The path of with_devkit, which resolves as \"$path\", is not found." "$LINENO" 5
+    fi
+
+    with_devkit="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+        DEVKIT_ROOT="$with_devkit"
+        # Check for a meta data info file in the root of the devkit
+        if test -f "$DEVKIT_ROOT/devkit.info"; then
+          # This potentially sets the following:
+          # DEVKIT_NAME: A descriptive name of the devkit
+          # DEVKIT_TOOLCHAIN_PATH: Corresponds to --with-toolchain-path
+          # DEVKIT_EXTRA_PATH: Corresponds to --with-extra-path
+          # DEVKIT_SYSROOT: Corresponds to --with-sysroot
+          . $DEVKIT_ROOT/devkit.info
+        fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for devkit" >&5
+$as_echo_n "checking for devkit... " >&6; }
+        if test "x$DEVKIT_NAME" != x; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEVKIT_NAME in $DEVKIT_ROOT" >&5
+$as_echo "$DEVKIT_NAME in $DEVKIT_ROOT" >&6; }
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEVKIT_ROOT" >&5
+$as_echo "$DEVKIT_ROOT" >&6; }
+        fi
+
+        if test "x$DEVKIT_EXTRA_PATH" != x; then
+
+  if test "x$DEVKIT_EXTRA_PATH" != x; then
+    if test "x$EXTRA_PATH" = x; then
+      EXTRA_PATH="$DEVKIT_EXTRA_PATH"
+    else
+      EXTRA_PATH="$DEVKIT_EXTRA_PATH:$EXTRA_PATH"
+    fi
+  fi
+
+        fi
+
+        # Fallback default of just /bin if DEVKIT_PATH is not defined
+        if test "x$DEVKIT_TOOLCHAIN_PATH" = x; then
+          DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/bin"
+        fi
+
+  if test "x$DEVKIT_TOOLCHAIN_PATH" != x; then
+    if test "x$TOOLCHAIN_PATH" = x; then
+      TOOLCHAIN_PATH="$DEVKIT_TOOLCHAIN_PATH"
+    else
+      TOOLCHAIN_PATH="$DEVKIT_TOOLCHAIN_PATH:$TOOLCHAIN_PATH"
+    fi
+  fi
+
+
+        # If DEVKIT_SYSROOT is set, use that, otherwise try a couple of known
+        # places for backwards compatiblity.
+        if test "x$DEVKIT_SYSROOT" != x; then
+          SYSROOT="$DEVKIT_SYSROOT"
+        elif test -d "$DEVKIT_ROOT/$host_alias/libc"; then
+          SYSROOT="$DEVKIT_ROOT/$host_alias/libc"
+        elif test -d "$DEVKIT_ROOT/$host/sys-root"; then
+          SYSROOT="$DEVKIT_ROOT/$host/sys-root"
+        fi
+
+
+fi
+
+
+  # You can force the sysroot if the sysroot encoded into the compiler tools
+  # is not correct.
+
+# Check whether --with-sys-root was given.
+if test "${with_sys_root+set}" = set; then :
+  withval=$with_sys_root; SYSROOT=$with_sys_root
+
+fi
+
+
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot; SYSROOT=$with_sysroot
+
+fi
+
+
+
+# Check whether --with-tools-dir was given.
+if test "${with_tools_dir+set}" = set; then :
+  withval=$with_tools_dir;
+  if test "x$with_tools_dir" != x; then
+    if test "x$TOOLCHAIN_PATH" = x; then
+      TOOLCHAIN_PATH="$with_tools_dir"
+    else
+      TOOLCHAIN_PATH="$with_tools_dir:$TOOLCHAIN_PATH"
+    fi
+  fi
+
+
+fi
+
+
+
+# Check whether --with-toolchain-path was given.
+if test "${with_toolchain_path+set}" = set; then :
+  withval=$with_toolchain_path;
+  if test "x$with_toolchain_path" != x; then
+    if test "x$TOOLCHAIN_PATH" = x; then
+      TOOLCHAIN_PATH="$with_toolchain_path"
+    else
+      TOOLCHAIN_PATH="$with_toolchain_path:$TOOLCHAIN_PATH"
+    fi
+  fi
+
+
+fi
+
+
+
+# Check whether --with-extra-path was given.
+if test "${with_extra_path+set}" = set; then :
+  withval=$with_extra_path;
+  if test "x$with_extra_path" != x; then
+    if test "x$EXTRA_PATH" = x; then
+      EXTRA_PATH="$with_extra_path"
+    else
+      EXTRA_PATH="$with_extra_path:$EXTRA_PATH"
+    fi
+  fi
+
+
+fi
+
+
+  # Prepend the extra path to the global path
+
+  if test "x$EXTRA_PATH" != x; then
+    if test "x$PATH" = x; then
+      PATH="$EXTRA_PATH"
+    else
+      PATH="$EXTRA_PATH:$PATH"
+    fi
+  fi
+
+
+  if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
+    # Add extra search paths on solaris for utilities like ar and as etc...
+    PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin"
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYSROOT" >&5
+$as_echo "$SYSROOT" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for toolchain path" >&5
+$as_echo_n "checking for toolchain path... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLCHAIN_PATH" >&5
+$as_echo "$TOOLCHAIN_PATH" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra path" >&5
+$as_echo_n "checking for extra path... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $EXTRA_PATH" >&5
+$as_echo "$EXTRA_PATH" >&6; }
+
+
 # To properly create a configuration name, we need to have the OpenJDK target
 # and options (variants and debug level) parsed.
 
@@ -16082,10 +16240,10 @@
     fi
 
     if test "x$FOUND_MAKE" = x; then
-      if test "x$TOOLS_DIR" != x; then
-        # We have a tools-dir, check that as well before giving up.
+      if test "x$TOOLCHAIN_PATH" != x; then
+        # We have a toolchain path, check that as well before giving up.
         OLD_PATH=$PATH
-        PATH=$TOOLS_DIR:$PATH
+        PATH=$TOOLCHAIN_PATH:$PATH
         for ac_prog in gmake
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -27207,47 +27365,62 @@
     # Lets extract the variables that are set by vcvarsall.bat/vsvars32.bat/vsvars64.bat
     { $as_echo "$as_me:${as_lineno-$LINENO}: Trying to extract Visual Studio environment variables" >&5
 $as_echo "$as_me: Trying to extract Visual Studio environment variables" >&6;}
-    cd $OUTPUT_ROOT
-    # FIXME: The code betweeen ---- was inlined from a separate script and is not properly adapted
-    # to autoconf standards.
-
-    #----
-
-    # Cannot use the VS10 setup script directly (since it only updates the DOS subshell environment)
-    # but calculate the difference in Cygwin environment before/after running it and then
-    # apply the diff.
-
-    if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then
-      _vs10varsall=`cygpath -a -m -s "$VS_ENV_CMD"`
-      _dosvs10varsall=`cygpath -a -w -s $_vs10varsall`
-      _dosbash=`cygpath -a -w -s \`which bash\`.*`
-    else
-      _dosvs10varsall=`cmd //c echo $VS_ENV_CMD`
-      _dosbash=`cmd //c echo \`which bash\``
-    fi
-
-    # generate the set of exported vars before/after the vs10 setup
-    $ECHO "@echo off"                                           >  localdevenvtmp.bat
-    $ECHO "$_dosbash -c \"export -p\" > localdevenvtmp.export0" >> localdevenvtmp.bat
-    $ECHO "call $_dosvs10varsall $VS_ENV_ARGS"                  >> localdevenvtmp.bat
-    $ECHO "$_dosbash -c \"export -p\" > localdevenvtmp.export1" >> localdevenvtmp.bat
+
+    # We need to create a couple of temporary files.
+    VS_ENV_TMP_DIR="$OUTPUT_ROOT/vs-env"
+    $MKDIR -p $VS_ENV_TMP_DIR
+
+    # Cannot use the VS10 setup script directly (since it only updates the DOS subshell environment).
+    # Instead create a shell script which will set the relevant variables when run.
+    WINPATH_VS_ENV_CMD="$VS_ENV_CMD"
+
+  unix_path="$WINPATH_VS_ENV_CMD"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    windows_path=`$CYGPATH -m "$unix_path"`
+    WINPATH_VS_ENV_CMD="$windows_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    windows_path=`cmd //c echo $unix_path`
+    WINPATH_VS_ENV_CMD="$windows_path"
+  fi
+
+    WINPATH_BASH="$BASH"
+
+  unix_path="$WINPATH_BASH"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    windows_path=`$CYGPATH -m "$unix_path"`
+    WINPATH_BASH="$windows_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    windows_path=`cmd //c echo $unix_path`
+    WINPATH_BASH="$windows_path"
+  fi
+
+
+    # Generate a DOS batch file which runs $VS_ENV_CMD, and then creates a shell
+    # script (executable by bash) that will setup the important variables.
+    EXTRACT_VC_ENV_BAT_FILE="$VS_ENV_TMP_DIR/extract-vs-env.bat"
+    $ECHO "@echo off" >  $EXTRACT_VC_ENV_BAT_FILE
+    # This will end up something like:
+    # call C:/progra~2/micros~2.0/vc/bin/amd64/vcvars64.bat
+    $ECHO "call $WINPATH_VS_ENV_CMD $VS_ENV_ARGS" >> $EXTRACT_VC_ENV_BAT_FILE
+    # These will end up something like:
+    # C:/CygWin/bin/bash -c 'echo VS_PATH=\"$PATH\" > localdevenv.sh
+    # The trailing space for everyone except PATH is no typo, but is needed due
+    # to trailing \ in the Windows paths. These will be stripped later.
+    $ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
 
     # Now execute the newly created bat file.
-    # The | cat is to stop SetEnv.Cmd to mess with system colors on msys
-    cmd /c localdevenvtmp.bat | cat
-
-    # apply the diff (less some non-vs10 vars named by "!")
-    $SORT localdevenvtmp.export0 | $GREP -v "!" > localdevenvtmp.export0.sort
-    $SORT localdevenvtmp.export1 | $GREP -v "!" > localdevenvtmp.export1.sort
-    $COMM -1 -3 localdevenvtmp.export0.sort localdevenvtmp.export1.sort > localdevenv.sh
-
-    # cleanup
-    $RM localdevenvtmp*
-    #----
+    # The | cat is to stop SetEnv.Cmd to mess with system colors on msys.
+    # Change directory so we don't need to mess with Windows paths in redirects.
+    cd $VS_ENV_TMP_DIR
+    cmd /c extract-vs-env.bat | $CAT
     cd $CURDIR
-    if test ! -s $OUTPUT_ROOT/localdevenv.sh; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+    if test ! -s $VS_ENV_TMP_DIR/set-vs-env.sh; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: Could not succesfully extract the envionment variables needed for the VS setup." >&5
 $as_echo "$as_me: Could not succesfully extract the envionment variables needed for the VS setup." >&6;}
       { $as_echo "$as_me:${as_lineno-$LINENO}: Try setting --with-tools-dir to the VC/bin directory within the VS installation" >&5
@@ -27261,31 +27434,37 @@
     # the configure script to find and run the compiler in the proper way.
     { $as_echo "$as_me:${as_lineno-$LINENO}: Setting extracted environment variables" >&5
 $as_echo "$as_me: Setting extracted environment variables" >&6;}
-    . $OUTPUT_ROOT/localdevenv.sh
+    . $VS_ENV_TMP_DIR/set-vs-env.sh
+    # Now we have VS_PATH, VS_INCLUDE, VS_LIB. For further checking, we
+    # also define VCINSTALLDIR, WindowsSdkDir and WINDOWSSDKDIR.
   else
     # We did not find a vsvars bat file, let's hope we are run from a VS command prompt.
     { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot locate a valid Visual Studio installation, checking current environment" >&5
 $as_echo "$as_me: Cannot locate a valid Visual Studio installation, checking current environment" >&6;}
   fi
 
-  # At this point, we should have corrent variables in the environment, or we can't continue.
+  # At this point, we should have correct variables in the environment, or we can't continue.
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Visual Studio variables" >&5
 $as_echo_n "checking for Visual Studio variables... " >&6; }
 
   if test "x$VCINSTALLDIR" != x || test "x$WindowsSDKDir" != x || test "x$WINDOWSSDKDIR" != x; then
-    if test "x$INCLUDE" = x || test "x$LIB" = x; then
+    if test "x$VS_INCLUDE" = x || test "x$VS_LIB" = x; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: present but broken" >&5
 $as_echo "present but broken" >&6; }
       as_fn_error $? "Your VC command prompt seems broken, INCLUDE and/or LIB is missing." "$LINENO" 5
     else
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
 $as_echo "ok" >&6; }
-      # Remove any trailing \ from INCLUDE and LIB to avoid trouble in spec.gmk.
-      VS_INCLUDE=`$ECHO "$INCLUDE" | $SED 's/\\\\$//'`
-      VS_LIB=`$ECHO "$LIB" | $SED 's/\\\\$//'`
-      # Remove any paths containing # (typically F#) as that messes up make
-      PATH=`$ECHO "$PATH" | $SED 's/[^:#]*#[^:]*://g'`
-      VS_PATH="$PATH"
+      # Remove any trailing "\" and " " from the variables.
+      VS_INCLUDE=`$ECHO "$VS_INCLUDE" | $SED 's/\\\\* *$//'`
+      VS_LIB=`$ECHO "$VS_LIB" | $SED 's/\\\\* *$//'`
+      VCINSTALLDIR=`$ECHO "$VCINSTALLDIR" | $SED 's/\\\\* *$//'`
+      WindowsSDKDir=`$ECHO "$WindowsSDKDir" | $SED 's/\\\\* *$//'`
+      WINDOWSSDKDIR=`$ECHO "$WINDOWSSDKDIR" | $SED 's/\\\\* *$//'`
+      # Remove any paths containing # (typically F#) as that messes up make. This
+      # is needed if visual studio was installed with F# support.
+      VS_PATH=`$ECHO "$VS_PATH" | $SED 's/[^:#]*#[^:]*://g'`
+
 
 
 
@@ -27310,6 +27489,12 @@
     as_fn_error $? "Cannot continue" "$LINENO" 5
   fi
 
+    # Reset path to VS_PATH. It will include everything that was on PATH at the time we
+    # ran TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV.
+    PATH="$VS_PATH"
+    # The microsoft toolchain also requires INCLUDE and LIB to be set.
+    export INCLUDE="$VS_INCLUDE"
+    export LIB="$VS_LIB"
   fi
 
   # autoconf magic only relies on PATH, so update it if tools dir is specified
@@ -27323,169 +27508,11 @@
     PATH="/usr/ccs/bin:$PATH"
   fi
 
-  # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to
+  # Finally add TOOLCHAIN_PATH at the beginning, to allow --with-tools-dir to
   # override all other locations.
-  if test "x$TOOLS_DIR" != x; then
-    PATH=$TOOLS_DIR:$PATH
-  fi
-
-  # If a devkit is found on the builddeps server, then prepend its path to the
-  # PATH variable. If there are cross compilers available in the devkit, these
-  # will be found by AC_PROG_CC et al.
-  DEVKIT=
-
-
-  if test "x$with_builddeps_server" != x || test "x$with_builddeps_conf" != x; then
-    # Source the builddeps file again, to make sure it uses the latest variables!
-    . $builddepsfile
-    # Look for a target and build machine specific resource!
-    eval resource=\${builddep_devkit_BUILD_${rewritten_build_var}_TARGET_${rewritten_target_var}}
-    if test "x$resource" = x; then
-      # Ok, lets instead look for a target specific resource
-      eval resource=\${builddep_devkit_TARGET_${rewritten_target_var}}
-    fi
-    if test "x$resource" = x; then
-      # Ok, lets instead look for a build specific resource
-      eval resource=\${builddep_devkit_BUILD_${rewritten_build_var}}
-    fi
-    if test "x$resource" = x; then
-      # Ok, lets instead look for a generic resource
-      # (The devkit comes from M4 and not the shell, thus no need for eval here.)
-      resource=${builddep_devkit}
-    fi
-    if test "x$resource" != x; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: Using builddeps $resource for devkit" >&5
-$as_echo "$as_me: Using builddeps $resource for devkit" >&6;}
-      # If the resource in the builddeps.conf file is an existing directory,
-      # for example /java/linux/cups
-      if test -d ${resource}; then
-        depdir=${resource}
-      else
-
-  # devkit is for example mymodule
-  # $resource is for example libs/general/libmymod_1_2_3.zip
-  # $with_builddeps_server is for example ftp://mybuilddeps.myserver.com/builddeps
-  # $with_builddeps_dir is for example /localhome/builddeps
-  # depdir is the name of the variable into which we store the depdir, eg MYMOD
-  # Will download ftp://mybuilddeps.myserver.com/builddeps/libs/general/libmymod_1_2_3.zip and
-  # unzip into the directory: /localhome/builddeps/libmymod_1_2_3
-  filename=`basename $resource`
-  filebase=`echo $filename | sed 's/\.[^\.]*$//'`
-  filebase=${filename%%.*}
-  extension=${filename#*.}
-  installdir=$with_builddeps_dir/$filebase
-  if test ! -f $installdir/$filename.unpacked; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Downloading build dependency devkit from $with_builddeps_server/$resource and installing into $installdir" >&5
-$as_echo "$as_me: Downloading build dependency devkit from $with_builddeps_server/$resource and installing into $installdir" >&6;}
-    if test ! -d $installdir; then
-      mkdir -p $installdir
-    fi
-    if test ! -d $installdir; then
-      as_fn_error $? "Could not create directory $installdir" "$LINENO" 5
-    fi
-    tmpfile=`mktemp $installdir/devkit.XXXXXXXXX`
-    touch $tmpfile
-    if test ! -f $tmpfile; then
-      as_fn_error $? "Could not create files in directory $installdir" "$LINENO" 5
-    fi
-
-  # $with_builddeps_server/$resource  is the ftp://abuilddeps.server.com/libs/cups.zip
-  # $tmpfile is the local file name for the downloaded file.
-  VALID_TOOL=no
-  if test "x$BDEPS_FTP" = xwget; then
-    VALID_TOOL=yes
-    wget -O $tmpfile $with_builddeps_server/$resource
-  fi
-  if test "x$BDEPS_FTP" = xlftp; then
-    VALID_TOOL=yes
-    lftp -c "get $with_builddeps_server/$resource  -o $tmpfile"
-  fi
-  if test "x$BDEPS_FTP" = xftp; then
-    VALID_TOOL=yes
-    FTPSERVER=`echo $with_builddeps_server/$resource  | cut -f 3 -d '/'`
-    FTPPATH=`echo $with_builddeps_server/$resource  | cut -f 4- -d '/'`
-    FTPUSERPWD=${FTPSERVER%%@*}
-    if test "x$FTPSERVER" != "x$FTPUSERPWD"; then
-      FTPUSER=${userpwd%%:*}
-      FTPPWD=${userpwd#*@}
-      FTPSERVER=${FTPSERVER#*@}
-    else
-      FTPUSER=ftp
-      FTPPWD=ftp
-    fi
-    # the "pass" command does not work on some
-    # ftp clients (read ftp.exe) but if it works,
-    # passive mode is better!
-    ( \
-        echo "user $FTPUSER $FTPPWD"        ; \
-        echo "pass"                         ; \
-        echo "bin"                          ; \
-        echo "get $FTPPATH $tmpfile"              ; \
-    ) | ftp -in $FTPSERVER
-  fi
-  if test "x$VALID_TOOL" != xyes; then
-    as_fn_error $? "I do not know how to use the tool: $BDEPS_FTP" "$LINENO" 5
-  fi
-
-    mv $tmpfile $installdir/$filename
-    if test ! -s $installdir/$filename; then
-      as_fn_error $? "Could not download $with_builddeps_server/$resource" "$LINENO" 5
-    fi
-    case "$extension" in
-      zip)  echo "Unzipping $installdir/$filename..."
-        (cd $installdir ; rm -f $installdir/$filename.unpacked ; $BDEPS_UNZIP $installdir/$filename > /dev/null && touch $installdir/$filename.unpacked)
-        ;;
-      tar.gz) echo "Untaring $installdir/$filename..."
-        (cd $installdir ; rm -f $installdir/$filename.unpacked ; tar xzf $installdir/$filename && touch $installdir/$filename.unpacked)
-        ;;
-      tgz) echo "Untaring $installdir/$filename..."
-        (cd $installdir ; rm -f $installdir/$filename.unpacked ; tar xzf $installdir/$filename && touch $installdir/$filename.unpacked)
-        ;;
-      *) as_fn_error $? "Cannot handle build depency archive with extension $extension" "$LINENO" 5
-        ;;
-    esac
-  fi
-  if test -f $installdir/$filename.unpacked; then
-    depdir=$installdir
-  fi
-
-      fi
-      # Source the builddeps file again, because in the previous command, the depdir
-      # was updated to point at the current build dependency install directory.
-      . $builddepsfile
-      # Now extract variables from the builddeps.conf files.
-      theroot=${builddep_devkit_ROOT}
-      thecflags=${builddep_devkit_CFLAGS}
-      thelibs=${builddep_devkit_LIBS}
-      if test "x$depdir" = x; then
-        as_fn_error $? "Could not download build dependency devkit" "$LINENO" 5
-      fi
-      DEVKIT=$depdir
-      if test "x$theroot" != x; then
-        DEVKIT="$theroot"
-      fi
-      if test "x$thecflags" != x; then
-        DEVKIT_CFLAGS="$thecflags"
-      fi
-      if test "x$thelibs" != x; then
-        DEVKIT_LIBS="$thelibs"
-      fi
-
-        # Found devkit
-        PATH="$DEVKIT/bin:$PATH"
-        SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
-        if test "x$x_includes" = "xNONE"; then
-          x_includes="$SYS_ROOT/usr/include/X11"
-        fi
-        if test "x$x_libraries" = "xNONE"; then
-          x_libraries="$SYS_ROOT/usr/lib"
-        fi
-
-
-    fi
-
-  fi
-
+  if test "x$TOOLCHAIN_PATH" != x; then
+    PATH=$TOOLCHAIN_PATH:$PATH
+  fi
 
 
   #
@@ -27569,59 +27596,59 @@
     # used.
 
     CC=
-    # If TOOLS_DIR is set, check for all compiler names in there first
+    # If TOOLCHAIN_PATH is set, check for all compiler names in there first
     # before checking the rest of the PATH.
     # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION
     # step, this should not be necessary.
-    if test -n "$TOOLS_DIR"; then
+    if test -n "$TOOLCHAIN_PATH"; then
       PATH_save="$PATH"
-      PATH="$TOOLS_DIR"
+      PATH="$TOOLCHAIN_PATH"
       for ac_prog in $SEARCH_LIST
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_TOOLS_DIR_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $TOOLS_DIR_CC in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_TOOLS_DIR_CC="$TOOLS_DIR_CC" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_TOOLS_DIR_CC="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-TOOLS_DIR_CC=$ac_cv_path_TOOLS_DIR_CC
-if test -n "$TOOLS_DIR_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLS_DIR_CC" >&5
-$as_echo "$TOOLS_DIR_CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$TOOLS_DIR_CC" && break
-done
-
-      CC=$TOOLS_DIR_CC
+if ${ac_cv_path_TOOLCHAIN_PATH_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $TOOLCHAIN_PATH_CC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_TOOLCHAIN_PATH_CC="$TOOLCHAIN_PATH_CC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_TOOLCHAIN_PATH_CC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+TOOLCHAIN_PATH_CC=$ac_cv_path_TOOLCHAIN_PATH_CC
+if test -n "$TOOLCHAIN_PATH_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLCHAIN_PATH_CC" >&5
+$as_echo "$TOOLCHAIN_PATH_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$TOOLCHAIN_PATH_CC" && break
+done
+
+      CC=$TOOLCHAIN_PATH_CC
       PATH="$PATH_save"
     fi
 
@@ -29275,59 +29302,59 @@
     # used.
 
     CXX=
-    # If TOOLS_DIR is set, check for all compiler names in there first
+    # If TOOLCHAIN_PATH is set, check for all compiler names in there first
     # before checking the rest of the PATH.
     # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION
     # step, this should not be necessary.
-    if test -n "$TOOLS_DIR"; then
+    if test -n "$TOOLCHAIN_PATH"; then
       PATH_save="$PATH"
-      PATH="$TOOLS_DIR"
+      PATH="$TOOLCHAIN_PATH"
       for ac_prog in $SEARCH_LIST
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_TOOLS_DIR_CXX+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $TOOLS_DIR_CXX in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_TOOLS_DIR_CXX="$TOOLS_DIR_CXX" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_TOOLS_DIR_CXX="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-TOOLS_DIR_CXX=$ac_cv_path_TOOLS_DIR_CXX
-if test -n "$TOOLS_DIR_CXX"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLS_DIR_CXX" >&5
-$as_echo "$TOOLS_DIR_CXX" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$TOOLS_DIR_CXX" && break
-done
-
-      CXX=$TOOLS_DIR_CXX
+if ${ac_cv_path_TOOLCHAIN_PATH_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $TOOLCHAIN_PATH_CXX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_TOOLCHAIN_PATH_CXX="$TOOLCHAIN_PATH_CXX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_TOOLCHAIN_PATH_CXX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+TOOLCHAIN_PATH_CXX=$ac_cv_path_TOOLCHAIN_PATH_CXX
+if test -n "$TOOLCHAIN_PATH_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLCHAIN_PATH_CXX" >&5
+$as_echo "$TOOLCHAIN_PATH_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$TOOLCHAIN_PATH_CXX" && break
+done
+
+      CXX=$TOOLCHAIN_PATH_CXX
       PATH="$PATH_save"
     fi
 
@@ -40735,6 +40762,32 @@
     CCXXFLAGS="$CCXXFLAGS -nologo"
   fi
 
+  if test "x$SYSROOT" != "x"; then
+    if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
+      if test "x$OPENJDK_TARGET_OS" = xsolaris; then
+        # Solaris Studio does not have a concept of sysroot. Instead we must
+        # make sure the default include and lib dirs are appended to each
+        # compile and link command line.
+        SYSROOT_CFLAGS="-I$SYSROOT/usr/include"
+        SYSROOT_LDFLAGS="-L$SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
+            -L$SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
+            -L$SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
+      fi
+    elif test "x$TOOLCHAIN_TYPE" = xgcc; then
+      SYSROOT_CFLAGS="--sysroot=\"$SYSROOT\""
+      SYSROOT_LDFLAGS="--sysroot=\"$SYSROOT\""
+    elif test "x$TOOLCHAIN_TYPE" = xclang; then
+      SYSROOT_CFLAGS="-isysroot \"$SYSROOT\""
+      SYSROOT_LDFLAGS="-isysroot \"$SYSROOT\""
+    fi
+    # Propagate the sysroot args to hotspot
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $SYSROOT_CFLAGS"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $SYSROOT_CFLAGS"
+    LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $SYSROOT_LDFLAGS"
+  fi
+
+
+
 
 # FIXME: Currently we must test this after toolchain but before flags. Fix!
 
@@ -41583,9 +41636,9 @@
   LDFLAGS_JDK="${LDFLAGS_JDK} $with_extra_ldflags"
 
   # Hotspot needs these set in their legacy form
-  LEGACY_EXTRA_CFLAGS=$with_extra_cflags
-  LEGACY_EXTRA_CXXFLAGS=$with_extra_cxxflags
-  LEGACY_EXTRA_LDFLAGS=$with_extra_ldflags
+  LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $with_extra_cflags"
+  LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $with_extra_cxxflags"
+  LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $with_extra_ldflags"
 
 
 
@@ -41683,7 +41736,13 @@
       CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_LITTLE_ENDIAN"
     fi
   else
-    CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN"
+    # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they
+    # are defined in the system?
+    if test "x$OPENJDK_TARGET_OS" = xsolaris; then
+      CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN="
+    else
+      CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN"
+    fi
   fi
 
   # Setup target OS define. Use OS target name but in upper case.
@@ -41989,6 +42048,22 @@
 
 
 
+  case "${TOOLCHAIN_TYPE}" in
+    microsoft)
+      CFLAGS_WARNINGS_ARE_ERRORS="/WX"
+      ;;
+    solstudio)
+      CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all"
+      ;;
+    gcc)
+      CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
+      ;;
+    clang)
+      CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
+      ;;
+  esac
+
+
 
 # Setup debug symbols (need objcopy from the toolchain for that)
 
@@ -42230,21 +42305,23 @@
   # Check if the user has specified sysroot, but not --x-includes or --x-libraries.
   # Make a simple check for the libraries at the sysroot, and setup --x-includes and
   # --x-libraries for the sysroot, if that seems to be correct.
-  if test "x$SYS_ROOT" != "x/"; then
-    if test "x$x_includes" = xNONE; then
-      if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then
-        x_includes="$SYS_ROOT/usr/X11R6/include"
-      elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then
-        x_includes="$SYS_ROOT/usr/include"
-      fi
-    fi
-    if test "x$x_libraries" = xNONE; then
-      if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then
-        x_libraries="$SYS_ROOT/usr/X11R6/lib"
-      elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
-        x_libraries="$SYS_ROOT/usr/lib64"
-      elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then
-        x_libraries="$SYS_ROOT/usr/lib"
+  if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
+    if test "x$SYSROOT" != "x"; then
+      if test "x$x_includes" = xNONE; then
+        if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
+          x_includes="$SYSROOT/usr/X11R6/include"
+        elif test -f "$SYSROOT/usr/include/X11/Xlib.h"; then
+          x_includes="$SYSROOT/usr/include"
+        fi
+      fi
+      if test "x$x_libraries" = xNONE; then
+        if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
+          x_libraries="$SYSROOT/usr/X11R6/lib"
+        elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+          x_libraries="$SYSROOT/usr/lib64"
+        elif test -f "$SYSROOT/usr/lib/libX11.so"; then
+          x_libraries="$SYSROOT/usr/lib"
+        fi
       fi
     fi
   fi
@@ -42976,9 +43053,12 @@
 
   if test "x$OPENJDK_TARGET_OS" = xsolaris; then
     OPENWIN_HOME="/usr/openwin"
-  fi
-
-
+    X_CFLAGS="-I$SYSROOT$OPENWIN_HOME/include -I$SYSROOT$OPENWIN_HOME/include/X11/extensions"
+    X_LIBS="-L$SYSROOT$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -L$SYSROOT$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -R$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR"
+  fi
 
   #
   # Weird Sol10 something check...TODO change to try compile
@@ -43278,14 +43358,14 @@
       # package installation locations.
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cups headers" >&5
 $as_echo_n "checking for cups headers... " >&6; }
-      if test -s /opt/sfw/cups/include/cups/cups.h; then
+      if test -s $SYSROOT/opt/sfw/cups/include/cups/cups.h; then
         # An SFW package seems to be installed!
         CUPS_FOUND=yes
-        CUPS_CFLAGS="-I/opt/sfw/cups/include"
-      elif test -s /opt/csw/include/cups/cups.h; then
+        CUPS_CFLAGS="-I$SYSROOT/opt/sfw/cups/include"
+      elif test -s $SYSROOT/opt/csw/include/cups/cups.h; then
         # A CSW package seems to be installed!
         CUPS_FOUND=yes
-        CUPS_CFLAGS="-I/opt/csw/include"
+        CUPS_CFLAGS="-I$SYSROOT/opt/csw/include"
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CUPS_FOUND" >&5
 $as_echo "$CUPS_FOUND" >&6; }
@@ -43878,9 +43958,11 @@
         fi
       fi
 
-      if test "x$FOUND_FREETYPE" != xyes; then
-        # Check modules using pkg-config, but only if we have it (ugly output results otherwise)
-        if test "x$PKG_CONFIG" != x; then
+      # If we have a sysroot, assume that's where we are supposed to look and skip pkg-config.
+      if test "x$SYSROOT" = x; then
+        if test "x$FOUND_FREETYPE" != xyes; then
+          # Check modules using pkg-config, but only if we have it (ugly output results otherwise)
+          if test "x$PKG_CONFIG" != x; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FREETYPE" >&5
@@ -43948,23 +44030,24 @@
 $as_echo "yes" >&6; }
 	FOUND_FREETYPE=yes
 fi
-          if test "x$FOUND_FREETYPE" = xyes; then
-            # On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
-            FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
-            # 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
-            if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64; then
-              FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
-            fi
-            # BDEPS_CHECK_MODULE will set FREETYPE_CFLAGS and _LIBS, but we don't get a lib path for bundling.
-            if test "x$BUNDLE_FREETYPE" = xyes; then
-              { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype using pkg-config, but ignoring since we can not bundle that" >&5
+            if test "x$FOUND_FREETYPE" = xyes; then
+              # On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
+              FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
+              # 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
+              if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64; then
+                FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
+              fi
+              # BDEPS_CHECK_MODULE will set FREETYPE_CFLAGS and _LIBS, but we don't get a lib path for bundling.
+              if test "x$BUNDLE_FREETYPE" = xyes; then
+                { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype using pkg-config, but ignoring since we can not bundle that" >&5
 $as_echo "$as_me: Found freetype using pkg-config, but ignoring since we can not bundle that" >&6;}
-              FOUND_FREETYPE=no
-            else
-              { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype" >&5
+                FOUND_FREETYPE=no
+              else
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype" >&5
 $as_echo_n "checking for freetype... " >&6; }
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (using pkg-config)" >&5
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (using pkg-config)" >&5
 $as_echo "yes (using pkg-config)" >&6; }
+              fi
             fi
           fi
         fi
@@ -44578,12 +44661,7 @@
 
           fi
         else
-          if test "x$SYS_ROOT" = "x/"; then
-            FREETYPE_ROOT=
-          else
-            FREETYPE_ROOT="$SYS_ROOT"
-          fi
-          FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr"
+          FREETYPE_BASE_DIR="$SYSROOT/usr"
 
   POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
   POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib"
@@ -44876,7 +44954,7 @@
 
 
           if test "x$FOUND_FREETYPE" != xyes; then
-            FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr/X11"
+            FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
 
   POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
   POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib"
@@ -45170,7 +45248,301 @@
           fi
 
           if test "x$FOUND_FREETYPE" != xyes; then
-            FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr"
+            FREETYPE_BASE_DIR="$SYSROOT/usr/sfw"
+
+  POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+  POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib"
+  METHOD="well-known location"
+
+  # First check if the files exists.
+  if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+    # We found an arbitrary include file. That's a good sign.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+    FOUND_FREETYPE=yes
+
+    FREETYPE_LIB_NAME="${LIBRARY_PREFIX}freetype${SHARED_LIBRARY_SUFFIX}"
+    if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+      FOUND_FREETYPE=no
+    else
+      if test "x$OPENJDK_TARGET_OS" = xwindows; then
+        # On Windows, we will need both .lib and .dll file.
+        if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/freetype.lib"; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;}
+          FOUND_FREETYPE=no
+        fi
+      elif test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64 && test -s "$POTENTIAL_FREETYPE_LIB_PATH/amd64/$FREETYPE_LIB_NAME"; then
+        # On solaris-x86_86, default is (normally) PATH/lib/amd64. Update our guess!
+        POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH/amd64"
+      fi
+    fi
+  fi
+
+  if test "x$FOUND_FREETYPE" = xyes; then
+
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-stile (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+  else
+    # We're on a posix platform. Hooray! :)
+    path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+    has_space=`$ECHO "$path" | $GREP " "`
+    if test "x$has_space" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+    fi
+
+    # Use eval to expand a potential ~
+    eval path="$path"
+    if test ! -f "$path" && test ! -d "$path"; then
+      as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+    fi
+
+    POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-stile (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+  else
+    # We're on a posix platform. Hooray! :)
+    path="$POTENTIAL_FREETYPE_LIB_PATH"
+    has_space=`$ECHO "$path" | $GREP " "`
+    if test "x$has_space" != x; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+      as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+    fi
+
+    # Use eval to expand a potential ~
+    eval path="$path"
+    if test ! -f "$path" && test ! -d "$path"; then
+      as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+    fi
+
+    POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+  fi
+
+
+    FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+    FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+  fi
+
+          fi
+
+          if test "x$FOUND_FREETYPE" != xyes; then
+            FREETYPE_BASE_DIR="$SYSROOT/usr"
             if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
 
   POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
@@ -46646,7 +47018,9 @@
   fi
 
     fi
-    if test "x$ALSA_FOUND" = xno; then
+    # Do not try pkg-config if we have a sysroot set.
+    if test "x$SYSROOT" = x; then
+      if test "x$ALSA_FOUND" = xno; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5
@@ -46714,6 +47088,7 @@
 $as_echo "yes" >&6; }
 	ALSA_FOUND=yes
 fi
+      fi
     fi
     if test "x$ALSA_FOUND" = xno; then
       for ac_header in alsa/asoundlib.h
@@ -47593,7 +47968,7 @@
 
   # libCrun is the c++ runtime-library with SunStudio (roughly the equivalent of gcc's libstdc++.so)
   if test "x$TOOLCHAIN_TYPE" = xsolstudio && test "x$LIBCXX" = x; then
-    LIBCXX="/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1"
+    LIBCXX="${SYSROOT}/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1"
   fi
 
   # TODO better (platform agnostic) test
@@ -48518,8 +48893,8 @@
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
     OLD_PATH="$PATH"
-    if test "x$TOOLS_DIR" != x; then
-      PATH=$TOOLS_DIR:$PATH
+    if test "x$TOOLCHAIN_PATH" != x; then
+      PATH=$TOOLCHAIN_PATH:$PATH
     fi
 
 
@@ -50203,6 +50578,7 @@
   printf "\n"
   printf "Configuration summary:\n"
   printf "* Debug level:    $DEBUG_LEVEL\n"
+  printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n"
   printf "* JDK variant:    $JDK_VARIANT\n"
   printf "* JVM variants:   $with_jvm_variants\n"
   printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n"
--- a/common/autoconf/help.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/help.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -200,6 +200,7 @@
   printf "\n"
   printf "Configuration summary:\n"
   printf "* Debug level:    $DEBUG_LEVEL\n"
+  printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n"
   printf "* JDK variant:    $JDK_VARIANT\n"
   printf "* JVM variants:   $with_jvm_variants\n"
   printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n"
--- a/common/autoconf/jdk-options.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/jdk-options.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -176,6 +176,7 @@
   #
   # Set the debug level
   #    release: no debug information, all optimizations, no asserts.
+  #    optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
   #    fastdebug: debug information (-g), all optimizations, all asserts
   #    slowdebug: debug information (-g), no optimizations, all asserts
   #
@@ -189,7 +190,7 @@
       ], [ENABLE_DEBUG="no"])
 
   AC_ARG_WITH([debug-level], [AS_HELP_STRING([--with-debug-level],
-      [set the debug level (release, fastdebug, slowdebug) @<:@release@:>@])],
+      [set the debug level (release, fastdebug, slowdebug, optimized (HotSpot build only)) @<:@release@:>@])],
       [
         DEBUG_LEVEL="${withval}"
         if test "x$ENABLE_DEBUG" = xyes; then
@@ -199,6 +200,7 @@
   AC_MSG_RESULT([$DEBUG_LEVEL])
 
   if test "x$DEBUG_LEVEL" != xrelease && \
+      test "x$DEBUG_LEVEL" != xoptimized && \
       test "x$DEBUG_LEVEL" != xfastdebug && \
       test "x$DEBUG_LEVEL" != xslowdebug; then
     AC_MSG_ERROR([Allowed debug levels are: release, fastdebug and slowdebug])
@@ -235,8 +237,30 @@
       HOTSPOT_DEBUG_LEVEL="jvmg"
       HOTSPOT_EXPORT="debug"
       ;;
+    optimized )
+      VARIANT="OPT"
+      FASTDEBUG="false"
+      DEBUG_CLASSFILES="false"
+      BUILD_VARIANT_RELEASE="-optimized"
+      HOTSPOT_DEBUG_LEVEL="optimized"
+      HOTSPOT_EXPORT="optimized"
+      ;;
   esac
 
+  # The debug level 'optimized' is a little special because it is currently only
+  # applicable to the HotSpot build where it means to build a completely
+  # optimized version of the VM without any debugging code (like for the
+  # 'release' debug level which is called 'product' in the HotSpot build) but
+  # with the exception that it can contain additional code which is otherwise
+  # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to
+  # test new and/or experimental features which are not intended for customer
+  # shipment. Because these new features need to be tested and benchmarked in
+  # real world scenarios, we want to build the containing JDK at the 'release'
+  # debug level.
+  if test "x$DEBUG_LEVEL" = xoptimized; then
+    DEBUG_LEVEL="release"
+  fi
+
   #####
   # Generate the legacy makefile targets for hotspot.
   # The hotspot api for selecting the build artifacts, really, needs to be improved.
--- a/common/autoconf/libraries.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/libraries.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -110,21 +110,23 @@
   # Check if the user has specified sysroot, but not --x-includes or --x-libraries.
   # Make a simple check for the libraries at the sysroot, and setup --x-includes and
   # --x-libraries for the sysroot, if that seems to be correct.
-  if test "x$SYS_ROOT" != "x/"; then
-    if test "x$x_includes" = xNONE; then
-      if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then
-        x_includes="$SYS_ROOT/usr/X11R6/include"
-      elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then
-        x_includes="$SYS_ROOT/usr/include"
+  if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
+    if test "x$SYSROOT" != "x"; then
+      if test "x$x_includes" = xNONE; then
+        if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
+          x_includes="$SYSROOT/usr/X11R6/include"
+        elif test -f "$SYSROOT/usr/include/X11/Xlib.h"; then
+          x_includes="$SYSROOT/usr/include"
+        fi
       fi
-    fi
-    if test "x$x_libraries" = xNONE; then
-      if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then
-        x_libraries="$SYS_ROOT/usr/X11R6/lib"
-      elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
-        x_libraries="$SYS_ROOT/usr/lib64"
-      elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then
-        x_libraries="$SYS_ROOT/usr/lib"
+      if test "x$x_libraries" = xNONE; then
+        if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
+          x_libraries="$SYSROOT/usr/X11R6/lib"
+        elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+          x_libraries="$SYSROOT/usr/lib64"
+        elif test -f "$SYSROOT/usr/lib/libX11.so"; then
+          x_libraries="$SYSROOT/usr/lib"
+        fi
       fi
     fi
   fi
@@ -146,9 +148,12 @@
 
   if test "x$OPENJDK_TARGET_OS" = xsolaris; then
     OPENWIN_HOME="/usr/openwin"
+    X_CFLAGS="-I$SYSROOT$OPENWIN_HOME/include -I$SYSROOT$OPENWIN_HOME/include/X11/extensions"
+    X_LIBS="-L$SYSROOT$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -L$SYSROOT$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -R$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
+        -R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR"
   fi
-  AC_SUBST(OPENWIN_HOME)
-
 
   #
   # Weird Sol10 something check...TODO change to try compile
@@ -237,14 +242,14 @@
       # Getting nervous now? Lets poke around for standard Solaris third-party
       # package installation locations.
       AC_MSG_CHECKING([for cups headers])
-      if test -s /opt/sfw/cups/include/cups/cups.h; then
+      if test -s $SYSROOT/opt/sfw/cups/include/cups/cups.h; then
         # An SFW package seems to be installed!
         CUPS_FOUND=yes
-        CUPS_CFLAGS="-I/opt/sfw/cups/include"
-      elif test -s /opt/csw/include/cups/cups.h; then
+        CUPS_CFLAGS="-I$SYSROOT/opt/sfw/cups/include"
+      elif test -s $SYSROOT/opt/csw/include/cups/cups.h; then
         # A CSW package seems to be installed!
         CUPS_FOUND=yes
-        CUPS_CFLAGS="-I/opt/csw/include"
+        CUPS_CFLAGS="-I$SYSROOT/opt/csw/include"
       fi
       AC_MSG_RESULT([$CUPS_FOUND])
     fi
@@ -398,24 +403,27 @@
         fi
       fi
 
-      if test "x$FOUND_FREETYPE" != xyes; then
-        # Check modules using pkg-config, but only if we have it (ugly output results otherwise)
-        if test "x$PKG_CONFIG" != x; then
-          PKG_CHECK_MODULES(FREETYPE, freetype2, [FOUND_FREETYPE=yes], [FOUND_FREETYPE=no])
-          if test "x$FOUND_FREETYPE" = xyes; then
-            # On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
-            FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
-            # 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
-            if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64; then
-              FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
-            fi
-            # BDEPS_CHECK_MODULE will set FREETYPE_CFLAGS and _LIBS, but we don't get a lib path for bundling.
-            if test "x$BUNDLE_FREETYPE" = xyes; then
-              AC_MSG_NOTICE([Found freetype using pkg-config, but ignoring since we can not bundle that])
-              FOUND_FREETYPE=no
-            else
-              AC_MSG_CHECKING([for freetype])
-              AC_MSG_RESULT([yes (using pkg-config)])
+      # If we have a sysroot, assume that's where we are supposed to look and skip pkg-config.
+      if test "x$SYSROOT" = x; then
+        if test "x$FOUND_FREETYPE" != xyes; then
+          # Check modules using pkg-config, but only if we have it (ugly output results otherwise)
+          if test "x$PKG_CONFIG" != x; then
+            PKG_CHECK_MODULES(FREETYPE, freetype2, [FOUND_FREETYPE=yes], [FOUND_FREETYPE=no])
+            if test "x$FOUND_FREETYPE" = xyes; then
+              # On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
+              FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
+              # 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
+              if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64; then
+                FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
+              fi
+              # BDEPS_CHECK_MODULE will set FREETYPE_CFLAGS and _LIBS, but we don't get a lib path for bundling.
+              if test "x$BUNDLE_FREETYPE" = xyes; then
+                AC_MSG_NOTICE([Found freetype using pkg-config, but ignoring since we can not bundle that])
+                FOUND_FREETYPE=no
+              else
+                AC_MSG_CHECKING([for freetype])
+                AC_MSG_RESULT([yes (using pkg-config)])
+              fi
             fi
           fi
         fi
@@ -433,21 +441,21 @@
             LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
           fi
         else
-          if test "x$SYS_ROOT" = "x/"; then
-            FREETYPE_ROOT=
-          else
-            FREETYPE_ROOT="$SYS_ROOT"
-          fi
-          FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr"
+          FREETYPE_BASE_DIR="$SYSROOT/usr"
           LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
 
           if test "x$FOUND_FREETYPE" != xyes; then
-            FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr/X11"
+            FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
             LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
           fi
 
           if test "x$FOUND_FREETYPE" != xyes; then
-            FREETYPE_BASE_DIR="$FREETYPE_ROOT/usr"
+            FREETYPE_BASE_DIR="$SYSROOT/usr/sfw"
+            LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
+          fi
+
+          if test "x$FOUND_FREETYPE" != xyes; then
+            FREETYPE_BASE_DIR="$SYSROOT/usr"
             if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
               LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/x86_64-linux-gnu], [well-known location])
             else
@@ -577,8 +585,11 @@
     if test "x$ALSA_FOUND" = xno; then
       BDEPS_CHECK_MODULE(ALSA, alsa, xxx, [ALSA_FOUND=yes], [ALSA_FOUND=no])
     fi
-    if test "x$ALSA_FOUND" = xno; then
-      PKG_CHECK_MODULES(ALSA, alsa, [ALSA_FOUND=yes], [ALSA_FOUND=no])
+    # Do not try pkg-config if we have a sysroot set.
+    if test "x$SYSROOT" = x; then
+      if test "x$ALSA_FOUND" = xno; then
+        PKG_CHECK_MODULES(ALSA, alsa, [ALSA_FOUND=yes], [ALSA_FOUND=no])
+      fi
     fi
     if test "x$ALSA_FOUND" = xno; then
       AC_CHECK_HEADERS([alsa/asoundlib.h],
@@ -917,7 +928,7 @@
 
   # libCrun is the c++ runtime-library with SunStudio (roughly the equivalent of gcc's libstdc++.so)
   if test "x$TOOLCHAIN_TYPE" = xsolstudio && test "x$LIBCXX" = x; then
-    LIBCXX="/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1"
+    LIBCXX="${SYSROOT}/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1"
   fi
 
   # TODO better (platform agnostic) test
--- a/common/autoconf/platform.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/platform.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -60,6 +60,12 @@
       VAR_CPU_BITS=64
       VAR_CPU_ENDIAN=big
       ;;
+    powerpc64le)
+      VAR_CPU=ppc64
+      VAR_CPU_ARCH=ppc
+      VAR_CPU_BITS=64
+      VAR_CPU_ENDIAN=little
+      ;;
     s390)
       VAR_CPU=s390
       VAR_CPU_ARCH=s390
--- a/common/autoconf/spec.gmk.in	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 19:35:40 2017 +0200
@@ -130,10 +130,8 @@
   export LIB:=@VS_LIB@
 endif
 
-# The sys root where standard headers and libraries are found.
-# Usually not needed since the configure script should have
-# taken it into account already when setting CFLAGS et al.
-SYS_ROOT:=@SYS_ROOT@
+SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
+SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
 
 # Paths to the source code
 ADD_SRC_ROOT:=@ADD_SRC_ROOT@
@@ -294,7 +292,6 @@
 # Necessary additional compiler flags to compile X11
 X_CFLAGS:=@X_CFLAGS@
 X_LIBS:=@X_LIBS@
-OPENWIN_HOME:=@OPENWIN_HOME@
 
 # The lowest required version of macosx to enforce compatiblity for
 MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@
@@ -324,6 +321,8 @@
 C_FLAG_DEPS:=@C_FLAG_DEPS@
 CXX_FLAG_DEPS:=@CXX_FLAG_DEPS@
 
+CFLAGS_WARNINGS_ARE_ERRORS:=@CFLAGS_WARNINGS_ARE_ERRORS@
+
 # Tools that potentially need to be cross compilation aware.
 CC:=@FIXPATH@ @CCACHE@ @CC@
 
--- a/common/autoconf/toolchain.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -189,6 +189,12 @@
   # it for DLL resolution in runtime.
   if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then
     TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV
+    # Reset path to VS_PATH. It will include everything that was on PATH at the time we
+    # ran TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV.
+    PATH="$VS_PATH"
+    # The microsoft toolchain also requires INCLUDE and LIB to be set.
+    export INCLUDE="$VS_INCLUDE"
+    export LIB="$VS_LIB"
   fi
 
   # autoconf magic only relies on PATH, so update it if tools dir is specified
@@ -202,29 +208,11 @@
     PATH="/usr/ccs/bin:$PATH"
   fi
 
-  # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to 
+  # Finally add TOOLCHAIN_PATH at the beginning, to allow --with-tools-dir to 
   # override all other locations.
-  if test "x$TOOLS_DIR" != x; then
-    PATH=$TOOLS_DIR:$PATH
+  if test "x$TOOLCHAIN_PATH" != x; then
+    PATH=$TOOLCHAIN_PATH:$PATH
   fi
-
-  # If a devkit is found on the builddeps server, then prepend its path to the
-  # PATH variable. If there are cross compilers available in the devkit, these
-  # will be found by AC_PROG_CC et al.
-  DEVKIT=
-  BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx,
-      [
-        # Found devkit
-        PATH="$DEVKIT/bin:$PATH"
-        SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
-        if test "x$x_includes" = "xNONE"; then
-          x_includes="$SYS_ROOT/usr/include/X11"
-        fi
-        if test "x$x_libraries" = "xNONE"; then
-          x_libraries="$SYS_ROOT/usr/lib"
-        fi
-      ],
-      [])
 ])
 
 # Restore path, etc
@@ -396,15 +384,15 @@
     # used.
 
     $1=
-    # If TOOLS_DIR is set, check for all compiler names in there first
+    # If TOOLCHAIN_PATH is set, check for all compiler names in there first
     # before checking the rest of the PATH.
     # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION
     # step, this should not be necessary.
-    if test -n "$TOOLS_DIR"; then
+    if test -n "$TOOLCHAIN_PATH"; then
       PATH_save="$PATH"
-      PATH="$TOOLS_DIR"
-      AC_PATH_PROGS(TOOLS_DIR_$1, $SEARCH_LIST)
-      $1=$TOOLS_DIR_$1
+      PATH="$TOOLCHAIN_PATH"
+      AC_PATH_PROGS(TOOLCHAIN_PATH_$1, $SEARCH_LIST)
+      $1=$TOOLCHAIN_PATH_$1
       PATH="$PATH_save"
     fi
 
--- a/common/autoconf/toolchain_windows.m4	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/autoconf/toolchain_windows.m4	Wed Jul 05 19:35:40 2017 +0200
@@ -141,46 +141,44 @@
 
     # Lets extract the variables that are set by vcvarsall.bat/vsvars32.bat/vsvars64.bat
     AC_MSG_NOTICE([Trying to extract Visual Studio environment variables])
-    cd $OUTPUT_ROOT
-    # FIXME: The code betweeen ---- was inlined from a separate script and is not properly adapted
-    # to autoconf standards.
+
+    # We need to create a couple of temporary files.
+    VS_ENV_TMP_DIR="$OUTPUT_ROOT/vs-env"
+    $MKDIR -p $VS_ENV_TMP_DIR
 
-    #----
-
-    # Cannot use the VS10 setup script directly (since it only updates the DOS subshell environment)
-    # but calculate the difference in Cygwin environment before/after running it and then
-    # apply the diff.
+    # Cannot use the VS10 setup script directly (since it only updates the DOS subshell environment).
+    # Instead create a shell script which will set the relevant variables when run.
+    WINPATH_VS_ENV_CMD="$VS_ENV_CMD"
+    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_VS_ENV_CMD])
+    WINPATH_BASH="$BASH"
+    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_BASH])
 
-    if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then
-      _vs10varsall=`cygpath -a -m -s "$VS_ENV_CMD"`
-      _dosvs10varsall=`cygpath -a -w -s $_vs10varsall`
-      _dosbash=`cygpath -a -w -s \`which bash\`.*`
-    else
-      _dosvs10varsall=`cmd //c echo $VS_ENV_CMD`
-      _dosbash=`cmd //c echo \`which bash\``
-    fi
-
-    # generate the set of exported vars before/after the vs10 setup
-    $ECHO "@echo off"                                           >  localdevenvtmp.bat
-    $ECHO "$_dosbash -c \"export -p\" > localdevenvtmp.export0" >> localdevenvtmp.bat
-    $ECHO "call $_dosvs10varsall $VS_ENV_ARGS"                  >> localdevenvtmp.bat
-    $ECHO "$_dosbash -c \"export -p\" > localdevenvtmp.export1" >> localdevenvtmp.bat
+    # Generate a DOS batch file which runs $VS_ENV_CMD, and then creates a shell
+    # script (executable by bash) that will setup the important variables.
+    EXTRACT_VC_ENV_BAT_FILE="$VS_ENV_TMP_DIR/extract-vs-env.bat"
+    $ECHO "@echo off" >  $EXTRACT_VC_ENV_BAT_FILE
+    # This will end up something like:
+    # call C:/progra~2/micros~2.0/vc/bin/amd64/vcvars64.bat
+    $ECHO "call $WINPATH_VS_ENV_CMD $VS_ENV_ARGS" >> $EXTRACT_VC_ENV_BAT_FILE
+    # These will end up something like:
+    # C:/CygWin/bin/bash -c 'echo VS_PATH=\"$PATH\" > localdevenv.sh
+    # The trailing space for everyone except PATH is no typo, but is needed due
+    # to trailing \ in the Windows paths. These will be stripped later.
+    $ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
 
     # Now execute the newly created bat file.
-    # The | cat is to stop SetEnv.Cmd to mess with system colors on msys
-    cmd /c localdevenvtmp.bat | cat
+    # The | cat is to stop SetEnv.Cmd to mess with system colors on msys.
+    # Change directory so we don't need to mess with Windows paths in redirects.
+    cd $VS_ENV_TMP_DIR
+    cmd /c extract-vs-env.bat | $CAT
+    cd $CURDIR
 
-    # apply the diff (less some non-vs10 vars named by "!")
-    $SORT localdevenvtmp.export0 | $GREP -v "!" > localdevenvtmp.export0.sort
-    $SORT localdevenvtmp.export1 | $GREP -v "!" > localdevenvtmp.export1.sort
-    $COMM -1 -3 localdevenvtmp.export0.sort localdevenvtmp.export1.sort > localdevenv.sh
-
-    # cleanup
-    $RM localdevenvtmp*
-    #----
-    cd $CURDIR
-    if test ! -s $OUTPUT_ROOT/localdevenv.sh; then
-      AC_MSG_RESULT([no])
+    if test ! -s $VS_ENV_TMP_DIR/set-vs-env.sh; then
       AC_MSG_NOTICE([Could not succesfully extract the envionment variables needed for the VS setup.])
       AC_MSG_NOTICE([Try setting --with-tools-dir to the VC/bin directory within the VS installation])
       AC_MSG_NOTICE([or run "bash.exe -l" from a VS command prompt and then run configure from there.])
@@ -190,30 +188,36 @@
     # Now set all paths and other env variables. This will allow the rest of
     # the configure script to find and run the compiler in the proper way.
     AC_MSG_NOTICE([Setting extracted environment variables])
-    . $OUTPUT_ROOT/localdevenv.sh
+    . $VS_ENV_TMP_DIR/set-vs-env.sh
+    # Now we have VS_PATH, VS_INCLUDE, VS_LIB. For further checking, we
+    # also define VCINSTALLDIR, WindowsSdkDir and WINDOWSSDKDIR.
   else
     # We did not find a vsvars bat file, let's hope we are run from a VS command prompt.
     AC_MSG_NOTICE([Cannot locate a valid Visual Studio installation, checking current environment])
   fi
 
-  # At this point, we should have corrent variables in the environment, or we can't continue.
+  # At this point, we should have correct variables in the environment, or we can't continue.
   AC_MSG_CHECKING([for Visual Studio variables])
 
   if test "x$VCINSTALLDIR" != x || test "x$WindowsSDKDir" != x || test "x$WINDOWSSDKDIR" != x; then
-    if test "x$INCLUDE" = x || test "x$LIB" = x; then
+    if test "x$VS_INCLUDE" = x || test "x$VS_LIB" = x; then
       AC_MSG_RESULT([present but broken])
       AC_MSG_ERROR([Your VC command prompt seems broken, INCLUDE and/or LIB is missing.])
     else
       AC_MSG_RESULT([ok])
-      # Remove any trailing \ from INCLUDE and LIB to avoid trouble in spec.gmk.
-      VS_INCLUDE=`$ECHO "$INCLUDE" | $SED 's/\\\\$//'`
-      VS_LIB=`$ECHO "$LIB" | $SED 's/\\\\$//'`
-      # Remove any paths containing # (typically F#) as that messes up make
-      PATH=`$ECHO "$PATH" | $SED 's/[[^:#]]*#[^:]*://g'`
-      VS_PATH="$PATH"
+      # Remove any trailing "\" and " " from the variables.
+      VS_INCLUDE=`$ECHO "$VS_INCLUDE" | $SED 's/\\\\* *$//'`
+      VS_LIB=`$ECHO "$VS_LIB" | $SED 's/\\\\* *$//'`
+      VCINSTALLDIR=`$ECHO "$VCINSTALLDIR" | $SED 's/\\\\* *$//'`
+      WindowsSDKDir=`$ECHO "$WindowsSDKDir" | $SED 's/\\\\* *$//'`
+      WINDOWSSDKDIR=`$ECHO "$WINDOWSSDKDIR" | $SED 's/\\\\* *$//'`
+      # Remove any paths containing # (typically F#) as that messes up make. This
+      # is needed if visual studio was installed with F# support.
+      VS_PATH=`$ECHO "$VS_PATH" | $SED 's/[[^:#]]*#[^:]*://g'`
+
+      AC_SUBST(VS_PATH)
       AC_SUBST(VS_INCLUDE)
       AC_SUBST(VS_LIB)
-      AC_SUBST(VS_PATH)
     fi
   else
     AC_MSG_RESULT([not found])
--- a/common/bin/compare.sh	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/bin/compare.sh	Wed Jul 05 19:35:40 2017 +0200
@@ -114,7 +114,7 @@
     fi
     if test "x$SUFFIX" = "xproperties"; then
         # Run through nawk to add possibly missing newline at end of file.
-        $CAT $OTHER_FILE | $NAWK '{ print }' > $OTHER_FILE.cleaned
+        $CAT $OTHER_FILE | $NAWK '{ print }' | LC_ALL=C $SORT > $OTHER_FILE.cleaned
 # Disable this exception since we aren't changing the properties cleaning method yet.
 #        $CAT $OTHER_FILE | $SED -e 's/\([^\\]\):/\1\\:/g' -e  's/\([^\\]\)=/\1\\=/g' -e 's/#.*/#/g' \
 #            | $SED -f "$SRC_ROOT/common/makefiles/support/unicode2x.sed" \
--- a/common/bin/hgforest.sh	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/bin/hgforest.sh	Wed Jul 05 19:35:40 2017 +0200
@@ -24,12 +24,58 @@
 #
 
 # Shell script for a fast parallel forest command
-command="$1"
-pull_extra_base="$2"
+
+global_opts=""
+status_output="/dev/stdout"
+qflag="false"
+vflag="false"
+sflag="false"
+while [ $# -gt 0 ]
+do
+  case $1 in
+    -q | --quiet )
+      qflag="true"
+      global_opts="${global_opts} -q"
+      status_output="/dev/null"
+      ;;
+
+    -v | --verbose )
+      vflag="true"
+      global_opts="${global_opts} -v"
+      ;;
+
+    -s | --sequential )
+      sflag="true"
+      ;;
 
-if [ "" = "$command" ] ; then
-  echo No command to hg supplied!
-  exit 1
+    '--' ) # no more options
+      shift; break
+      ;;
+
+    -*)  # bad option
+      usage
+      ;;
+
+     * )  # non option
+      break
+      ;;
+  esac
+  shift
+done
+
+
+command="$1"; shift
+command_args="$@"
+
+usage() {
+      echo "usage: $0 [-q|--quiet] [-v|--verbose] [-s|--sequential] [--] <command> [commands...]" > ${status_output}
+      exit 1
+}
+
+
+if [ "x" = "x$command" ] ; then
+  echo "ERROR: No command to hg supplied!"
+  usage
 fi
 
 # Clean out the temporary directory that stores the pid files.
@@ -40,17 +86,17 @@
 safe_interrupt () {
   if [ -d ${tmp} ]; then
     if [ "`ls ${tmp}/*.pid`" != "" ]; then
-      echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!"
+      echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!" > ${status_output}
       sleep 1
       # Pipe stderr to dev/null to silence kill, that complains when trying to kill
       # a subprocess that has already exited.
       kill -TERM `cat ${tmp}/*.pid | tr '\n' ' '` 2> /dev/null
       wait
-      echo Interrupt complete!
+      echo "Interrupt complete!" > ${status_output}
     fi
+    rm -f -r ${tmp}
   fi
-  rm -f -r ${tmp}
-  exit 1
+  exit 130
 }
 
 nice_exit () {
@@ -58,39 +104,44 @@
     if [ "`ls ${tmp}`" != "" ]; then
       wait
     fi
+    rm -f -r ${tmp}
   fi
-  rm -f -r ${tmp}
 }
 
 trap 'safe_interrupt' INT QUIT
 trap 'nice_exit' EXIT
 
+subrepos="corba jaxp jaxws langtools jdk hotspot nashorn"
+subrepos_extra="closed jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
+
 # Only look in specific locations for possible forests (avoids long searches)
 pull_default=""
 repos=""
 repos_extra=""
-if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
-  subrepos="corba jaxp jaxws langtools jdk hotspot nashorn"
-  if [ -f .hg/hgrc ] ; then
-    pull_default=`hg paths default`
-    if [ "${pull_default}" = "" ] ; then
-      echo "ERROR: Need initial clone with 'hg paths default' defined"
-      exit 1
-    fi
-  fi
-  if [ "${pull_default}" = "" ] ; then
-    echo "ERROR: Need initial repository to use this script"
+if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then
+  if [ ! -f .hg/hgrc ] ; then
+    echo "ERROR: Need initial repository to use this script" > ${status_output}
     exit 1
   fi
+
+  pull_default=`hg paths default`
+  if [ "${pull_default}" = "" ] ; then
+    echo "ERROR: Need initial clone with 'hg paths default' defined" > ${status_output}
+    exit 1
+  fi
+
   for i in ${subrepos} ; do
     if [ ! -f ${i}/.hg/hgrc ] ; then
       repos="${repos} ${i}"
     fi
   done
-  if [ "${pull_extra_base}" != "" ] ; then
-    subrepos_extra="closed jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
+  if [ "${command_args}" != "" ] ; then
     pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
-    pull_extra="${pull_extra_base}/${pull_default_tail}"
+    if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then
+      echo "ERROR: Need initial clone from non-local source" > ${status_output}
+      exit 1
+    fi
+    pull_extra="${command_args}/${pull_default_tail}"
     for i in ${subrepos_extra} ; do
       if [ ! -f ${i}/.hg/hgrc ] ; then
         repos_extra="${repos_extra} ${i}"
@@ -100,78 +151,115 @@
   at_a_time=2
   # Any repos to deal with?
   if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then
+    echo "No repositories to process." > ${status_output}
     exit
   fi
 else
-  hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null`
-  # Derive repository names from the .hg directory locations
-  for i in ${hgdirs} ; do
-    repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`"
+  for i in . ${subrepos} ${subrepos_extra} ; do
+    if [ -d ${i}/.hg ] ; then
+      repos="${repos} ${i}"
+    fi
   done
+
+  # Any repos to deal with?
+  if [ "${repos}" = "" ] ; then
+    echo "No repositories to process." > ${status_output}
+    exit
+  fi
+
+  # any of the repos locked?
   for i in ${repos} ; do
     if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then
       locked="${i} ${locked}"
     fi
   done
+  if [ "${locked}" != "" ] ; then
+    echo "ERROR: These repositories are locked: ${locked}" > ${status_output}
+    exit 1
+  fi
   at_a_time=8
-  # Any repos to deal with?
-  if [ "${repos}" = "" ] ; then
-    echo "No repositories to process."
-    exit
-  fi
-  if [ "${locked}" != "" ] ; then
-    echo "These repositories are locked: ${locked}"
-    exit
-  fi
 fi
 
 # Echo out what repositories we do a command on.
-echo "# Repositories: ${repos} ${repos_extra}"
-echo
+echo "# Repositories: ${repos} ${repos_extra}" > ${status_output}
+
+if [ "${command}" = "serve" ] ; then
+  # "serve" is run for all the repos.
+  (
+    (
+      (
+        echo "[web]"
+        echo "description = $(basename $(pwd))"
+        echo "allow_push = *"
+        echo "push_ssl = False"
 
-# Run the supplied command on all repos in parallel.
-n=0
-for i in ${repos} ${repos_extra} ; do
-  n=`expr ${n} '+' 1`
-  repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
-  reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
-  pull_base="${pull_default}"
-  for j in $repos_extra ; do
+        echo "[paths]"
+        for i in ${repos} ${repos_extra} ; do
+          if [ "${i}" != "." ] ; then
+            echo "/$(basename $(pwd))/${i} = ${i}"
+          else
+            echo "/$(basename $(pwd)) = $(pwd)"
+          fi
+        done
+      ) > ${tmp}/serve.web-conf
+
+      echo "serving root repo $(basename $(pwd))"
+
+      (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
+    ) 2>&1 | sed -e "s@^@serve:   @" > ${status_output}
+  ) &
+else
+  # Run the supplied command on all repos in parallel.
+  n=0
+  for i in ${repos} ${repos_extra} ; do
+    n=`expr ${n} '+' 1`
+    repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
+    reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
+    pull_base="${pull_default}"
+    for j in $repos_extra ; do
       if [ "$i" = "$j" ] ; then
           pull_base="${pull_extra}"
       fi
-  done
-  (
+    done
     (
-      if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
-        pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
-        echo hg clone ${pull_newrepo} ${i}
-        path="`dirname ${i}`"
-        if [ "${path}" != "." ] ; then
-          times=0
-          while [ ! -d "${path}" ]   ## nested repo, ensure containing dir exists
-          do
-            times=`expr ${times} '+' 1`
-            if [ `expr ${times} '%' 10` -eq 0 ] ; then
-              echo ${path} still not created, waiting...
-            fi
-            sleep 5
-          done
+      (
+        if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then
+          pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
+          path="`dirname ${i}`"
+          if [ "${path}" != "." ] ; then
+            times=0
+            while [ ! -d "${path}" ]   ## nested repo, ensure containing dir exists
+            do
+              times=`expr ${times} '+' 1`
+              if [ `expr ${times} '%' 10` -eq 0 ] ; then
+                echo "${path} still not created, waiting..." > ${status_output}
+              fi
+              sleep 5
+            done
+          fi
+          echo "hg clone ${pull_newrepo} ${i}" > ${status_output}
+          (PYTHONUNBUFFERED=true hg${global_opts} clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
+        else
+          echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output}
+          cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
         fi
-        (PYTHONUNBUFFERED=true hg clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
-      else
-        echo "cd ${i} && hg $*"
-        cd ${i} && (PYTHONUNBUFFERED=true hg "$@"; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
-      fi
-      echo $! > ${tmp}/${repopidfile}.pid
-    ) 2>&1 | sed -e "s@^@${reponame}:   @") &
+
+        echo $! > ${tmp}/${repopidfile}.pid
+      ) 2>&1 | sed -e "s@^@${reponame}:   @" > ${status_output}
+    ) &
 
-  if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
-    sleep 2
-    echo Waiting 5 secs before spawning next background command.
-    sleep 3
-  fi
-done
+    if [ `expr ${n} '%' ${at_a_time}` -eq 0 -a "${sflag}" = "false" ] ; then
+      sleep 2
+      echo "Waiting 5 secs before spawning next background command." > ${status_output}
+      sleep 3
+    fi
+
+    if [ "${sflag}" = "true" ] ; then
+        wait
+    fi
+  done
+fi
+
 # Wait for all hg commands to complete
 wait
 
@@ -181,7 +269,8 @@
   for rc in ${tmp}/*.pid.rc ; do
     exit_code=`cat ${rc} | tr -d ' \n\r'`
     if [ "${exit_code}" != "0" ] ; then
-      echo "WARNING: ${rc} exited abnormally."
+      repo="`echo ${rc} | sed -e s@^${tmp}@@ -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`"
+      echo "WARNING: ${repo} exited abnormally." > ${status_output}
       ec=1
     fi
   done
--- a/common/src/fixpath.c	Fri Apr 11 14:07:25 2014 -0700
+++ b/common/src/fixpath.c	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -29,7 +29,7 @@
 #include <string.h>
 #include <malloc.h>
 
-void report_error()
+void report_error(char const * msg)
 {
   LPVOID lpMsgBuf;
   DWORD dw = GetLastError();
@@ -46,8 +46,8 @@
       NULL);
 
   fprintf(stderr,
-          "Could not start process!  Failed with error %d: %s\n",
-          dw, lpMsgBuf);
+          "%s  Failed with error %d: %s\n",
+          msg, dw, lpMsgBuf);
 
   LocalFree(lpMsgBuf);
 }
@@ -56,7 +56,7 @@
  * Test if pos points to /cygdrive/_/ where _ can
  * be any character.
  */
-int is_cygdrive_here(int pos, char *in, int len)
+int is_cygdrive_here(int pos, char const *in, int len)
 {
   // Length of /cygdrive/c/ is 12
   if (pos+12 > len) return 0;
@@ -81,16 +81,17 @@
  * Works in place since drive letter is always
  * shorter than /cygdrive/
  */
-char *replace_cygdrive_cygwin(char *in)
+char *replace_cygdrive_cygwin(char const *in)
 {
-  int len = strlen(in);
-  char *out = malloc(len+1);
+  size_t len = strlen(in);
+  char *out = (char*) malloc(len+1);
   int i,j;
 
   if (len < 12) {
-    strcpy(out, in);
+    memmove(out, in, len + 1);
     return out;
   }
+
   for (i = 0, j = 0; i<len;) {
     if (is_cygdrive_here(i, in, len)) {
       out[j++] = in[i+10];
@@ -102,7 +103,7 @@
       j++;
     }
   }
-  out[j] = 0;
+  out[j] = '\0';
   return out;
 }
 
@@ -110,7 +111,7 @@
 {
   while ( (addlen+*u+1) > *bl) {
     *bl *= 2;
-    *b = realloc(*b, *bl);
+    *b = (char*) realloc(*b, *bl);
   }
   memcpy(*b+*u, add, addlen);
   *u += addlen;
@@ -125,7 +126,7 @@
   int in_len = strlen(in);
   int sub_len = strlen(sub);
   int rep_len = strlen(rep);
-  char *out = malloc(in_len - sub_len + rep_len + 1);
+  char *out = (char *) malloc(in_len - sub_len + rep_len + 1);
   char *p;
 
   if (!(p = strstr(in, sub))) {
@@ -145,7 +146,7 @@
 char* msys_path_list; // @-separated list of paths prefix to look for
 char* msys_path_list_end; // Points to last \0 in msys_path_list.
 
-void setup_msys_path_list(char* argument)
+void setup_msys_path_list(char const * argument)
 {
   char* p;
   char* drive_letter_pos;
@@ -173,7 +174,7 @@
   } while (p != NULL);
 }
 
-char *replace_cygdrive_msys(char *in)
+char *replace_cygdrive_msys(char const *in)
 {
   char* str;
   char* prefix;
@@ -195,12 +196,12 @@
   return str;
 }
 
-char*(*replace_cygdrive)(char *in) = NULL;
+char*(*replace_cygdrive)(char const *in) = NULL;
 
 char *files_to_delete[1024];
 int num_files_to_delete = 0;
 
-char *fix_at_file(char *in)
+char *fix_at_file(char const *in)
 {
   char *tmpdir;
   char name[2048];
@@ -222,9 +223,13 @@
     exit(-1);
   }
 
-  tmpdir = getenv("TMP");
+  tmpdir = getenv("TEMP");
   if (tmpdir == NULL) {
+#if _WIN64
+    tmpdir = "c:/cygwin64/tmp";
+#else
     tmpdir = "c:/cygwin/tmp";
+#endif
   }
   _snprintf(name, sizeof(name), "%s\\atfile_XXXXXX", tmpdir);
 
@@ -240,7 +245,7 @@
     exit(-1);
   }
 
-  buffer = malloc(buflen);
+  buffer = (char*) malloc(buflen);
   while((blocklen = fread(block,1,sizeof(block),atin)) > 0) {
     append(&buffer, &buflen, &used, block, blocklen);
   }
@@ -257,84 +262,229 @@
   fclose(atout);
   free(fixed);
   free(buffer);
-  files_to_delete[num_files_to_delete] = malloc(strlen(name)+1);
+  files_to_delete[num_files_to_delete] = (char*) malloc(strlen(name)+1);
   strcpy(files_to_delete[num_files_to_delete], name);
   num_files_to_delete++;
-  atname = malloc(strlen(name)+2);
+  atname = (char*) malloc(strlen(name)+2);
   atname[0] = '@';
   strcpy(atname+1, name);
   return atname;
 }
 
-int main(int argc, char **argv)
+// given an argument, convert it to the windows command line safe quoted version
+// using rules from:
+// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
+// caller is responsible for freeing both input and output.
+char * quote_arg(char const * in_arg) {
+  char *quoted = NULL;
+  char *current = quoted;
+  int pass;
+
+  if(strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) {
+     return _strdup(in_arg);
+  }
+
+  // process the arg twice. Once to calculate the size and then to copy it.
+  for(pass=1; pass<=2; pass++) {
+    char const *arg = in_arg;
+
+    // initial "
+    if(pass == 2) {
+      *current = '\"';
+    }
+    current++;
+
+    // process string to be quoted until NUL
+    do {
+      int escapes = 0;
+
+      while (*arg == '\\') {
+        // count escapes.
+        escapes++;
+        arg++;
+      }
+
+      if (*arg == '\0') {
+         // escape the escapes before final "
+         escapes *= 2;
+      } else if (*arg == '"') {
+        // escape the escapes and the "
+        escapes = escapes * 2 + 1;
+      } else {
+         // escapes aren't special, just echo them.
+      }
+
+      // emit some escapes
+      while (escapes > 0) {
+        if (pass == 2) {
+          *current = '\\';
+        }
+        current++;
+        escapes--;
+      }
+
+      // and the current char
+      if (pass == 2) {
+        *current = *arg;
+      }
+      current++;
+    } while( *arg++ != '\0');
+
+    // allocate the buffer
+    if (pass == 1) {
+      size_t alloc = (size_t) (current - quoted + (ptrdiff_t) 2);
+      current = quoted = (char*) calloc(alloc, sizeof(char));
+    }
+  }
+
+  // final " and \0
+  *(current - 1) = '"';
+  *current = '\0';
+
+  return quoted;
+}
+
+int main(int argc, char const ** argv)
 {
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     unsigned short rc;
 
-    char *new_at_file;
-    char *old_at_file;
     char *line;
-    int i;
+    char *current;
+    int i, cmd;
     DWORD exitCode;
 
-    if (argc<3 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) {
-        fprintf(stderr, "Usage: fixpath -c|m<path@path@...> /cygdrive/c/WINDOWS/notepad.exe /cygdrive/c/x/test.txt\n");
+    if (argc<2 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) {
+        fprintf(stderr, "Usage: fixpath -c|m<path@path@...> /cygdrive/c/WINDOWS/notepad.exe [/cygdrive/c/x/test.txt|@/cygdrive/c/x/atfile]\n");
         exit(0);
     }
 
     if (getenv("DEBUG_FIXPATH") != NULL) {
-      fprintf(stderr, "fixpath input line >%s<\n", strstr(GetCommandLine(), argv[1]));
+      char const * cmdline = GetCommandLine();
+      fprintf(stderr, "fixpath input line >%s<\n", strstr( cmdline , argv[1]));
     }
 
     if (argv[1][1] == 'c' && argv[1][2] == '\0') {
       if (getenv("DEBUG_FIXPATH") != NULL) {
-        fprintf(stderr, "using cygwin mode\n");
+        fprintf(stderr, "fixpath using cygwin mode\n");
       }
       replace_cygdrive = replace_cygdrive_cygwin;
     } else if (argv[1][1] == 'm') {
       if (getenv("DEBUG_FIXPATH") != NULL) {
-        fprintf(stderr, "using msys mode, with path list: %s\n", &argv[1][2]);
+        fprintf(stderr, "fixpath using msys mode, with path list: %s\n", &argv[1][2]);
       }
       setup_msys_path_list(argv[1]);
       replace_cygdrive = replace_cygdrive_msys;
     } else {
-      fprintf(stderr, "Unknown mode: %s\n", argv[1]);
+      fprintf(stderr, "fixpath Unknown mode: %s\n", argv[1]);
       exit(-1);
     }
-    line = replace_cygdrive(strstr(GetCommandLine(), argv[2]));
+
+    i = 2;
+
+    // handle assignments
+    while (i < argc) {
+      char const * assignment = strchr(argv[i], '=');
+      if (assignment != NULL && assignment != argv[i]) {
+        size_t var_len = (size_t) (assignment - argv[i] + (ptrdiff_t) 1);
+        char *var = (char *) calloc(var_len, sizeof(char));
+        char *val = replace_cygdrive(assignment + 1);
+        memmove(var, argv[i], var_len);
+        var[var_len - 1] = '\0';
+        strupr(var);
+
+        if (getenv("DEBUG_FIXPATH") != NULL) {
+          fprintf(stderr, "fixpath setting var >%s< to >%s<\n", var, val);
+        }
+
+        rc = SetEnvironmentVariable(var, val);
+        if(!rc) {
+          // Could not set var for some reason.  Try to report why.
+          const int msg_len = 80 + var_len + strlen(val);
+          char * msg = (char *) alloca(msg_len);
+          _snprintf_s(msg, msg_len, _TRUNCATE, "Could not set environment variable [%s=%s]", var, val);
+          report_error(msg);
+          exit(1);
+        }
+        free(var);
+        free(val);
+      } else {
+        // no more assignments;
+        break;
+      }
+      i++;
+    }
 
-    for (i=1; i<argc; ++i) {
-       if (argv[i][0] == '@') {
-          // Found at-file! Fix it!
-          old_at_file = replace_cygdrive(argv[i]);
-          new_at_file = fix_at_file(old_at_file);
-          line = replace_substring(line, old_at_file, new_at_file);
-       }
+    // remember index of the command
+    cmd = i;
+
+    // handle command and it's args.
+    while (i < argc) {
+      char const *replaced = replace_cygdrive(argv[i]);
+      if(replaced[0] == '@') {
+        // Found at-file! Fix it!
+        replaced = fix_at_file(replaced);
+      }
+      argv[i] = quote_arg(replaced);
+      i++;
     }
 
+    // determine the length of the line
+    line = NULL;
+    // args
+    for(i = cmd; i < argc; i++) {
+      line += (ptrdiff_t) strlen(argv[i]);
+    }
+    // spaces and null
+    line += (ptrdiff_t) (argc - cmd + 1);
+    // allocate
+    line = (char*) calloc(line - (char*) NULL, sizeof(char));
+
+    // copy in args.
+    current = line;
+    for(i = cmd; i < argc; i++) {
+      ptrdiff_t len = strlen(argv[i]);
+      if (i != cmd) {
+        *current++ = ' ';
+      }
+      memmove(current, argv[i], len);
+      current += len;
+    }
+    *current = '\0';
+
     if (getenv("DEBUG_FIXPATH") != NULL) {
       fprintf(stderr, "fixpath converted line >%s<\n", line);
     }
 
+    if(cmd == argc) {
+       if (getenv("DEBUG_FIXPATH") != NULL) {
+         fprintf(stderr, "fixpath no command provided!\n");
+       }
+       exit(0);
+    }
+
     ZeroMemory(&si,sizeof(si));
     si.cb=sizeof(si);
     ZeroMemory(&pi,sizeof(pi));
 
+    fflush(stderr);
+    fflush(stdout);
+
     rc = CreateProcess(NULL,
                        line,
                        0,
                        0,
                        TRUE,
                        0,
-                       0,
-                       0,
+                       NULL,
+                       NULL,
                        &si,
                        &pi);
     if(!rc) {
       // Could not start process for some reason.  Try to report why:
-      report_error();
-      exit(rc);
+      report_error("Could not start process!");
+      exit(126);
     }
 
     WaitForSingleObject(pi.hProcess,INFINITE);
@@ -342,15 +492,21 @@
 
     if (getenv("DEBUG_FIXPATH") != NULL) {
       for (i=0; i<num_files_to_delete; ++i) {
-        fprintf(stderr, "Not deleting temporary fixpath file %s\n",
+        fprintf(stderr, "fixpath Not deleting temporary file %s\n",
                 files_to_delete[i]);
       }
-    }
-    else {
+    } else {
       for (i=0; i<num_files_to_delete; ++i) {
         remove(files_to_delete[i]);
       }
     }
 
+    if (exitCode != 0) {
+      if (getenv("DEBUG_FIXPATH") != NULL) {
+        fprintf(stderr, "fixpath exit code %d\n",
+                exitCode);
+      }
+    }
+
     exit(exitCode);
 }
--- a/hotspot/.hgtags	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 19:35:40 2017 +0200
@@ -409,3 +409,4 @@
 3812c088b9456ee22c933e88aee1ece71f4e783a jdk9-b04
 bdc5311e1db7598589b77015119b821bf8c828bd jdk9-b05
 52377a30a3f87b62d6135706997b8c7a47366e37 jdk9-b06
+52f7edf2589d9f9d35db3008bc5377f279de9c18 jdk9-b07
--- a/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m	Wed Jul 05 19:35:40 2017 +0200
@@ -95,7 +95,9 @@
 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; } 
 
 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
-  (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+  jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
+  CHECK_EXCEPTION;
+  (*env)->ThrowNew(env, exceptionClass, errMsg);
 }
 
 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
@@ -129,6 +131,7 @@
 JNIEXPORT void JNICALL 
 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
   symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
+  CHECK_EXCEPTION;
   taskID = (*env)->GetFieldID(env, cls, "task", "J");
   CHECK_EXCEPTION;
 
@@ -236,13 +239,16 @@
   (JNIEnv *env, jobject this_obj, jlong addr) {
   uintptr_t offset;
   const char* sym = NULL;
+  jstring sym_string;
 
   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   if (ph != NULL && ph->core != NULL) {
     sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
     if (sym == NULL) return 0;
+    sym_string = (*env)->NewStringUTF(env, sym);
+    CHECK_EXCEPTION_(0);
     return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
-                          (*env)->NewStringUTF(env, sym), (jlong)offset);
+                                                sym_string, (jlong)offset);
   }
   return 0;
 }
@@ -749,11 +755,14 @@
      const char* name;
      jobject loadObject;
      jobject loadObjectList;
+     jstring nameString;
 
      base = get_lib_base(ph, i);
      name = get_lib_name(ph, i);
+     nameString = (*env)->NewStringUTF(env, name);
+     CHECK_EXCEPTION;
      loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
-                                   (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
+                                            nameString, (jlong)0, (jlong)base);
      CHECK_EXCEPTION;
      loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
      CHECK_EXCEPTION;
--- a/hotspot/agent/src/os/linux/symtab.c	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/agent/src/os/linux/symtab.c	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -162,28 +162,27 @@
 static struct elf_section *find_section_by_name(char *name,
                                                 int fd,
                                                 ELF_EHDR *ehdr,
-                                                ELF_SHDR *shbuf,
                                                 struct elf_section *scn_cache)
 {
-  ELF_SHDR* cursct = NULL;
   char *strtab;
   int cnt;
+  int strtab_size;
 
+  // Section cache have to already contain data for e_shstrndx section.
+  // If it's not true - elf file is broken, so just bail out
   if (scn_cache[ehdr->e_shstrndx].c_data == NULL) {
-    if ((scn_cache[ehdr->e_shstrndx].c_data
-         = read_section_data(fd, ehdr, cursct)) == NULL) {
-      return NULL;
-    }
+    return NULL;
   }
 
   strtab = scn_cache[ehdr->e_shstrndx].c_data;
+  strtab_size = scn_cache[ehdr->e_shstrndx].c_shdr->sh_size;
 
-  for (cursct = shbuf, cnt = 0;
-       cnt < ehdr->e_shnum;
-       cnt++, cursct++) {
-    if (strcmp(cursct->sh_name + strtab, name) == 0) {
-      scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct);
-      return &scn_cache[cnt];
+  for (cnt = 0; cnt < ehdr->e_shnum; ++cnt) {
+    if (scn_cache[cnt].c_shdr->sh_name < strtab_size) {
+      if (strcmp(scn_cache[cnt].c_shdr->sh_name + strtab, name) == 0) {
+        scn_cache[cnt].c_data = read_section_data(fd, ehdr, scn_cache[cnt].c_shdr);
+        return &scn_cache[cnt];
+      }
     }
   }
 
@@ -195,12 +194,11 @@
 static int open_file_from_debug_link(const char *name,
                                      int fd,
                                      ELF_EHDR *ehdr,
-                                     ELF_SHDR *shbuf,
                                      struct elf_section *scn_cache)
 {
   int debug_fd;
   struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr,
-                                                        shbuf, scn_cache);
+                                                         scn_cache);
   if (debug_link == NULL)
     return -1;
   char *debug_filename = debug_link->c_data;
@@ -221,7 +219,6 @@
 
   /* Look in the same directory as the object.  */
   strcpy(last_slash+1, debug_filename);
-
   debug_fd = open_debug_file(debug_pathname, crc);
   if (debug_fd >= 0) {
     free(debug_pathname);
@@ -261,10 +258,9 @@
 static struct symtab *build_symtab_from_debug_link(const char *name,
                                      int fd,
                                      ELF_EHDR *ehdr,
-                                     ELF_SHDR *shbuf,
                                      struct elf_section *scn_cache)
 {
-  fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache);
+  fd = open_file_from_debug_link(name, fd, ehdr, scn_cache);
 
   if (fd >= 0) {
     struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
@@ -463,7 +459,7 @@
 
     // Then, if that doesn't work, the debug link
     if (symtab == NULL) {
-      symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf,
+      symtab = build_symtab_from_debug_link(filename, fd, &ehdr,
                                             scn_cache);
     }
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java	Wed Jul 05 19:35:40 2017 +0200
@@ -51,9 +51,9 @@
     static private CIntegerField summaryBytesUsedField;
     // G1MonitoringSupport* _g1mm;
     static private AddressField g1mmField;
-    // MasterOldRegionSet _old_set;
+    // HeapRegionSet _old_set;
     static private long oldSetFieldOffset;
-    // MasterHumongousRegionSet _humongous_set;
+    // HeapRegionSet _humongous_set;
     static private long humongousSetFieldOffset;
 
     static {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java	Wed Jul 05 19:35:40 2017 +0200
@@ -40,12 +40,8 @@
 // Mirror class for HeapRegionSetBase. Represents a group of regions.
 
 public class HeapRegionSetBase extends VMObject {
-    // uint _length;
-    static private CIntegerField lengthField;
-    // uint _region_num;
-    static private CIntegerField regionNumField;
-    // size_t _total_used_bytes;
-    static private CIntegerField totalUsedBytesField;
+
+    static private long countField;
 
     static {
         VM.registerVMInitializedObserver(new Observer() {
@@ -58,21 +54,13 @@
     static private synchronized void initialize(TypeDataBase db) {
         Type type = db.lookupType("HeapRegionSetBase");
 
-        lengthField         = type.getCIntegerField("_length");
-        regionNumField      = type.getCIntegerField("_region_num");
-        totalUsedBytesField = type.getCIntegerField("_total_used_bytes");
+        countField = type.getField("_count").getOffset();
     }
 
-    public long length() {
-        return lengthField.getValue(addr);
-    }
 
-    public long regionNum() {
-        return regionNumField.getValue(addr);
-    }
-
-    public long totalUsedBytes() {
-        return totalUsedBytesField.getValue(addr);
+    public HeapRegionSetCount count() {
+        Address countFieldAddr = addr.addOffsetTo(countField);
+        return (HeapRegionSetCount) VMObjectFactory.newObject(HeapRegionSetCount.class, countFieldAddr);
     }
 
     public HeapRegionSetBase(Address addr) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetCount.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+package sun.jvm.hotspot.gc_implementation.g1;
+
+import java.util.Iterator;
+import java.util.Observable;
+import java.util.Observer;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.AddressField;
+import sun.jvm.hotspot.types.CIntegerField;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
+
+// Mirror class for HeapRegionSetCount. Represents a group of regions.
+
+public class HeapRegionSetCount extends VMObject {
+
+    static private CIntegerField lengthField;
+    static private CIntegerField capacityField;
+
+    static {
+        VM.registerVMInitializedObserver(new Observer() {
+                public void update(Observable o, Object data) {
+                    initialize(VM.getVM().getTypeDataBase());
+                }
+            });
+    }
+
+    static private synchronized void initialize(TypeDataBase db) {
+        Type type = db.lookupType("HeapRegionSetCount");
+
+        lengthField   = type.getCIntegerField("_length");
+        capacityField = type.getCIntegerField("_capacity");
+    }
+
+    public long length() {
+        return lengthField.getValue(addr);
+    }
+
+    public long capacity() {
+        return capacityField.getValue(addr);
+    }
+
+    public HeapRegionSetCount(Address addr) {
+        super(addr);
+    }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Wed Jul 05 19:35:40 2017 +0200
@@ -114,7 +114,8 @@
              long survivorRegionNum = g1mm.survivorRegionNum();
              HeapRegionSetBase oldSet = g1h.oldSet();
              HeapRegionSetBase humongousSet = g1h.humongousSet();
-             long oldRegionNum = oldSet.regionNum() + humongousSet.regionNum();
+             long oldRegionNum = oldSet.count().length()
+                          + humongousSet.count().capacity() / HeapRegion.grainBytes();
              printG1Space("G1 Heap:", g1h.n_regions(),
                           g1h.used(), g1h.capacity());
              System.out.println("G1 Young Generation:");
--- a/hotspot/make/Makefile	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/Makefile	Wed Jul 05 19:35:40 2017 +0200
@@ -287,8 +287,43 @@
 	@$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true."
 endif
 
+remove_old_debuginfo:
+ifeq ($(JVM_VARIANT_CLIENT), true)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    ifeq ($(OSNAME), windows)
+	  $(RM) -f $(EXPORT_CLIENT_DIR)/jvm.map $(EXPORT_CLIENT_DIR)/jvm.pdb
+    else
+	  $(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+    endif
+  else
+	$(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.diz
+  endif
+endif
+ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    ifeq ($(OSNAME), windows)
+	  $(RM) -f $(EXPORT_SERVER_DIR)/jvm.map $(EXPORT_SERVER_DIR)/jvm.pdb
+    else
+      ifeq ($(OS_VENDOR), Darwin)
+	    $(RM) -rf $(EXPORT_SERVER_DIR)/libjvm.dylib.dSYM
+      else
+	    $(RM) -f $(EXPORT_SERVER_DIR)/libjvm.debuginfo
+      endif
+    endif
+  else
+	$(RM) -f $(EXPORT_SERVER_DIR)/libjvm.diz
+  endif
+endif
+ifeq ($(JVM_VARIANT_MINIMAL1),true)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.debuginfo
+  else
+	$(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.diz
+  endif
+endif
+
 # Export file rule
-generic_export: $(EXPORT_LIST)
+generic_export: $(EXPORT_LIST) remove_old_debuginfo
 
 export_product:
 	$(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export
@@ -841,4 +876,4 @@
 	export_jdk_product export_jdk_fastdebug export_jdk_debug \
 	create_jdk copy_jdk update_jdk test_jdk \
 	copy_product_jdk copy_fastdebug_jdk copy_debug_jdk  \
-	$(HS_ALT_MAKE)/Makefile.make
+	$(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo
--- a/hotspot/make/aix/makefiles/vm.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/aix/makefiles/vm.make	Wed Jul 05 19:35:40 2017 +0200
@@ -101,7 +101,7 @@
 # This is VERY important! The version define must only be supplied to vm_version.o
 # If not, ccache will not re-use the cache at all, since the version string might contain
 # a time and date.
-vm_version.o: CXXFLAGS += ${JRE_VERSION}
+CXXFLAGS/vm_version.o += ${JRE_VERSION}
 
 CXXFLAGS/BYFILE = $(CXXFLAGS/$@)
 
--- a/hotspot/make/excludeSrc.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/excludeSrc.make	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 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
@@ -87,9 +87,10 @@
 	g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \
 	g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
 	g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \
-	g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \
+	g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1StringDedup.cpp g1StringDedupStat.cpp \
+	g1StringDedupTable.cpp g1StringDedupThread.cpp g1StringDedupQueue.cpp g1_globals.cpp heapRegion.cpp \
 	g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
-	ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \
+	ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp g1CodeCacheRemSet.cpp \
 	adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
 	cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \
 	parallelScavengeHeap.cpp parMarkBitMap.cpp pcTasks.cpp psAdaptiveSizePolicy.cpp \
--- a/hotspot/make/jprt.properties	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/jprt.properties	Wed Jul 05 19:35:40 2017 +0200
@@ -33,7 +33,7 @@
 
 # This tells jprt what default release we want to build
 
-jprt.hotspot.default.release=jdk8
+jprt.hotspot.default.release=jdk9
 
 jprt.tools.default.release=${jprt.submit.option.release?${jprt.submit.option.release}:${jprt.hotspot.default.release}}
 
@@ -47,72 +47,50 @@
 #       sparc etc.
 
 # Define the Solaris platforms we want for the various releases
-jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10
-jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
-jprt.my.solaris.sparcv9.jdk7u8=${jprt.my.solaris.sparcv9.jdk7}
+jprt.my.solaris.sparcv9.jdk9=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
 
-jprt.my.solaris.x64.jdk8=solaris_x64_5.10
-jprt.my.solaris.x64.jdk7=solaris_x64_5.10
-jprt.my.solaris.x64.jdk7u8=${jprt.my.solaris.x64.jdk7}
+jprt.my.solaris.x64.jdk9=solaris_x64_5.10
 jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
 
-jprt.my.linux.i586.jdk8=linux_i586_2.6
-jprt.my.linux.i586.jdk7=linux_i586_2.6
-jprt.my.linux.i586.jdk7u8=${jprt.my.linux.i586.jdk7}
+jprt.my.linux.i586.jdk9=linux_i586_2.6
 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}}
 
-jprt.my.linux.x64.jdk8=linux_x64_2.6
-jprt.my.linux.x64.jdk7=linux_x64_2.6
-jprt.my.linux.x64.jdk7u8=${jprt.my.linux.x64.jdk7}
+jprt.my.linux.x64.jdk9=linux_x64_2.6
 jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}}
 
-jprt.my.linux.ppc.jdk8=linux_ppc_2.6
-jprt.my.linux.ppc.jdk7=linux_ppc_2.6
-jprt.my.linux.ppc.jdk7u8=${jprt.my.linux.ppc.jdk7}
+jprt.my.linux.ppc.jdk9=linux_ppc_2.6
 jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}}
 
-jprt.my.linux.ppcv2.jdk8=linux_ppcv2_2.6
-jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6
-jprt.my.linux.ppcv2.jdk7u8=${jprt.my.linux.ppcv2.jdk7}
+jprt.my.linux.ppcv2.jdk9=linux_ppcv2_2.6
 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}}
 
-jprt.my.linux.ppcsflt.jdk8=linux_ppcsflt_2.6
-jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6
-jprt.my.linux.ppcsflt.jdk7u8=${jprt.my.linux.ppcsflt.jdk7}
+jprt.my.linux.ppcsflt.jdk9=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}}
 
-jprt.my.linux.armvfpsflt.jdk8=linux_armvfpsflt_2.6
+jprt.my.linux.armvfpsflt.jdk9=linux_armvfpsflt_2.6
 jprt.my.linux.armvfpsflt=${jprt.my.linux.armvfpsflt.${jprt.tools.default.release}}
 
-jprt.my.linux.armvfphflt.jdk8=linux_armvfphflt_2.6
+jprt.my.linux.armvfphflt.jdk9=linux_armvfphflt_2.6
 jprt.my.linux.armvfphflt=${jprt.my.linux.armvfphflt.${jprt.tools.default.release}}
 
 # The ARM GP vfp-sflt build is not currently supported
-#jprt.my.linux.armvs.jdk8=linux_armvs_2.6
+#jprt.my.linux.armvs.jdk9=linux_armvs_2.6
 #jprt.my.linux.armvs=${jprt.my.linux.armvs.${jprt.tools.default.release}}
 
-jprt.my.linux.armvh.jdk8=linux_armvh_2.6
+jprt.my.linux.armvh.jdk9=linux_armvh_2.6
 jprt.my.linux.armvh=${jprt.my.linux.armvh.${jprt.tools.default.release}}
 
-jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6
-jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6
-jprt.my.linux.armsflt.jdk7u8=${jprt.my.linux.armsflt.jdk7}
+jprt.my.linux.armsflt.jdk9=linux_armsflt_2.6
 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}}
 
-jprt.my.macosx.x64.jdk8=macosx_x64_10.7
-jprt.my.macosx.x64.jdk7=macosx_x64_10.7
-jprt.my.macosx.x64.jdk7u8=${jprt.my.macosx.x64.jdk7}
+jprt.my.macosx.x64.jdk9=macosx_x64_10.7
 jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}}
 
-jprt.my.windows.i586.jdk8=windows_i586_6.1
-jprt.my.windows.i586.jdk7=windows_i586_6.1
-jprt.my.windows.i586.jdk7u8=${jprt.my.windows.i586.jdk7}
+jprt.my.windows.i586.jdk9=windows_i586_6.1
 jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
 
-jprt.my.windows.x64.jdk8=windows_x64_6.1
-jprt.my.windows.x64.jdk7=windows_x64_6.1
-jprt.my.windows.x64.jdk7u8=${jprt.my.windows.x64.jdk7}
+jprt.my.windows.x64.jdk9=windows_x64_6.1
 jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}}
 
 # Standard list of jprt build targets for this source tree
@@ -143,9 +121,7 @@
 jprt.build.targets.all=${jprt.build.targets.standard}, \
     ${jprt.build.targets.embedded}, ${jprt.build.targets.open}
 
-jprt.build.targets.jdk8=${jprt.build.targets.all}
-jprt.build.targets.jdk7=${jprt.build.targets.all}
-jprt.build.targets.jdk7u8=${jprt.build.targets.all}
+jprt.build.targets.jdk9=${jprt.build.targets.all}
 jprt.build.targets=${jprt.build.targets.${jprt.tools.default.release}}
 
 # Subset lists of test targets for this source tree
@@ -349,9 +325,7 @@
   ${jprt.my.windows.i586.test.targets}, \
   ${jprt.my.windows.x64.test.targets}
 
-jprt.test.targets.jdk8=${jprt.test.targets.standard}
-jprt.test.targets.jdk7=${jprt.test.targets.standard}
-jprt.test.targets.jdk7u8=${jprt.test.targets.jdk7}
+jprt.test.targets.jdk9=${jprt.test.targets.standard}
 jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}}
 
 # The default test/Makefile targets that should be run
@@ -399,9 +373,7 @@
 jprt.make.rule.test.targets.embedded = \
   ${jprt.make.rule.test.targets.standard.client}
 
-jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard}
-jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard}
-jprt.make.rule.test.targets.jdk7u8=${jprt.make.rule.test.targets.jdk7}
+jprt.make.rule.test.targets.jdk9=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}}
 
 # 7155453: Work-around to prevent popups on OSX from blocking test completion
--- a/hotspot/make/linux/Makefile	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/linux/Makefile	Wed Jul 05 19:35:40 2017 +0200
@@ -66,8 +66,8 @@
     FORCE_TIERED=1
   endif
 endif
-# C1 is not ported on ppc64(le), so we cannot build a tiered VM:
-ifneq (,$(filter $(ARCH),ppc64 pp64le))
+# C1 is not ported on ppc64, so we cannot build a tiered VM:
+ifeq ($(ARCH),ppc64)
   FORCE_TIERED=0
 endif
 
--- a/hotspot/make/linux/makefiles/defs.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/linux/makefiles/defs.make	Wed Jul 05 19:35:40 2017 +0200
@@ -33,6 +33,11 @@
 # ARCH can be set explicitly in spec.gmk
 ifndef ARCH
   ARCH := $(shell uname -m)
+  # Fold little endian PowerPC64 into big-endian (if ARCH is set in
+  # hotspot-spec.gmk, this will be done by the configure script).
+  ifeq ($(ARCH),ppc64le)
+    ARCH := ppc64
+  endif
 endif
 
 PATH_SEP ?= :
--- a/hotspot/make/linux/makefiles/gcc.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/linux/makefiles/gcc.make	Wed Jul 05 19:35:40 2017 +0200
@@ -337,56 +337,20 @@
 ifeq ($(DEBUG_BINARIES), true)
   CFLAGS += -g
 else
-  # Use the stabs format for debugging information (this is the default
-  # on gcc-2.91). It's good enough, has all the information about line
-  # numbers and local variables, and libjvm.so is only about 16M.
-  # Change this back to "-g" if you want the most expressive format.
-  # (warning: that could easily inflate libjvm.so to 150M!)
-  # Note: The Itanium gcc compiler crashes when using -gstabs.
-  DEBUG_CFLAGS/ia64  = -g
-  DEBUG_CFLAGS/amd64 = -g
-  DEBUG_CFLAGS/arm   = -g
-  DEBUG_CFLAGS/ppc   = -g
-  DEBUG_CFLAGS/ppc64 = -g
   DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
   ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
-      ifeq ($(USE_CLANG), true)
-        # Clang doesn't understand -gstabs
-        DEBUG_CFLAGS += -g
-      else
-        DEBUG_CFLAGS += -gstabs
-      endif
+    DEBUG_CFLAGS += -g
   endif
-  
+
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-    FASTDEBUG_CFLAGS/ia64  = -g
-    FASTDEBUG_CFLAGS/amd64 = -g
-    FASTDEBUG_CFLAGS/arm   = -g
-    FASTDEBUG_CFLAGS/ppc   = -g
-    FASTDEBUG_CFLAGS/ppc64 = -g
-    FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
+    FASTDEBUG_CFLAGS += $(FASTDEBUG_CFLAGS/$(BUILDARCH))
     ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),)
-      ifeq ($(USE_CLANG), true)
-        # Clang doesn't understand -gstabs
-        FASTDEBUG_CFLAGS += -g
-      else
-        FASTDEBUG_CFLAGS += -gstabs
-      endif
+      FASTDEBUG_CFLAGS += -g
     endif
-  
-    OPT_CFLAGS/ia64  = -g
-    OPT_CFLAGS/amd64 = -g
-    OPT_CFLAGS/arm   = -g
-    OPT_CFLAGS/ppc   = -g
-    OPT_CFLAGS/ppc64 = -g
+
     OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH))
     ifeq ($(OPT_CFLAGS/$(BUILDARCH)),)
-      ifeq ($(USE_CLANG), true)
-        # Clang doesn't understand -gstabs
-        OPT_CFLAGS += -g
-      else
-        OPT_CFLAGS += -gstabs
-      endif
+      OPT_CFLAGS += -g
     endif
   endif
 endif
--- a/hotspot/make/linux/makefiles/ppc64.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/linux/makefiles/ppc64.make	Wed Jul 05 19:35:40 2017 +0200
@@ -26,14 +26,26 @@
 # make c code know it is on a 64 bit platform.
 CFLAGS += -D_LP64=1
 
-# fixes `relocation truncated to fit' error for gcc 4.1.
-CFLAGS += -mminimal-toc
+ifeq ($(origin OPENJDK_TARGET_CPU_ENDIAN),undefined)
+  # This can happen during hotspot standalone build. Set endianness from
+  # uname. We assume build and target machines are the same.
+  OPENJDK_TARGET_CPU_ENDIAN:=$(if $(filter ppc64le,$(shell uname -m)),little,big)
+endif
 
-# finds use ppc64 instructions, but schedule for power5
-CFLAGS += -mcpu=powerpc64 -mtune=power5 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+ifeq ($(filter $(OPENJDK_TARGET_CPU_ENDIAN),big little),)
+  $(error OPENJDK_TARGET_CPU_ENDIAN value should be 'big' or 'little')
+endif
 
-# let linker find external 64 bit libs.
-LFLAGS_VM += -L/lib64
+ifeq ($(OPENJDK_TARGET_CPU_ENDIAN),big)
+  # fixes `relocation truncated to fit' error for gcc 4.1.
+  CFLAGS += -mminimal-toc
 
-# specify lib format.
-LFLAGS_VM +=  -Wl,-melf64ppc
+  # finds use ppc64 instructions, but schedule for power5
+  CFLAGS += -mcpu=powerpc64 -mtune=power5 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+else
+  # Little endian machine uses ELFv2 ABI.
+  CFLAGS += -DVM_LITTLE_ENDIAN -DABI_ELFv2
+
+  # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
+  CFLAGS += -mcpu=power7 -mtune=power8 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+endif
--- a/hotspot/make/windows/makefiles/defs.make	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/make/windows/makefiles/defs.make	Wed Jul 05 19:35:40 2017 +0200
@@ -260,7 +260,6 @@
       EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
     endif
   endif
-  EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
 endif
 ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
@@ -275,6 +274,8 @@
   endif
 endif
 
+EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
+
 ifeq ($(BUILD_WIN_SA), 1)
   EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
  */
 
 #include "precompiled.hpp"
-#include "asm/assembler.hpp"
 #include "asm/assembler.inline.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
 #include "interpreter/interpreter.hpp"
@@ -37,6 +36,7 @@
 #include "runtime/os.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
+#include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
@@ -384,10 +384,10 @@
       bool load_xa = (xa != 0) || (xb < 0);
       bool return_xd = false;
 
-      if (load_xa) lis(tmp, xa);
-      if (xc) lis(d, xc);
+      if (load_xa) { lis(tmp, xa); }
+      if (xc) { lis(d, xc); }
       if (load_xa) {
-        if (xb) ori(tmp, tmp, xb); // No addi, we support tmp == R0.
+        if (xb) { ori(tmp, tmp, (unsigned short)xb); } // No addi, we support tmp == R0.
       } else {
         li(tmp, xb); // non-negative
       }
@@ -409,18 +409,18 @@
     // opt 4: avoid adding 0
     if (xa) { // Highest 16-bit needed?
       lis(d, xa);
-      if (xb) addi(d, d, xb);
+      if (xb) { addi(d, d, xb); }
     } else {
       li(d, xb);
     }
     sldi(d, d, 32);
-    if (xc) addis(d, d, xc);
+    if (xc) { addis(d, d, xc); }
   }
 
   // opt 5: Return offset to be inserted into following instruction.
   if (return_simm16_rest) return xd;
 
-  if (xd) addi(d, d, xd);
+  if (xd) { addi(d, d, xd); }
   return 0;
 }
 
@@ -696,4 +696,5 @@
   tty->print_cr("\ntest_asm disassembly (0x%lx 0x%lx):", code()->insts_begin(), code()->insts_end());
   code()->decode();
 }
+
 #endif // !PRODUCT
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1025,15 +1025,14 @@
   }
 
   static void set_imm(int* instr, short s) {
-    short* p = ((short *)instr) + 1;
-    *p = s;
+    // imm is always in the lower 16 bits of the instruction,
+    // so this is endian-neutral. Same for the get_imm below.
+    uint32_t w = *(uint32_t *)instr;
+    *instr = (int)((w & ~0x0000FFFF) | (s & 0x0000FFFF));
   }
 
   static int get_imm(address a, int instruction_number) {
-    short imm;
-    short *p =((short *)a)+2*instruction_number+1;
-    imm = *p;
-    return (int)imm;
+    return (short)((int *)a)[instruction_number];
   }
 
   static inline int hi16_signed(  int x) { return (int)(int16_t)(x >> 16); }
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -139,7 +139,8 @@
 inline void Assembler::cmplw( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 0, a, b); }
 inline void Assembler::cmpld( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 1, a, b); }
 
-inline void Assembler::isel(Register d, Register a, Register b, int c) { emit_int32(ISEL_OPCODE    | rt(d)  | ra(a) | rb(b) | bc(c)); }
+inline void Assembler::isel(Register d, Register a, Register b, int c) { guarantee(VM_Version::has_isel(), "opcode not supported on this hardware");
+                                                                         emit_int32(ISEL_OPCODE    | rt(d)  | ra(a) | rb(b) | bc(c)); }
 
 // PPC 1, section 3.3.11, Fixed-Point Logical Instructions
 inline void Assembler::andi_(   Register a, Register s, int ui16)      { emit_int32(ANDI_OPCODE    | rta(a) | rs(s) | uimm(ui16, 16)); }
@@ -531,9 +532,12 @@
 //inline void Assembler::mffgpr( FloatRegister d, Register b)   { emit_int32( MFFGPR_OPCODE | frt(d) | rb(b) | rc(0)); }
 //inline void Assembler::mftgpr( Register d, FloatRegister b)   { emit_int32( MFTGPR_OPCODE | rt(d) | frb(b) | rc(0)); }
 // add cmpb and popcntb to detect ppc power version.
-inline void Assembler::cmpb(   Register a, Register s, Register b) { emit_int32( CMPB_OPCODE    | rta(a) | rs(s) | rb(b) | rc(0)); }
-inline void Assembler::popcntb(Register a, Register s)             { emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); };
-inline void Assembler::popcntw(Register a, Register s)             { emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); };
+inline void Assembler::cmpb(   Register a, Register s, Register b) { guarantee(VM_Version::has_cmpb(), "opcode not supported on this hardware");
+                                                                     emit_int32( CMPB_OPCODE    | rta(a) | rs(s) | rb(b) | rc(0)); }
+inline void Assembler::popcntb(Register a, Register s)             { guarantee(VM_Version::has_popcntb(), "opcode not supported on this hardware");
+                                                                     emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); };
+inline void Assembler::popcntw(Register a, Register s)             { guarantee(VM_Version::has_popcntw(), "opcode not supported on this hardware");
+                                                                     emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); };
 inline void Assembler::popcntd(Register a, Register s)             { emit_int32( POPCNTD_OPCODE | rta(a) | rs(s)); };
 
 inline void Assembler::fneg(  FloatRegister d, FloatRegister b) { emit_int32( FNEG_OPCODE  | frt(d) | frb(b) | rc(0)); }
@@ -568,14 +572,17 @@
 inline void Assembler::fctiw( FloatRegister d, FloatRegister b) { emit_int32( FCTIW_OPCODE  | frt(d) | frb(b) | rc(0)); }
 inline void Assembler::fctiwz(FloatRegister d, FloatRegister b) { emit_int32( FCTIWZ_OPCODE | frt(d) | frb(b) | rc(0)); }
 inline void Assembler::fcfid( FloatRegister d, FloatRegister b) { emit_int32( FCFID_OPCODE  | frt(d) | frb(b) | rc(0)); }
-inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); }
+inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fcfids(), "opcode not supported on this hardware");
+                                                                  emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); }
 
 // PPC 1, section 4.6.7 Floating-Point Compare Instructions
 inline void Assembler::fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b) { emit_int32( FCMPU_OPCODE | bf(crx) | fra(a) | frb(b)); }
 
 // PPC 1, section 5.2.1 Floating-Point Arithmetic Instructions
-inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { emit_int32( FSQRT_OPCODE  | frt(d) | frb(b) | rc(0)); }
-inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); }
+inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrt(), "opcode not supported on this hardware");
+                                                                  emit_int32( FSQRT_OPCODE  | frt(d) | frb(b) | rc(0)); }
+inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrts(), "opcode not supported on this hardware");
+                                                                  emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); }
 
 // Vector instructions for >= Power6.
 inline void Assembler::lvebx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEBX_OPCODE  | vrt(d) | ra0mem(s1) | rb(s2)); }
@@ -703,7 +710,8 @@
 inline void Assembler::vcmpgtub_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
 inline void Assembler::vcmpgtuh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
 inline void Assembler::vcmpgtuw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
-inline void Assembler::vand(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAND_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
+inline void Assembler::vand(    VectorRegister d, VectorRegister a, VectorRegister b) { guarantee(VM_Version::has_vand(), "opcode not supported on this hardware");
+                                                                                        emit_int32( VAND_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vandc(   VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vnor(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vor(     VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE      | vrt(d) | vra(a) | vrb(b)); }
--- a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -35,6 +35,126 @@
 
   // Can I count on address always being a pointer to an unsigned char? Yes.
 
+#if defined(VM_LITTLE_ENDIAN)
+
+  // Returns true, if the byte ordering used by Java is different from the native byte ordering
+  // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
+  static inline bool is_Java_byte_ordering_different() { return true; }
+
+  // Forward declarations of the compiler-dependent implementation
+  static inline u2 swap_u2(u2 x);
+  static inline u4 swap_u4(u4 x);
+  static inline u8 swap_u8(u8 x);
+
+  static inline u2   get_native_u2(address p) {
+    return (intptr_t(p) & 1) == 0
+             ?   *(u2*)p
+             :   ( u2(p[1]) << 8 )
+               | ( u2(p[0])      );
+  }
+
+  static inline u4   get_native_u4(address p) {
+    switch (intptr_t(p) & 3) {
+     case 0:  return *(u4*)p;
+
+     case 2:  return (  u4( ((u2*)p)[1] ) << 16  )
+                   | (  u4( ((u2*)p)[0] )        );
+
+    default:  return ( u4(p[3]) << 24 )
+                   | ( u4(p[2]) << 16 )
+                   | ( u4(p[1]) <<  8 )
+                   |   u4(p[0]);
+    }
+  }
+
+  static inline u8   get_native_u8(address p) {
+    switch (intptr_t(p) & 7) {
+      case 0:  return *(u8*)p;
+
+      case 4:  return (  u8( ((u4*)p)[1] ) << 32  )
+                    | (  u8( ((u4*)p)[0] )        );
+
+      case 2:  return (  u8( ((u2*)p)[3] ) << 48  )
+                    | (  u8( ((u2*)p)[2] ) << 32  )
+                    | (  u8( ((u2*)p)[1] ) << 16  )
+                    | (  u8( ((u2*)p)[0] )        );
+
+     default:  return ( u8(p[7]) << 56 )
+                    | ( u8(p[6]) << 48 )
+                    | ( u8(p[5]) << 40 )
+                    | ( u8(p[4]) << 32 )
+                    | ( u8(p[3]) << 24 )
+                    | ( u8(p[2]) << 16 )
+                    | ( u8(p[1]) <<  8 )
+                    |   u8(p[0]);
+    }
+  }
+
+
+
+  static inline void put_native_u2(address p, u2 x) {
+    if ( (intptr_t(p) & 1) == 0 )  *(u2*)p = x;
+    else {
+      p[1] = x >> 8;
+      p[0] = x;
+    }
+  }
+
+  static inline void put_native_u4(address p, u4 x) {
+    switch ( intptr_t(p) & 3 ) {
+    case 0:  *(u4*)p = x;
+              break;
+
+    case 2:  ((u2*)p)[1] = x >> 16;
+             ((u2*)p)[0] = x;
+             break;
+
+    default: ((u1*)p)[3] = x >> 24;
+             ((u1*)p)[2] = x >> 16;
+             ((u1*)p)[1] = x >>  8;
+             ((u1*)p)[0] = x;
+             break;
+    }
+  }
+
+  static inline void put_native_u8(address p, u8 x) {
+    switch ( intptr_t(p) & 7 ) {
+    case 0:  *(u8*)p = x;
+             break;
+
+    case 4:  ((u4*)p)[1] = x >> 32;
+             ((u4*)p)[0] = x;
+             break;
+
+    case 2:  ((u2*)p)[3] = x >> 48;
+             ((u2*)p)[2] = x >> 32;
+             ((u2*)p)[1] = x >> 16;
+             ((u2*)p)[0] = x;
+             break;
+
+    default: ((u1*)p)[7] = x >> 56;
+             ((u1*)p)[6] = x >> 48;
+             ((u1*)p)[5] = x >> 40;
+             ((u1*)p)[4] = x >> 32;
+             ((u1*)p)[3] = x >> 24;
+             ((u1*)p)[2] = x >> 16;
+             ((u1*)p)[1] = x >>  8;
+             ((u1*)p)[0] = x;
+    }
+  }
+
+  // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
+  // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
+  static inline u2   get_Java_u2(address p) { return swap_u2(get_native_u2(p)); }
+  static inline u4   get_Java_u4(address p) { return swap_u4(get_native_u4(p)); }
+  static inline u8   get_Java_u8(address p) { return swap_u8(get_native_u8(p)); }
+
+  static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, swap_u2(x)); }
+  static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, swap_u4(x)); }
+  static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, swap_u8(x)); }
+
+#else // !defined(VM_LITTLE_ENDIAN)
+
   // Returns true, if the byte ordering used by Java is different from the nativ byte ordering
   // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
   static inline bool is_Java_byte_ordering_different() { return false; }
@@ -150,6 +270,12 @@
   static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, x); }
   static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, x); }
   static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, x); }
+
+#endif // VM_LITTLE_ENDIAN
 };
 
+#if defined(TARGET_OS_ARCH_linux_ppc)
+#include "bytes_linux_ppc.inline.hpp"
+#endif
+
 #endif // CPU_PPC_VM_BYTES_PPC_HPP
--- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,7 +87,7 @@
 define_pd_global(uintx, CodeCacheMinBlockLength,     4);
 define_pd_global(uintx, CodeCacheMinimumUseSpace,    400*K);
 
-define_pd_global(bool,  TrapBasedRangeChecks,        false);
+define_pd_global(bool,  TrapBasedRangeChecks,        true);
 
 // Heap related flags
 define_pd_global(uintx,MetaspaceSize,                ScaleForWordSize(16*M));
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,6 @@
  */
 
 #include "precompiled.hpp"
-#include "asm/assembler.hpp"
-#include "asm/assembler.inline.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "compiler/disassembler.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
@@ -1120,7 +1118,7 @@
   }
   return _last_calls_return_pc;
 }
-#endif
+#endif // ABI_ELFv2
 
 void MacroAssembler::call_VM_base(Register oop_result,
                                   Register last_java_sp,
@@ -1794,7 +1792,7 @@
   cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern);
   bne(cr_reg, cas_label);
 
-  load_klass_with_trap_null_check(temp_reg, obj_reg);
+  load_klass(temp_reg, obj_reg);
 
   load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place));
   ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg);
@@ -1891,7 +1889,7 @@
   // the bias from one thread to another directly in this situation.
   andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place);
   orr(temp_reg, R16_thread, temp_reg);
-  load_klass_with_trap_null_check(temp2_reg, obj_reg);
+  load_klass(temp2_reg, obj_reg);
   ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg);
   orr(temp_reg, temp_reg, temp2_reg);
 
@@ -1927,7 +1925,7 @@
   // that another thread raced us for the privilege of revoking the
   // bias of this particular object, so it's okay to continue in the
   // normal locking code.
-  load_klass_with_trap_null_check(temp_reg, obj_reg);
+  load_klass(temp_reg, obj_reg);
   ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg);
   andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place);
   orr(temp_reg, temp_reg, temp2_reg);
@@ -2213,8 +2211,7 @@
   stbx(R0, Rtmp, Robj);
 }
 
-#ifndef SERIALGC
-
+#if INCLUDE_ALL_GCS
 // General G1 pre-barrier generator.
 // Goal: record the previous value if it is not null.
 void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
@@ -2328,14 +2325,17 @@
 
   // Get the address of the card.
   lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr);
-
-  assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
-  cmpwi(CCR0, Rtmp3 /* card value */, 0);
+  cmpwi(CCR0, Rtmp3, (int)G1SATBCardTableModRefBS::g1_young_card_val());
+  beq(CCR0, filtered);
+
+  membar(Assembler::StoreLoad);
+  lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr);  // Reload after membar.
+  cmpwi(CCR0, Rtmp3 /* card value */, CardTableModRefBS::dirty_card_val());
   beq(CCR0, filtered);
 
   // Storing a region crossing, non-NULL oop, card is clean.
   // Dirty card and log.
-  li(Rtmp3, 0); // dirty
+  li(Rtmp3, CardTableModRefBS::dirty_card_val());
   //release(); // G1: oops are allowed to get visible after dirty marking.
   stbx(Rtmp3, Rbase, Rcard_addr);
 
@@ -2362,7 +2362,7 @@
 
   bind(filtered_int);
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // Values for last_Java_pc, and last_Java_sp must comply to the rules
 // in frame_ppc64.hpp.
@@ -2453,7 +2453,8 @@
 void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
   Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided.
   if (Universe::narrow_klass_base() != 0) {
-    load_const(R0, Universe::narrow_klass_base(), (dst != current) ? dst : noreg); // Use dst as temp if it is free.
+    // Use dst as temp if it is free.
+    load_const(R0, Universe::narrow_klass_base(), (dst != current && dst != R0) ? dst : noreg);
     sub(dst, current, R0);
     current = dst;
   }
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -514,14 +514,14 @@
   void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp);
   void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // General G1 pre-barrier generator.
   void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
                             Register Rtmp1, Register Rtmp2, bool needs_frame = false);
   // General G1 post-barrier generator
   void g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1,
                              Register Rtmp2, Register Rtmp3, Label *filtered_ext = NULL);
-#endif // SERIALGC
+#endif
 
   // Support for managing the JavaThread pointer (i.e.; the reference to
   // thread-local information).
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,6 +119,7 @@
 
 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp,
                                             bool for_compiler_entry) {
+  Label L_no_such_method;
   assert(method == R19_method, "interpreter calling convention");
   assert_different_registers(method, target, temp);
 
@@ -131,17 +132,31 @@
     __ lwz(temp, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread);
     __ cmplwi(CCR0, temp, 0);
     __ beq(CCR0, run_compiled_code);
+    // Null method test is replicated below in compiled case,
+    // it might be able to address across the verify_thread()
+    __ cmplwi(CCR0, R19_method, 0);
+    __ beq(CCR0, L_no_such_method);
     __ ld(target, in_bytes(Method::interpreter_entry_offset()), R19_method);
     __ mtctr(target);
     __ bctr();
     __ BIND(run_compiled_code);
   }
 
+  // Compiled case, either static or fall-through from runtime conditional
+  __ cmplwi(CCR0, R19_method, 0);
+  __ beq(CCR0, L_no_such_method);
+
   const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() :
                                                      Method::from_interpreted_offset();
   __ ld(target, in_bytes(entry_offset), R19_method);
   __ mtctr(target);
   __ bctr();
+
+  __ bind(L_no_such_method);
+  assert(StubRoutines::throw_AbstractMethodError_entry() != NULL, "not yet generated!");
+  __ load_const_optimized(target, StubRoutines::throw_AbstractMethodError_entry());
+  __ mtctr(target);
+  __ bctr();
 }
 
 
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 19:35:40 2017 +0200
@@ -891,6 +891,13 @@
 // This is a block of C++ code which provides values, functions, and
 // definitions necessary in the rest of the architecture description.
 source_hpp %{
+  // Header information of the source block.
+  // Method declarations/definitions which are used outside
+  // the ad-scope can conveniently be defined here.
+  //
+  // To keep related declarations/definitions/uses close together,
+  // we switch between source %{ }% and source_hpp %{ }% freely as needed.
+
   // Returns true if Node n is followed by a MemBar node that 
   // will do an acquire. If so, this node must not do the acquire
   // operation.
@@ -1114,6 +1121,40 @@
 
 //=============================================================================
 
+%} // interrupt source
+
+source_hpp %{ // Header information of the source block.
+
+//--------------------------------------------------------------
+//---<  Used for optimization in Compile::Shorten_branches  >---
+//--------------------------------------------------------------
+
+const uint trampoline_stub_size     =  6 * BytesPerInstWord;
+
+class CallStubImpl {
+
+ public:
+
+  static void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset);
+
+  // Size of call trampoline stub.
+  // This doesn't need to be accurate to the byte, but it
+  // must be larger than or equal to the real size of the stub.
+  static uint size_call_trampoline() {
+    return trampoline_stub_size;
+  }
+
+  // number of relocations needed by a call trampoline stub
+  static uint reloc_call_trampoline() {
+    return 5;
+  }
+
+};
+
+%} // end source_hpp
+
+source %{
+
 // Emit a trampoline stub for a call to a target which is too far away.
 //
 // code sequences:
@@ -1125,9 +1166,7 @@
 //   load the call target from the constant pool
 //   branch via CTR (LR/link still points to the call-site above)
 
-const uint trampoline_stub_size = 6 * BytesPerInstWord;
-
-void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
+void CallStubImpl::emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
   // Start the stub.
   address stub = __ start_a_stub(Compile::MAX_stubs_size/2);
   if (stub == NULL) {
@@ -1170,19 +1209,6 @@
   __ end_a_stub();
 }
 
-// Size of trampoline stub, this doesn't need to be accurate but it must
-// be larger or equal to the real size of the stub.
-// Used for optimization in Compile::Shorten_branches.
-uint size_call_trampoline() {
-  return trampoline_stub_size;
-}
-
-// Number of relocation entries needed by trampoline stub.
-// Used for optimization in Compile::Shorten_branches.
-uint reloc_call_trampoline() {
-  return 5;
-}
-
 //=============================================================================
 
 // Emit an inline branch-and-link call and a related trampoline stub.
@@ -1221,7 +1247,7 @@
     const int     entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
 
     // Emit the trampoline stub which will be related to the branch-and-link below.
-    emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
+    CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
     __ relocate(rtype);
   }
 
@@ -2023,17 +2049,34 @@
 
 //=============================================================================
 
-uint size_exception_handler() {
-  // The exception_handler is a b64_patchable.
-  return MacroAssembler::b64_patchable_size;
-}
-
-uint size_deopt_handler() {
-  // The deopt_handler is a bl64_patchable.
-  return MacroAssembler::bl64_patchable_size;
-}
-
-int emit_exception_handler(CodeBuffer &cbuf) {
+%} // interrupt source
+
+source_hpp %{ // Header information of the source block.
+
+class HandlerImpl {
+
+ public:
+
+  static int emit_exception_handler(CodeBuffer &cbuf);
+  static int emit_deopt_handler(CodeBuffer& cbuf);
+
+  static uint size_exception_handler() {
+    // The exception_handler is a b64_patchable.
+    return MacroAssembler::b64_patchable_size;
+  }
+
+  static uint size_deopt_handler() {
+    // The deopt_handler is a bl64_patchable.
+    return MacroAssembler::bl64_patchable_size;
+  }
+
+};
+
+%} // end source_hpp
+
+source %{
+
+int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
   MacroAssembler _masm(&cbuf);
 
   address base = __ start_a_stub(size_exception_handler());
@@ -2050,7 +2093,7 @@
 
 // The deopt_handler is like the exception handler, but it calls to
 // the deoptimization blob instead of jumping to the exception blob.
-int emit_deopt_handler(CodeBuffer& cbuf) {
+int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
   MacroAssembler _masm(&cbuf);
 
   address base = __ start_a_stub(size_deopt_handler());
@@ -3438,7 +3481,7 @@
         const int     entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
 
         // Emit the trampoline stub which will be related to the branch-and-link below.
-        emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
+        CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
         __ relocate(_optimized_virtual ?
                     relocInfo::opt_virtual_call_type : relocInfo::static_call_type);
       }
@@ -3481,7 +3524,7 @@
       const int     entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
 
       // Emit the trampoline stub which will be related to the branch-and-link below.
-      emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
+      CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
       assert(_optimized_virtual, "methodHandle call should be a virtual call");
       __ relocate(relocInfo::opt_virtual_call_type);
     }
@@ -3531,7 +3574,7 @@
       const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method;
       const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none);
       const int entry_point_const_toc_offset = __ offset_to_method_toc(entry_point_const);
-      emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset());
+      CallStubImpl::emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset());
 
       if (ra_->C->env()->failing())
         return;
@@ -8755,6 +8798,7 @@
 // Single-precision sqrt.
 instruct sqrtF_reg(regF dst, regF src) %{
   match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
+  predicate(VM_Version::has_fsqrts());
   ins_cost(DEFAULT_COST);
 
   format %{ "FSQRTS  $dst, $src" %}
@@ -11550,8 +11594,7 @@
   // effect no longer needs to be mentioned, since r0 is not contained
   // in a reg_class.
 
-  format %{ "LD      R12, addr of polling page\n\t"
-            "LD      R0, #0, R12 \t// Safepoint poll for GC" %}
+  format %{ "LD      R0, #0, R12 \t// Safepoint poll for GC" %}
   ins_encode( enc_poll(0x0, poll) );
   ins_pipe(pipe_class_default);
 %}
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -34,6 +34,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/vframeArray.hpp"
 #include "vmreg_ppc.inline.hpp"
+#include "adfiles/ad_ppc_64.hpp"
 #ifdef COMPILER1
 #include "c1/c1_Runtime1.hpp"
 #endif
@@ -52,10 +53,6 @@
 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
 
 
-// Used by generate_deopt_blob.  Defined in .ad file.
-extern uint size_deopt_handler();
-
-
 class RegisterSaver {
  // Used for saving volatile registers.
  public:
@@ -2782,7 +2779,7 @@
   // We can't grab a free register here, because all registers may
   // contain live values, so let the RegisterSaver do the adjustment
   // of the return pc.
-  const int return_pc_adjustment_no_exception = -size_deopt_handler();
+  const int return_pc_adjustment_no_exception = -HandlerImpl::size_deopt_handler();
 
   // Push the "unpack frame"
   // Save everything in sight.
--- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,6 @@
  *
  */
 
-#include "precompiled.hpp"
-#include "runtime/deoptimization.hpp"
-#include "runtime/frame.inline.hpp"
-#include "runtime/stubRoutines.hpp"
-#ifdef TARGET_OS_FAMILY_aix
-# include "thread_aix.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_linux
-# include "thread_linux.inline.hpp"
-#endif
-
 // Implementation of the platform-specific part of StubRoutines - for
 // a description of how to extend it, see the stubRoutines.hpp file.
 
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1672,7 +1672,7 @@
   //__ flush_bundle();
   address entry = __ pc();
 
-  char *bname = NULL;
+  const char *bname = NULL;
   uint tsize = 0;
   switch(state) {
   case ftos:
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -402,6 +402,9 @@
   CodeBuffer cb("detect_cpu_features", code_size, 0);
   MacroAssembler* a = new MacroAssembler(&cb);
 
+  // Must be set to true so we can generate the test code.
+  _features = VM_Version::all_features_m;
+
   // Emit code.
   void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry();
   uint32_t *code = (uint32_t *)a->pc();
@@ -409,14 +412,15 @@
   // Keep R3_ARG1 unmodified, it contains &field (see below).
   // Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
   a->fsqrt(F3, F4);                            // code[0] -> fsqrt_m
-  a->isel(R7, R5, R6, 0);                      // code[1] -> isel_m
-  a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[2] -> lxarx_m
-  a->cmpb(R7, R5, R6);                         // code[3] -> bcmp
-  //a->mftgpr(R7, F3);                         // code[4] -> mftgpr
-  a->popcntb(R7, R5);                          // code[5] -> popcntb
-  a->popcntw(R7, R5);                          // code[6] -> popcntw
-  a->fcfids(F3, F4);                           // code[7] -> fcfids
-  a->vand(VR0, VR0, VR0);                      // code[8] -> vand
+  a->fsqrts(F3, F4);                           // code[1] -> fsqrts_m
+  a->isel(R7, R5, R6, 0);                      // code[2] -> isel_m
+  a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
+  a->cmpb(R7, R5, R6);                         // code[4] -> bcmp
+  //a->mftgpr(R7, F3);                         // code[5] -> mftgpr
+  a->popcntb(R7, R5);                          // code[6] -> popcntb
+  a->popcntw(R7, R5);                          // code[7] -> popcntw
+  a->fcfids(F3, F4);                           // code[8] -> fcfids
+  a->vand(VR0, VR0, VR0);                      // code[9] -> vand
   a->blr();
 
   // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@@ -426,6 +430,7 @@
 
   uint32_t *code_end = (uint32_t *)a->pc();
   a->flush();
+  _features = VM_Version::unknown_m;
 
   // Print the detection code.
   if (PrintAssembly) {
@@ -450,6 +455,7 @@
   // determine which instructions are legal.
   int feature_cntr = 0;
   if (code[feature_cntr++]) features |= fsqrt_m;
+  if (code[feature_cntr++]) features |= fsqrts_m;
   if (code[feature_cntr++]) features |= isel_m;
   if (code[feature_cntr++]) features |= lxarxeh_m;
   if (code[feature_cntr++]) features |= cmpb_m;
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 protected:
   enum Feature_Flag {
     fsqrt,
+    fsqrts,
     isel,
     lxarxeh,
     cmpb,
@@ -46,6 +47,7 @@
   enum Feature_Flag_Set {
     unknown_m             = 0,
     fsqrt_m               = (1 << fsqrt  ),
+    fsqrts_m              = (1 << fsqrts ),
     isel_m                = (1 << isel   ),
     lxarxeh_m             = (1 << lxarxeh),
     cmpb_m                = (1 << cmpb   ),
@@ -72,6 +74,7 @@
   static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
   // CPU instruction support
   static bool has_fsqrt()   { return (_features & fsqrt_m) != 0; }
+  static bool has_fsqrts()  { return (_features & fsqrts_m) != 0; }
   static bool has_isel()    { return (_features & isel_m) != 0; }
   static bool has_lxarxeh() { return (_features & lxarxeh_m) !=0; }
   static bool has_cmpb()    { return (_features & cmpb_m) != 0; }
--- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
   address npe_addr = __ pc(); // npe = null pointer exception
   __ load_klass_with_trap_null_check(rcvr_klass, R3);
 
- // Set methodOop (in case of interpreted method), and destination address.
+ // Set method (in case of interpreted method), and destination address.
   int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
 
 #ifndef PRODUCT
@@ -161,8 +161,6 @@
   address npe_addr = __ pc(); // npe = null pointer exception
   __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1);
 
-  //__ ld(rcvr_klass, oopDesc::klass_offset_in_bytes(), R3_ARG1);
-
   BLOCK_COMMENT("Load start of itable entries into itable_entry.");
   __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass);
   __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize));
@@ -199,7 +197,7 @@
                                    itable_offset_search_inc;
   __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr);
 
-  // Compute itableMethodEntry and get methodOop and entry point for compiler.
+  // Compute itableMethodEntry and get method and entry point for compiler.
   const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
     itableMethodEntry::method_offset_in_bytes();
 
@@ -211,7 +209,7 @@
     Label ok;
     __ cmpd(CCR0, R19_method, 0);
     __ bne(CCR0, ok);
-    __ stop("methodOop is null", 103);
+    __ stop("method is null", 103);
     __ bind(ok);
   }
 #endif
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -3320,7 +3320,7 @@
 
   // if tmp is invalid, then the function being called doesn't destroy the thread
   if (tmp->is_valid()) {
-    __ save_thread(tmp->as_register());
+    __ save_thread(tmp->as_pointer_register());
   }
   __ call(dest, relocInfo::runtime_call_type);
   __ delayed()->nop();
@@ -3328,7 +3328,7 @@
     add_call_info_here(info);
   }
   if (tmp->is_valid()) {
-    __ restore_thread(tmp->as_register());
+    __ restore_thread(tmp->as_pointer_register());
   }
 
 #ifdef ASSERT
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -69,7 +69,7 @@
 LIR_Opr LIRGenerator::exceptionOopOpr()              { return FrameMap::Oexception_opr;  }
 LIR_Opr LIRGenerator::exceptionPcOpr()               { return FrameMap::Oissuing_pc_opr; }
 LIR_Opr LIRGenerator::syncTempOpr()                  { return new_register(T_OBJECT); }
-LIR_Opr LIRGenerator::getThreadTemp()                { return rlock_callee_saved(T_INT); }
+LIR_Opr LIRGenerator::getThreadTemp()                { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); }
 
 LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) {
   LIR_Opr opr;
--- a/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -66,6 +66,4 @@
 define_pd_global(bool, CSEArrayLength,               true );
 define_pd_global(bool, TwoOperandLIRForm,            false);
 
-define_pd_global(intx, SafepointPollOffset,          0    );
-
 #endif // CPU_SPARC_VM_C1_GLOBALS_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 19:35:40 2017 +0200
@@ -457,6 +457,13 @@
 // This is a block of C++ code which provides values, functions, and
 // definitions necessary in the rest of the architecture description
 source_hpp %{
+// Header information of the source block.
+// Method declarations/definitions which are used outside
+// the ad-scope can conveniently be defined here.
+//
+// To keep related declarations/definitions/uses close together,
+// we switch between source %{ }% and source_hpp %{ }% freely as needed.
+
 // Must be visible to the DFA in dfa_sparc.cpp
 extern bool can_branch_register( Node *bol, Node *cmp );
 
@@ -468,6 +475,46 @@
 #define LONG_HI_REG(x) (x)
 #define LONG_LO_REG(x) (x)
 
+class CallStubImpl {
+
+  //--------------------------------------------------------------
+  //---<  Used for optimization in Compile::Shorten_branches  >---
+  //--------------------------------------------------------------
+
+ public:
+  // Size of call trampoline stub.
+  static uint size_call_trampoline() {
+    return 0; // no call trampolines on this platform
+  }
+
+  // number of relocations needed by a call trampoline stub
+  static uint reloc_call_trampoline() {
+    return 0; // no call trampolines on this platform
+  }
+};
+
+class HandlerImpl {
+
+ public:
+
+  static int emit_exception_handler(CodeBuffer &cbuf);
+  static int emit_deopt_handler(CodeBuffer& cbuf);
+
+  static uint size_exception_handler() {
+    if (TraceJumps) {
+      return (400); // just a guess
+    }
+    return ( NativeJump::instruction_size ); // sethi;jmp;nop
+  }
+
+  static uint size_deopt_handler() {
+    if (TraceJumps) {
+      return (400); // just a guess
+    }
+    return ( 4+  NativeJump::instruction_size ); // save;sethi;jmp;restore
+  }
+};
+
 %}
 
 source %{
@@ -1710,22 +1757,9 @@
 
 //=============================================================================
 
-uint size_exception_handler() {
-  if (TraceJumps) {
-    return (400); // just a guess
-  }
-  return ( NativeJump::instruction_size ); // sethi;jmp;nop
-}
-
-uint size_deopt_handler() {
-  if (TraceJumps) {
-    return (400); // just a guess
-  }
-  return ( 4+  NativeJump::instruction_size ); // save;sethi;jmp;restore
-}
 
 // Emit exception handler code.
-int emit_exception_handler(CodeBuffer& cbuf) {
+int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
   Register temp_reg = G3;
   AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point());
   MacroAssembler _masm(&cbuf);
@@ -1746,7 +1780,7 @@
   return offset;
 }
 
-int emit_deopt_handler(CodeBuffer& cbuf) {
+int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
   // Can't use any of the current frame's registers as we may have deopted
   // at a poll and everything (including G3) can be live.
   Register temp_reg = L0;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1112,7 +1112,6 @@
 }
 
 void Assembler::bsrl(Register dst, Register src) {
-  assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
   int encode = prefix_and_encode(dst->encoding(), src->encoding());
   emit_int8(0x0F);
   emit_int8((unsigned char)0xBD);
@@ -2343,6 +2342,11 @@
   emit_int8(imm8);
 }
 
+void Assembler::pause() {
+  emit_int8((unsigned char)0xF3);
+  emit_int8((unsigned char)0x90);
+}
+
 void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
   assert(VM_Version::supports_sse4_2(), "");
   InstructionMark im(this);
@@ -2667,6 +2671,11 @@
   }
 }
 
+void Assembler::rdtsc() {
+  emit_int8((unsigned char)0x0F);
+  emit_int8((unsigned char)0x31);
+}
+
 // copies data from [esi] to [edi] using rcx pointer sized words
 // generic
 void Assembler::rep_mov() {
@@ -2976,6 +2985,11 @@
   emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE);
 }
 
+void Assembler::xabort(int8_t imm8) {
+  emit_int8((unsigned char)0xC6);
+  emit_int8((unsigned char)0xF8);
+  emit_int8((unsigned char)(imm8 & 0xFF));
+}
 
 void Assembler::xaddl(Address dst, Register src) {
   InstructionMark im(this);
@@ -2985,6 +2999,24 @@
   emit_operand(src, dst);
 }
 
+void Assembler::xbegin(Label& abort, relocInfo::relocType rtype) {
+  InstructionMark im(this);
+  relocate(rtype);
+  if (abort.is_bound()) {
+    address entry = target(abort);
+    assert(entry != NULL, "abort entry NULL");
+    intptr_t offset = entry - pc();
+    emit_int8((unsigned char)0xC7);
+    emit_int8((unsigned char)0xF8);
+    emit_int32(offset - 6); // 2 opcode + 4 address
+  } else {
+    abort.add_patch_at(code(), locator());
+    emit_int8((unsigned char)0xC7);
+    emit_int8((unsigned char)0xF8);
+    emit_int32(0);
+  }
+}
+
 void Assembler::xchgl(Register dst, Address src) { // xchg
   InstructionMark im(this);
   prefix(src, dst);
@@ -2998,6 +3030,12 @@
   emit_int8((unsigned char)(0xC0 | encode));
 }
 
+void Assembler::xend() {
+  emit_int8((unsigned char)0x0F);
+  emit_int8((unsigned char)0x01);
+  emit_int8((unsigned char)0xD5);
+}
+
 void Assembler::xgetbv() {
   emit_int8(0x0F);
   emit_int8(0x01);
@@ -4938,7 +4976,6 @@
 }
 
 void Assembler::bsrq(Register dst, Register src) {
-  assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
   int encode = prefixq_and_encode(dst->encoding(), src->encoding());
   emit_int8(0x0F);
   emit_int8((unsigned char)0xBD);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1451,6 +1451,8 @@
   // Pemutation of 64bit words
   void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256);
 
+  void pause();
+
   // SSE4.2 string instructions
   void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
   void pcmpestri(XMMRegister xmm1, Address src, int imm8);
@@ -1535,6 +1537,8 @@
 
   void rclq(Register dst, int imm8);
 
+  void rdtsc();
+
   void ret(int imm16);
 
   void sahf();
@@ -1632,16 +1636,22 @@
   void ucomiss(XMMRegister dst, Address src);
   void ucomiss(XMMRegister dst, XMMRegister src);
 
+  void xabort(int8_t imm8);
+
   void xaddl(Address dst, Register src);
 
   void xaddq(Address dst, Register src);
 
+  void xbegin(Label& abort, relocInfo::relocType rtype = relocInfo::none);
+
   void xchgl(Register reg, Address adr);
   void xchgl(Register dst, Register src);
 
   void xchgq(Register reg, Address adr);
   void xchgq(Register dst, Register src);
 
+  void xend();
+
   // Get Value of Extended Control Register
   void xgetbv();
 
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -604,8 +604,7 @@
 
   // Note: we do not need to round double result; float result has the right precision
   // the poll sets the condition code, but no data registers
-  AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
-                              relocInfo::poll_return_type);
+  AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
 
   if (Assembler::is_polling_page_far()) {
     __ lea(rscratch1, polling_page);
@@ -619,8 +618,7 @@
 
 
 int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
-  AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
-                              relocInfo::poll_type);
+  AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
   guarantee(info != NULL, "Shouldn't be NULL");
   int offset = __ offset();
   if (Assembler::is_polling_page_far()) {
@@ -801,7 +799,13 @@
         if (UseCompressedOops && !wide) {
           __ movl(as_Address(addr), (int32_t)NULL_WORD);
         } else {
+#ifdef _LP64
+          __ xorptr(rscratch1, rscratch1);
+          null_check_here = code_offset();
+          __ movptr(as_Address(addr), rscratch1);
+#else
           __ movptr(as_Address(addr), NULL_WORD);
+#endif
         }
       } else {
         if (is_literal_address(addr)) {
--- a/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -65,6 +65,4 @@
 define_pd_global(bool, CSEArrayLength,               false);
 define_pd_global(bool, TwoOperandLIRForm,            true );
 
-define_pd_global(intx, SafepointPollOffset,          256  );
-
 #endif // CPU_X86_VM_C1_GLOBALS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -129,6 +129,42 @@
   product(bool, UseFastStosb, false,                                        \
           "Use fast-string operation for zeroing: rep stosb")               \
                                                                             \
+  /* Use Restricted Transactional Memory for lock eliding */                \
+  product(bool, UseRTMLocking, false,                                       \
+          "Enable RTM lock eliding for inflated locks in compiled code")    \
+                                                                            \
+  experimental(bool, UseRTMForStackLocks, false,                            \
+          "Enable RTM lock eliding for stack locks in compiled code")       \
+                                                                            \
+  product(bool, UseRTMDeopt, false,                                         \
+          "Perform deopt and recompilation based on RTM abort ratio")       \
+                                                                            \
+  product(uintx, RTMRetryCount, 5,                                          \
+          "Number of RTM retries on lock abort or busy")                    \
+                                                                            \
+  experimental(intx, RTMSpinLoopCount, 100,                                 \
+          "Spin count for lock to become free before RTM retry")            \
+                                                                            \
+  experimental(intx, RTMAbortThreshold, 1000,                               \
+          "Calculate abort ratio after this number of aborts")              \
+                                                                            \
+  experimental(intx, RTMLockingThreshold, 10000,                            \
+          "Lock count at which to do RTM lock eliding without "             \
+          "abort ratio calculation")                                        \
+                                                                            \
+  experimental(intx, RTMAbortRatio, 50,                                     \
+          "Lock abort ratio at which to stop use RTM lock eliding")         \
+                                                                            \
+  experimental(intx, RTMTotalCountIncrRate, 64,                             \
+          "Increment total RTM attempted lock count once every n times")    \
+                                                                            \
+  experimental(intx, RTMLockingCalculationDelay, 0,                         \
+          "Number of milliseconds to wait before start calculating aborts " \
+          "for RTM locking")                                                \
+                                                                            \
+  experimental(bool, UseRTMXendForLockBusy, false,                          \
+          "Use RTM Xend instead of Xabort when lock busy")                  \
+                                                                            \
   /* assembler */                                                           \
   product(bool, Use486InstrsOnly, false,                                    \
           "Use 80486 Compliant instruction subset")                         \
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -301,7 +301,9 @@
   mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate());
 }
 
-void MacroAssembler::movptr(Register dst, AddressLiteral src) {
+void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) {
+  // scratch register is not used,
+  // it is defined to match parameters of 64-bit version of this method.
   if (src.is_lval()) {
     mov_literal32(dst, (intptr_t)src.target(), src.rspec());
   } else {
@@ -613,6 +615,15 @@
   /* else */      { subq(dst, value)       ; return; }
 }
 
+void MacroAssembler::incrementq(AddressLiteral dst) {
+  if (reachable(dst)) {
+    incrementq(as_Address(dst));
+  } else {
+    lea(rscratch1, dst);
+    incrementq(Address(rscratch1, 0));
+  }
+}
+
 void MacroAssembler::incrementq(Register reg, int value) {
   if (value == min_jint) { addq(reg, value); return; }
   if (value <  0) { decrementq(reg, -value); return; }
@@ -681,15 +692,15 @@
   movq(dst, rscratch1);
 }
 
-void MacroAssembler::movptr(Register dst, AddressLiteral src) {
+void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) {
   if (src.is_lval()) {
     mov_literal64(dst, (intptr_t)src.target(), src.rspec());
   } else {
     if (reachable(src)) {
       movq(dst, as_Address(src));
     } else {
-      lea(rscratch1, src);
-      movq(dst, Address(rscratch1,0));
+      lea(scratch, src);
+      movq(dst, Address(scratch, 0));
     }
   }
 }
@@ -988,20 +999,37 @@
   LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32));
 }
 
-void MacroAssembler::atomic_incl(AddressLiteral counter_addr) {
-  pushf();
+void MacroAssembler::atomic_incl(Address counter_addr) {
+  if (os::is_MP())
+    lock();
+  incrementl(counter_addr);
+}
+
+void MacroAssembler::atomic_incl(AddressLiteral counter_addr, Register scr) {
   if (reachable(counter_addr)) {
-    if (os::is_MP())
-      lock();
-    incrementl(as_Address(counter_addr));
+    atomic_incl(as_Address(counter_addr));
   } else {
-    lea(rscratch1, counter_addr);
-    if (os::is_MP())
-      lock();
-    incrementl(Address(rscratch1, 0));
-  }
-  popf();
-}
+    lea(scr, counter_addr);
+    atomic_incl(Address(scr, 0));
+  }
+}
+
+#ifdef _LP64
+void MacroAssembler::atomic_incq(Address counter_addr) {
+  if (os::is_MP())
+    lock();
+  incrementq(counter_addr);
+}
+
+void MacroAssembler::atomic_incq(AddressLiteral counter_addr, Register scr) {
+  if (reachable(counter_addr)) {
+    atomic_incq(as_Address(counter_addr));
+  } else {
+    lea(scr, counter_addr);
+    atomic_incq(Address(scr, 0));
+  }
+}
+#endif
 
 // Writes to stack successive pages until offset reached to check for
 // stack overflow + shadow pages.  This clobbers tmp.
@@ -1274,6 +1302,325 @@
 }
 
 #ifdef COMPILER2
+
+#if INCLUDE_RTM_OPT
+
+// Update rtm_counters based on abort status
+// input: abort_status
+//        rtm_counters (RTMLockingCounters*)
+// flags are killed
+void MacroAssembler::rtm_counters_update(Register abort_status, Register rtm_counters) {
+
+  atomic_incptr(Address(rtm_counters, RTMLockingCounters::abort_count_offset()));
+  if (PrintPreciseRTMLockingStatistics) {
+    for (int i = 0; i < RTMLockingCounters::ABORT_STATUS_LIMIT; i++) {
+      Label check_abort;
+      testl(abort_status, (1<<i));
+      jccb(Assembler::equal, check_abort);
+      atomic_incptr(Address(rtm_counters, RTMLockingCounters::abortX_count_offset() + (i * sizeof(uintx))));
+      bind(check_abort);
+    }
+  }
+}
+
+// Branch if (random & (count-1) != 0), count is 2^n
+// tmp, scr and flags are killed
+void MacroAssembler::branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel) {
+  assert(tmp == rax, "");
+  assert(scr == rdx, "");
+  rdtsc(); // modifies EDX:EAX
+  andptr(tmp, count-1);
+  jccb(Assembler::notZero, brLabel);
+}
+
+// Perform abort ratio calculation, set no_rtm bit if high ratio
+// input:  rtm_counters_Reg (RTMLockingCounters* address)
+// tmpReg, rtm_counters_Reg and flags are killed
+void MacroAssembler::rtm_abort_ratio_calculation(Register tmpReg,
+                                                 Register rtm_counters_Reg,
+                                                 RTMLockingCounters* rtm_counters,
+                                                 Metadata* method_data) {
+  Label L_done, L_check_always_rtm1, L_check_always_rtm2;
+
+  if (RTMLockingCalculationDelay > 0) {
+    // Delay calculation
+    movptr(tmpReg, ExternalAddress((address) RTMLockingCounters::rtm_calculation_flag_addr()), tmpReg);
+    testptr(tmpReg, tmpReg);
+    jccb(Assembler::equal, L_done);
+  }
+  // Abort ratio calculation only if abort_count > RTMAbortThreshold
+  //   Aborted transactions = abort_count * 100
+  //   All transactions = total_count *  RTMTotalCountIncrRate
+  //   Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio)
+
+  movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::abort_count_offset()));
+  cmpptr(tmpReg, RTMAbortThreshold);
+  jccb(Assembler::below, L_check_always_rtm2);
+  imulptr(tmpReg, tmpReg, 100);
+
+  Register scrReg = rtm_counters_Reg;
+  movptr(scrReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset()));
+  imulptr(scrReg, scrReg, RTMTotalCountIncrRate);
+  imulptr(scrReg, scrReg, RTMAbortRatio);
+  cmpptr(tmpReg, scrReg);
+  jccb(Assembler::below, L_check_always_rtm1);
+  if (method_data != NULL) {
+    // set rtm_state to "no rtm" in MDO
+    mov_metadata(tmpReg, method_data);
+    if (os::is_MP()) {
+      lock();
+    }
+    orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), NoRTM);
+  }
+  jmpb(L_done);
+  bind(L_check_always_rtm1);
+  // Reload RTMLockingCounters* address
+  lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters));
+  bind(L_check_always_rtm2);
+  movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset()));
+  cmpptr(tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate);
+  jccb(Assembler::below, L_done);
+  if (method_data != NULL) {
+    // set rtm_state to "always rtm" in MDO
+    mov_metadata(tmpReg, method_data);
+    if (os::is_MP()) {
+      lock();
+    }
+    orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), UseRTM);
+  }
+  bind(L_done);
+}
+
+// Update counters and perform abort ratio calculation
+// input:  abort_status_Reg
+// rtm_counters_Reg, flags are killed
+void MacroAssembler::rtm_profiling(Register abort_status_Reg,
+                                   Register rtm_counters_Reg,
+                                   RTMLockingCounters* rtm_counters,
+                                   Metadata* method_data,
+                                   bool profile_rtm) {
+
+  assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
+  // update rtm counters based on rax value at abort
+  // reads abort_status_Reg, updates flags
+  lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters));
+  rtm_counters_update(abort_status_Reg, rtm_counters_Reg);
+  if (profile_rtm) {
+    // Save abort status because abort_status_Reg is used by following code.
+    if (RTMRetryCount > 0) {
+      push(abort_status_Reg);
+    }
+    assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
+    rtm_abort_ratio_calculation(abort_status_Reg, rtm_counters_Reg, rtm_counters, method_data);
+    // restore abort status
+    if (RTMRetryCount > 0) {
+      pop(abort_status_Reg);
+    }
+  }
+}
+
+// Retry on abort if abort's status is 0x6: can retry (0x2) | memory conflict (0x4)
+// inputs: retry_count_Reg
+//       : abort_status_Reg
+// output: retry_count_Reg decremented by 1
+// flags are killed
+void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register abort_status_Reg, Label& retryLabel) {
+  Label doneRetry;
+  assert(abort_status_Reg == rax, "");
+  // The abort reason bits are in eax (see all states in rtmLocking.hpp)
+  // 0x6 = conflict on which we can retry (0x2) | memory conflict (0x4)
+  // if reason is in 0x6 and retry count != 0 then retry
+  andptr(abort_status_Reg, 0x6);
+  jccb(Assembler::zero, doneRetry);
+  testl(retry_count_Reg, retry_count_Reg);
+  jccb(Assembler::zero, doneRetry);
+  pause();
+  decrementl(retry_count_Reg);
+  jmp(retryLabel);
+  bind(doneRetry);
+}
+
+// Spin and retry if lock is busy,
+// inputs: box_Reg (monitor address)
+//       : retry_count_Reg
+// output: retry_count_Reg decremented by 1
+//       : clear z flag if retry count exceeded
+// tmp_Reg, scr_Reg, flags are killed
+void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg,
+                                            Register tmp_Reg, Register scr_Reg, Label& retryLabel) {
+  Label SpinLoop, SpinExit, doneRetry;
+  // Clean monitor_value bit to get valid pointer
+  int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
+
+  testl(retry_count_Reg, retry_count_Reg);
+  jccb(Assembler::zero, doneRetry);
+  decrementl(retry_count_Reg);
+  movptr(scr_Reg, RTMSpinLoopCount);
+
+  bind(SpinLoop);
+  pause();
+  decrementl(scr_Reg);
+  jccb(Assembler::lessEqual, SpinExit);
+  movptr(tmp_Reg, Address(box_Reg, owner_offset));
+  testptr(tmp_Reg, tmp_Reg);
+  jccb(Assembler::notZero, SpinLoop);
+
+  bind(SpinExit);
+  jmp(retryLabel);
+  bind(doneRetry);
+  incrementl(retry_count_Reg); // clear z flag
+}
+
+// Use RTM for normal stack locks
+// Input: objReg (object to lock)
+void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Register scrReg,
+                                       Register retry_on_abort_count_Reg,
+                                       RTMLockingCounters* stack_rtm_counters,
+                                       Metadata* method_data, bool profile_rtm,
+                                       Label& DONE_LABEL, Label& IsInflated) {
+  assert(UseRTMForStackLocks, "why call this otherwise?");
+  assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking");
+  assert(tmpReg == rax, "");
+  assert(scrReg == rdx, "");
+  Label L_rtm_retry, L_decrement_retry, L_on_abort;
+
+  if (RTMRetryCount > 0) {
+    movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort
+    bind(L_rtm_retry);
+  }
+  if (!UseRTMXendForLockBusy) {
+    movptr(tmpReg, Address(objReg, 0));
+    testptr(tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
+    jcc(Assembler::notZero, IsInflated);
+  }
+  if (PrintPreciseRTMLockingStatistics || profile_rtm) {
+    Label L_noincrement;
+    if (RTMTotalCountIncrRate > 1) {
+      // tmpReg, scrReg and flags are killed
+      branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement);
+    }
+    assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM");
+    atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg);
+    bind(L_noincrement);
+  }
+  xbegin(L_on_abort);
+  movptr(tmpReg, Address(objReg, 0));       // fetch markword
+  andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits
+  cmpptr(tmpReg, markOopDesc::unlocked_value);            // bits = 001 unlocked
+  jcc(Assembler::equal, DONE_LABEL);        // all done if unlocked
+
+  Register abort_status_Reg = tmpReg; // status of abort is stored in RAX
+  if (UseRTMXendForLockBusy) {
+    xend();
+    movptr(tmpReg, Address(objReg, 0));
+    testptr(tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
+    jcc(Assembler::notZero, IsInflated);
+    movptr(abort_status_Reg, 0x1);                // Set the abort status to 1 (as xabort does)
+    jmp(L_decrement_retry);
+  }
+  else {
+    xabort(0);
+  }
+  bind(L_on_abort);
+  if (PrintPreciseRTMLockingStatistics || profile_rtm) {
+    rtm_profiling(abort_status_Reg, scrReg, stack_rtm_counters, method_data, profile_rtm);
+  }
+  bind(L_decrement_retry);
+  if (RTMRetryCount > 0) {
+    // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4)
+    rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry);
+  }
+}
+
+// Use RTM for inflating locks
+// inputs: objReg (object to lock)
+//         boxReg (on-stack box address (displaced header location) - KILLED)
+//         tmpReg (ObjectMonitor address + 2(monitor_value))
+void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg,
+                                          Register scrReg, Register retry_on_busy_count_Reg,
+                                          Register retry_on_abort_count_Reg,
+                                          RTMLockingCounters* rtm_counters,
+                                          Metadata* method_data, bool profile_rtm,
+                                          Label& DONE_LABEL) {
+  assert(UseRTMLocking, "why call this otherwise?");
+  assert(tmpReg == rax, "");
+  assert(scrReg == rdx, "");
+  Label L_rtm_retry, L_decrement_retry, L_on_abort;
+  // Clean monitor_value bit to get valid pointer
+  int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
+
+  // Without cast to int32_t a movptr will destroy r10 which is typically obj
+  movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
+  movptr(boxReg, tmpReg); // Save ObjectMonitor address
+
+  if (RTMRetryCount > 0) {
+    movl(retry_on_busy_count_Reg, RTMRetryCount);  // Retry on lock busy
+    movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort
+    bind(L_rtm_retry);
+  }
+  if (PrintPreciseRTMLockingStatistics || profile_rtm) {
+    Label L_noincrement;
+    if (RTMTotalCountIncrRate > 1) {
+      // tmpReg, scrReg and flags are killed
+      branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement);
+    }
+    assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
+    atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg);
+    bind(L_noincrement);
+  }
+  xbegin(L_on_abort);
+  movptr(tmpReg, Address(objReg, 0));
+  movptr(tmpReg, Address(tmpReg, owner_offset));
+  testptr(tmpReg, tmpReg);
+  jcc(Assembler::zero, DONE_LABEL);
+  if (UseRTMXendForLockBusy) {
+    xend();
+    jmp(L_decrement_retry);
+  }
+  else {
+    xabort(0);
+  }
+  bind(L_on_abort);
+  Register abort_status_Reg = tmpReg; // status of abort is stored in RAX
+  if (PrintPreciseRTMLockingStatistics || profile_rtm) {
+    rtm_profiling(abort_status_Reg, scrReg, rtm_counters, method_data, profile_rtm);
+  }
+  if (RTMRetryCount > 0) {
+    // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4)
+    rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry);
+  }
+
+  movptr(tmpReg, Address(boxReg, owner_offset)) ;
+  testptr(tmpReg, tmpReg) ;
+  jccb(Assembler::notZero, L_decrement_retry) ;
+
+  // Appears unlocked - try to swing _owner from null to non-null.
+  // Invariant: tmpReg == 0.  tmpReg is EAX which is the implicit cmpxchg comparand.
+#ifdef _LP64
+  Register threadReg = r15_thread;
+#else
+  get_thread(scrReg);
+  Register threadReg = scrReg;
+#endif
+  if (os::is_MP()) {
+    lock();
+  }
+  cmpxchgptr(threadReg, Address(boxReg, owner_offset)); // Updates tmpReg
+
+  if (RTMRetryCount > 0) {
+    // success done else retry
+    jccb(Assembler::equal, DONE_LABEL) ;
+    bind(L_decrement_retry);
+    // Spin and retry if lock is busy.
+    rtm_retry_lock_on_busy(retry_on_busy_count_Reg, boxReg, tmpReg, scrReg, L_rtm_retry);
+  }
+  else {
+    bind(L_decrement_retry);
+  }
+}
+
+#endif //  INCLUDE_RTM_OPT
+
 // Fast_Lock and Fast_Unlock used by C2
 
 // Because the transitions from emitted code to the runtime
@@ -1350,17 +1697,26 @@
 // box: on-stack box address (displaced header location) - KILLED
 // rax,: tmp -- KILLED
 // scr: tmp -- KILLED
-void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, Register scrReg, BiasedLockingCounters* counters) {
+void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg,
+                               Register scrReg, Register cx1Reg, Register cx2Reg,
+                               BiasedLockingCounters* counters,
+                               RTMLockingCounters* rtm_counters,
+                               RTMLockingCounters* stack_rtm_counters,
+                               Metadata* method_data,
+                               bool use_rtm, bool profile_rtm) {
   // Ensure the register assignents are disjoint
-  guarantee (objReg != boxReg, "");
-  guarantee (objReg != tmpReg, "");
-  guarantee (objReg != scrReg, "");
-  guarantee (boxReg != tmpReg, "");
-  guarantee (boxReg != scrReg, "");
-  guarantee (tmpReg == rax, "");
+  assert(tmpReg == rax, "");
+
+  if (use_rtm) {
+    assert_different_registers(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg);
+  } else {
+    assert(cx1Reg == noreg, "");
+    assert(cx2Reg == noreg, "");
+    assert_different_registers(objReg, boxReg, tmpReg, scrReg);
+  }
 
   if (counters != NULL) {
-    atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()));
+    atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()), scrReg);
   }
   if (EmitSync & 1) {
       // set box->dhw = unused_mark (3)
@@ -1419,12 +1775,20 @@
       biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, counters);
     }
 
+#if INCLUDE_RTM_OPT
+    if (UseRTMForStackLocks && use_rtm) {
+      rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg,
+                        stack_rtm_counters, method_data, profile_rtm,
+                        DONE_LABEL, IsInflated);
+    }
+#endif // INCLUDE_RTM_OPT
+
     movptr(tmpReg, Address(objReg, 0));          // [FETCH]
-    testl (tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
-    jccb  (Assembler::notZero, IsInflated);
+    testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased
+    jccb(Assembler::notZero, IsInflated);
 
     // Attempt stack-locking ...
-    orptr (tmpReg, 0x1);
+    orptr (tmpReg, markOopDesc::unlocked_value);
     movptr(Address(boxReg, 0), tmpReg);          // Anticipate successful CAS
     if (os::is_MP()) {
       lock();
@@ -1434,19 +1798,32 @@
       cond_inc32(Assembler::equal,
                  ExternalAddress((address)counters->fast_path_entry_count_addr()));
     }
-    jccb(Assembler::equal, DONE_LABEL);
-
-    // Recursive locking
+    jcc(Assembler::equal, DONE_LABEL);           // Success
+
+    // Recursive locking.
+    // The object is stack-locked: markword contains stack pointer to BasicLock.
+    // Locked by current thread if difference with current SP is less than one page.
     subptr(tmpReg, rsp);
+    // Next instruction set ZFlag == 1 (Success) if difference is less then one page.
     andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) );
     movptr(Address(boxReg, 0), tmpReg);
     if (counters != NULL) {
       cond_inc32(Assembler::equal,
                  ExternalAddress((address)counters->fast_path_entry_count_addr()));
     }
-    jmpb(DONE_LABEL);
+    jmp(DONE_LABEL);
 
     bind(IsInflated);
+    // The object is inflated. tmpReg contains pointer to ObjectMonitor* + 2(monitor_value)
+
+#if INCLUDE_RTM_OPT
+    // Use the same RTM locking code in 32- and 64-bit VM.
+    if (use_rtm) {
+      rtm_inflated_locking(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg,
+                           rtm_counters, method_data, profile_rtm, DONE_LABEL);
+    } else {
+#endif // INCLUDE_RTM_OPT
+
 #ifndef _LP64
     // The object is inflated.
     //
@@ -1576,7 +1953,7 @@
     // Without cast to int32_t a movptr will destroy r10 which is typically obj
     movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
 
-    mov    (boxReg, tmpReg);
+    movptr (boxReg, tmpReg);
     movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
     testptr(tmpReg, tmpReg);
     jccb   (Assembler::notZero, DONE_LABEL);
@@ -1587,9 +1964,11 @@
     }
     cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
     // Intentional fall-through into DONE_LABEL ...
-
+#endif // _LP64
+
+#if INCLUDE_RTM_OPT
+    } // use_rtm()
 #endif
-
     // DONE_LABEL is a hot target - we'd really like to place it at the
     // start of cache line by padding with NOPs.
     // See the AMD and Intel software optimization manuals for the
@@ -1631,11 +2010,9 @@
 // should not be unlocked by "normal" java-level locking and vice-versa.  The specification
 // doesn't specify what will occur if a program engages in such mixed-mode locking, however.
 
-void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) {
-  guarantee (objReg != boxReg, "");
-  guarantee (objReg != tmpReg, "");
-  guarantee (boxReg != tmpReg, "");
-  guarantee (boxReg == rax, "");
+void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) {
+  assert(boxReg == rax, "");
+  assert_different_registers(objReg, boxReg, tmpReg);
 
   if (EmitSync & 4) {
     // Disable - inhibit all inlining.  Force control through the slow-path
@@ -1667,14 +2044,41 @@
        biased_locking_exit(objReg, tmpReg, DONE_LABEL);
     }
 
+#if INCLUDE_RTM_OPT
+    if (UseRTMForStackLocks && use_rtm) {
+      assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking");
+      Label L_regular_unlock;
+      movptr(tmpReg, Address(objReg, 0));           // fetch markword
+      andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits
+      cmpptr(tmpReg, markOopDesc::unlocked_value);            // bits = 001 unlocked
+      jccb(Assembler::notEqual, L_regular_unlock);  // if !HLE RegularLock
+      xend();                                       // otherwise end...
+      jmp(DONE_LABEL);                              // ... and we're done
+      bind(L_regular_unlock);
+    }
+#endif
+
     cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header
+    jcc   (Assembler::zero, DONE_LABEL);            // 0 indicates recursive stack-lock
     movptr(tmpReg, Address(objReg, 0));             // Examine the object's markword
-    jccb  (Assembler::zero, DONE_LABEL);            // 0 indicates recursive stack-lock
-
-    testptr(tmpReg, 0x02);                          // Inflated?
+    testptr(tmpReg, markOopDesc::monitor_value);    // Inflated?
     jccb  (Assembler::zero, Stacked);
 
     // It's inflated.
+#if INCLUDE_RTM_OPT
+    if (use_rtm) {
+      Label L_regular_inflated_unlock;
+      // Clean monitor_value bit to get valid pointer
+      int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
+      movptr(boxReg, Address(tmpReg, owner_offset));
+      testptr(boxReg, boxReg);
+      jccb(Assembler::notZero, L_regular_inflated_unlock);
+      xend();
+      jmpb(DONE_LABEL);
+      bind(L_regular_inflated_unlock);
+    }
+#endif
+
     // Despite our balanced locking property we still check that m->_owner == Self
     // as java routines or native JNI code called by this thread might
     // have released the lock.
@@ -2448,7 +2852,9 @@
   Condition negated_cond = negate_condition(cond);
   Label L;
   jcc(negated_cond, L);
+  pushf(); // Preserve flags
   atomic_incl(counter_addr);
+  popf();
   bind(L);
 }
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,6 +27,7 @@
 
 #include "asm/assembler.hpp"
 #include "utilities/macros.hpp"
+#include "runtime/rtmLocking.hpp"
 
 
 // MacroAssembler extends Assembler by frequently used macros.
@@ -111,7 +112,8 @@
         op == 0xE9 /* jmp */ ||
         op == 0xEB /* short jmp */ ||
         (op & 0xF0) == 0x70 /* short jcc */ ||
-        op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */,
+        op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */ ||
+        op == 0xC7 && branch[1] == 0xF8 /* xbegin */,
         "Invalid opcode at patch point");
 
     if (op == 0xEB || (op & 0xF0) == 0x70) {
@@ -121,7 +123,7 @@
       guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset");
       *disp = imm8;
     } else {
-      int* disp = (int*) &branch[(op == 0x0F)? 2: 1];
+      int* disp = (int*) &branch[(op == 0x0F || op == 0xC7)? 2: 1];
       int imm32 = target - (address) &disp[1];
       *disp = imm32;
     }
@@ -161,7 +163,6 @@
   void incrementq(Register reg, int value = 1);
   void incrementq(Address dst, int value = 1);
 
-
   // Support optimal SSE move instructions.
   void movflt(XMMRegister dst, XMMRegister src) {
     if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; }
@@ -187,6 +188,8 @@
   void incrementl(AddressLiteral dst);
   void incrementl(ArrayAddress dst);
 
+  void incrementq(AddressLiteral dst);
+
   // Alignment
   void align(int modulus);
 
@@ -654,8 +657,36 @@
 #ifdef COMPILER2
   // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
   // See full desription in macroAssembler_x86.cpp.
-  void fast_lock(Register obj, Register box, Register tmp, Register scr, BiasedLockingCounters* counters);
-  void fast_unlock(Register obj, Register box, Register tmp);
+  void fast_lock(Register obj, Register box, Register tmp,
+                 Register scr, Register cx1, Register cx2,
+                 BiasedLockingCounters* counters,
+                 RTMLockingCounters* rtm_counters,
+                 RTMLockingCounters* stack_rtm_counters,
+                 Metadata* method_data,
+                 bool use_rtm, bool profile_rtm);
+  void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm);
+#if INCLUDE_RTM_OPT
+  void rtm_counters_update(Register abort_status, Register rtm_counters);
+  void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel);
+  void rtm_abort_ratio_calculation(Register tmp, Register rtm_counters_reg,
+                                   RTMLockingCounters* rtm_counters,
+                                   Metadata* method_data);
+  void rtm_profiling(Register abort_status_Reg, Register rtm_counters_Reg,
+                     RTMLockingCounters* rtm_counters, Metadata* method_data, bool profile_rtm);
+  void rtm_retry_lock_on_abort(Register retry_count, Register abort_status, Label& retryLabel);
+  void rtm_retry_lock_on_busy(Register retry_count, Register box, Register tmp, Register scr, Label& retryLabel);
+  void rtm_stack_locking(Register obj, Register tmp, Register scr,
+                         Register retry_on_abort_count,
+                         RTMLockingCounters* stack_rtm_counters,
+                         Metadata* method_data, bool profile_rtm,
+                         Label& DONE_LABEL, Label& IsInflated);
+  void rtm_inflated_locking(Register obj, Register box, Register tmp,
+                            Register scr, Register retry_on_busy_count,
+                            Register retry_on_abort_count,
+                            RTMLockingCounters* rtm_counters,
+                            Metadata* method_data, bool profile_rtm,
+                            Label& DONE_LABEL);
+#endif
 #endif
 
   Condition negate_condition(Condition cond);
@@ -721,6 +752,7 @@
 
 
   void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); }
+  void imulptr(Register dst, Register src, int imm32) { LP64_ONLY(imulq(dst, src, imm32)) NOT_LP64(imull(dst, src, imm32)); }
 
 
   void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); }
@@ -762,7 +794,14 @@
   // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes.
   void cond_inc32(Condition cond, AddressLiteral counter_addr);
   // Unconditional atomic increment.
-  void atomic_incl(AddressLiteral counter_addr);
+  void atomic_incl(Address counter_addr);
+  void atomic_incl(AddressLiteral counter_addr, Register scr = rscratch1);
+#ifdef _LP64
+  void atomic_incq(Address counter_addr);
+  void atomic_incq(AddressLiteral counter_addr, Register scr = rscratch1);
+#endif
+  void atomic_incptr(AddressLiteral counter_addr, Register scr = rscratch1) { LP64_ONLY(atomic_incq(counter_addr, scr)) NOT_LP64(atomic_incl(counter_addr, scr)) ; }
+  void atomic_incptr(Address counter_addr) { LP64_ONLY(atomic_incq(counter_addr)) NOT_LP64(atomic_incl(counter_addr)) ; }
 
   void lea(Register dst, AddressLiteral adr);
   void lea(Address dst, AddressLiteral adr);
@@ -1074,7 +1113,11 @@
 
   void movptr(Register dst, Address src);
 
-  void movptr(Register dst, AddressLiteral src);
+#ifdef _LP64
+  void movptr(Register dst, AddressLiteral src, Register scratch=rscratch1);
+#else
+  void movptr(Register dst, AddressLiteral src, Register scratch=noreg); // Scratch reg is ignored in 32-bit
+#endif
 
   void movptr(Register dst, intptr_t src);
   void movptr(Register dst, Register src);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/rtmLocking.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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 "memory/allocation.inline.hpp"
+#include "runtime/task.hpp"
+#include "runtime/rtmLocking.hpp"
+
+// One-shot PeriodicTask subclass for enabling RTM locking
+uintx RTMLockingCounters::_calculation_flag = 0;
+
+class RTMLockingCalculationTask : public PeriodicTask {
+ public:
+  RTMLockingCalculationTask(size_t interval_time) : PeriodicTask(interval_time){  }
+
+  virtual void task() {
+    RTMLockingCounters::_calculation_flag = 1;
+    // Reclaim our storage and disenroll ourself
+    delete this;
+  }
+};
+
+void RTMLockingCounters::init() {
+  if (UseRTMLocking && RTMLockingCalculationDelay > 0) {
+    RTMLockingCalculationTask* task = new RTMLockingCalculationTask(RTMLockingCalculationDelay);
+    task->enroll();
+  } else {
+    _calculation_flag = 1;
+  }
+}
+
+//------------------------------print_on-------------------------------
+void RTMLockingCounters::print_on(outputStream* st) {
+  tty->print_cr("# rtm locks total (estimated): " UINTX_FORMAT, _total_count * RTMTotalCountIncrRate);
+  tty->print_cr("# rtm lock aborts  : " UINTX_FORMAT, _abort_count);
+  for (int i = 0; i < ABORT_STATUS_LIMIT; i++) {
+    tty->print_cr("# rtm lock aborts %d: " UINTX_FORMAT, i, _abortX_count[i]);
+  }
+}
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1817,6 +1817,13 @@
   // Frame is now completed as far as size and linkage.
   int frame_complete = ((intptr_t)__ pc()) - start;
 
+  if (UseRTMLocking) {
+    // Abort RTM transaction before calling JNI
+    // because critical section will be large and will be
+    // aborted anyway. Also nmethod could be deoptimized.
+    __ xabort(0);
+  }
+
   // Calculate the difference between rsp and rbp,. We need to know it
   // after the native call because on windows Java Natives will pop
   // the arguments and it is painful to do rsp relative addressing
@@ -3170,6 +3177,12 @@
   };
 
   address start = __ pc();
+
+  if (UseRTMLocking) {
+    // Abort RTM transaction before possible nmethod deoptimization.
+    __ xabort(0);
+  }
+
   // Push self-frame.
   __ subptr(rsp, return_off*wordSize);     // Epilog!
 
@@ -3355,6 +3368,14 @@
   address call_pc = NULL;
   bool cause_return = (poll_type == POLL_AT_RETURN);
   bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
+
+  if (UseRTMLocking) {
+    // Abort RTM transaction before calling runtime
+    // because critical section will be large and will be
+    // aborted anyway. Also nmethod could be deoptimized.
+    __ xabort(0);
+  }
+
   // If cause_return is true we are at a poll_return and there is
   // the return address on the stack to the caller on the nmethod
   // that is safepoint. We can leave this return on the stack and
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -2012,6 +2012,13 @@
   // Frame is now completed as far as size and linkage.
   int frame_complete = ((intptr_t)__ pc()) - start;
 
+    if (UseRTMLocking) {
+      // Abort RTM transaction before calling JNI
+      // because critical section will be large and will be
+      // aborted anyway. Also nmethod could be deoptimized.
+      __ xabort(0);
+    }
+
 #ifdef ASSERT
     {
       Label L;
@@ -3612,6 +3619,11 @@
 
   address start = __ pc();
 
+  if (UseRTMLocking) {
+    // Abort RTM transaction before possible nmethod deoptimization.
+    __ xabort(0);
+  }
+
   // Push self-frame.  We get here with a return address on the
   // stack, so rsp is 8-byte aligned until we allocate our frame.
   __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog!
@@ -3792,6 +3804,13 @@
   bool cause_return = (poll_type == POLL_AT_RETURN);
   bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
 
+  if (UseRTMLocking) {
+    // Abort RTM transaction before calling runtime
+    // because critical section will be large and will be
+    // aborted anyway. Also nmethod could be deoptimized.
+    __ xabort(0);
+  }
+
   // Make room for return address (or push it again)
   if (!cause_return) {
     __ push(rbx);
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -50,13 +50,18 @@
 const char*           VM_Version::_features_str = "";
 VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
 
+// Address of instruction which causes SEGV
+address VM_Version::_cpuinfo_segv_addr = 0;
+// Address of instruction after the one which causes SEGV
+address VM_Version::_cpuinfo_cont_addr = 0;
+
 static BufferBlob* stub_blob;
-static const int stub_size = 550;
+static const int stub_size = 600;
 
 extern "C" {
-  typedef void (*getPsrInfo_stub_t)(void*);
+  typedef void (*get_cpu_info_stub_t)(void*);
 }
-static getPsrInfo_stub_t getPsrInfo_stub = NULL;
+static get_cpu_info_stub_t get_cpu_info_stub = NULL;
 
 
 class VM_Version_StubGenerator: public StubCodeGenerator {
@@ -64,7 +69,7 @@
 
   VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
 
-  address generate_getPsrInfo() {
+  address generate_get_cpu_info() {
     // Flags to test CPU type.
     const uint32_t HS_EFL_AC           = 0x40000;
     const uint32_t HS_EFL_ID           = 0x200000;
@@ -76,13 +81,13 @@
     Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
     Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
 
-    StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
+    StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
 #   define __ _masm->
 
     address start = __ pc();
 
     //
-    // void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
+    // void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
     //
     // LP64: rcx and rdx are first and second argument registers on windows
 
@@ -234,9 +239,9 @@
     // Check if OS has enabled XGETBV instruction to access XCR0
     // (OSXSAVE feature flag) and CPU supports AVX
     //
-    __ andl(rcx, 0x18000000);
+    __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
     __ cmpl(rcx, 0x18000000);
-    __ jccb(Assembler::notEqual, sef_cpuid);
+    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
 
     //
     // XCR0, XFEATURE_ENABLED_MASK register
@@ -247,6 +252,47 @@
     __ movl(Address(rsi, 0), rax);
     __ movl(Address(rsi, 4), rdx);
 
+    __ andl(rax, 0x6); // xcr0 bits sse | ymm
+    __ cmpl(rax, 0x6);
+    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
+
+    //
+    // Some OSs have a bug when upper 128bits of YMM
+    // registers are not restored after a signal processing.
+    // Generate SEGV here (reference through NULL)
+    // and check upper YMM bits after it.
+    //
+    VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
+
+    // load value into all 32 bytes of ymm7 register
+    __ movl(rcx, VM_Version::ymm_test_value());
+
+    __ movdl(xmm0, rcx);
+    __ pshufd(xmm0, xmm0, 0x00);
+    __ vinsertf128h(xmm0, xmm0, xmm0);
+    __ vmovdqu(xmm7, xmm0);
+#ifdef _LP64
+    __ vmovdqu(xmm8,  xmm0);
+    __ vmovdqu(xmm15, xmm0);
+#endif
+
+    __ xorl(rsi, rsi);
+    VM_Version::set_cpuinfo_segv_addr( __ pc() );
+    // Generate SEGV
+    __ movl(rax, Address(rsi, 0));
+
+    VM_Version::set_cpuinfo_cont_addr( __ pc() );
+    // Returns here after signal. Save xmm0 to check it later.
+    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
+    __ vmovdqu(Address(rsi,  0), xmm0);
+    __ vmovdqu(Address(rsi, 32), xmm7);
+#ifdef _LP64
+    __ vmovdqu(Address(rsi, 64), xmm8);
+    __ vmovdqu(Address(rsi, 96), xmm15);
+#endif
+
+    VM_Version::clean_cpuFeatures();
+
     //
     // cpuid(0x7) Structured Extended Features
     //
@@ -339,6 +385,14 @@
 };
 
 
+void VM_Version::get_cpu_info_wrapper() {
+  get_cpu_info_stub(&_cpuid_info);
+}
+
+#ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
+  #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
+#endif
+
 void VM_Version::get_processor_features() {
 
   _cpu = 4; // 486 by default
@@ -349,7 +403,11 @@
 
   if (!Use486InstrsOnly) {
     // Get raw processor info
-    getPsrInfo_stub(&_cpuid_info);
+
+    // Some platforms (like Win*) need a wrapper around here
+    // in order to properly handle SEGV for YMM registers test.
+    CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(get_cpu_info_wrapper);
+
     assert_is_initialized();
     _cpu = extended_cpu_family();
     _model = extended_cpu_model();
@@ -429,7 +487,7 @@
   }
 
   char buf[256];
-  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                cores_per_cpu(), threads_per_core(),
                cpu_family(), _model, _stepping,
                (supports_cmov() ? ", cmov" : ""),
@@ -446,8 +504,9 @@
                (supports_avx()    ? ", avx" : ""),
                (supports_avx2()   ? ", avx2" : ""),
                (supports_aes()    ? ", aes" : ""),
-               (supports_clmul()    ? ", clmul" : ""),
+               (supports_clmul()  ? ", clmul" : ""),
                (supports_erms()   ? ", erms" : ""),
+               (supports_rtm()    ? ", rtm" : ""),
                (supports_mmx_ext() ? ", mmxext" : ""),
                (supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
                (supports_lzcnt()   ? ", lzcnt": ""),
@@ -488,7 +547,7 @@
     }
   } else if (UseAES) {
     if (!FLAG_IS_DEFAULT(UseAES))
-      warning("AES instructions not available on this CPU");
+      warning("AES instructions are not available on this CPU");
     FLAG_SET_DEFAULT(UseAES, false);
   }
 
@@ -521,10 +580,57 @@
     }
   } else if (UseAESIntrinsics) {
     if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
-      warning("AES intrinsics not available on this CPU");
+      warning("AES intrinsics are not available on this CPU");
     FLAG_SET_DEFAULT(UseAESIntrinsics, false);
   }
 
+  // Adjust RTM (Restricted Transactional Memory) flags
+  if (!supports_rtm() && UseRTMLocking) {
+    // Can't continue because UseRTMLocking affects UseBiasedLocking flag
+    // setting during arguments processing. See use_biased_locking().
+    // VM_Version_init() is executed after UseBiasedLocking is used
+    // in Thread::allocate().
+    vm_exit_during_initialization("RTM instructions are not available on this CPU");
+  }
+
+#if INCLUDE_RTM_OPT
+  if (UseRTMLocking) {
+    if (!FLAG_IS_CMDLINE(UseRTMLocking)) {
+      // RTM locking should be used only for applications with
+      // high lock contention. For now we do not use it by default.
+      vm_exit_during_initialization("UseRTMLocking flag should be only set on command line");
+    }
+    if (!is_power_of_2(RTMTotalCountIncrRate)) {
+      warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64");
+      FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64);
+    }
+    if (RTMAbortRatio < 0 || RTMAbortRatio > 100) {
+      warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
+      FLAG_SET_DEFAULT(RTMAbortRatio, 50);
+    }
+  } else { // !UseRTMLocking
+    if (UseRTMForStackLocks) {
+      if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) {
+        warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off");
+      }
+      FLAG_SET_DEFAULT(UseRTMForStackLocks, false);
+    }
+    if (UseRTMDeopt) {
+      FLAG_SET_DEFAULT(UseRTMDeopt, false);
+    }
+    if (PrintPreciseRTMLockingStatistics) {
+      FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false);
+    }
+  }
+#else
+  if (UseRTMLocking) {
+    // Only C2 does RTM locking optimization.
+    // Can't continue because UseRTMLocking affects UseBiasedLocking flag
+    // setting during arguments processing. See use_biased_locking().
+    vm_exit_during_initialization("RTM locking optimization is not supported in this VM");
+  }
+#endif
+
 #ifdef COMPILER2
   if (UseFPUForSpilling) {
     if (UseSSE < 2) {
@@ -540,14 +646,28 @@
     if (MaxVectorSize > 32) {
       FLAG_SET_DEFAULT(MaxVectorSize, 32);
     }
-    if (MaxVectorSize > 16 && UseAVX == 0) {
-      // Only supported with AVX+
+    if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
+      // 32 bytes vectors (in YMM) are only supported with AVX+
       FLAG_SET_DEFAULT(MaxVectorSize, 16);
     }
     if (UseSSE < 2) {
-      // Only supported with SSE2+
+      // Vectors (in XMM) are only supported with SSE2+
       FLAG_SET_DEFAULT(MaxVectorSize, 0);
     }
+#ifdef ASSERT
+    if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
+      tty->print_cr("State of YMM registers after signal handle:");
+      int nreg = 2 LP64_ONLY(+2);
+      const char* ymm_name[4] = {"0", "7", "8", "15"};
+      for (int i = 0; i < nreg; i++) {
+        tty->print("YMM%s:", ymm_name[i]);
+        for (int j = 7; j >=0; j--) {
+          tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
+        }
+        tty->cr();
+      }
+    }
+#endif
   }
 #endif
 
@@ -678,14 +798,6 @@
       }
     }
   }
-#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
-    if (MaxVectorSize > 16) {
-      // Limit vectors size to 16 bytes on BSD until it fixes
-      // restoring upper 128bit of YMM registers on return
-      // from signal handler.
-      FLAG_SET_DEFAULT(MaxVectorSize, 16);
-    }
-#endif // COMPILER2
 
   // Use count leading zeros count instruction if available.
   if (supports_lzcnt()) {
@@ -814,6 +926,11 @@
     if (UseAES) {
       tty->print("  UseAES=1");
     }
+#ifdef COMPILER2
+    if (MaxVectorSize > 0) {
+      tty->print("  MaxVectorSize=%d", MaxVectorSize);
+    }
+#endif
     tty->cr();
     tty->print("Allocation");
     if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
@@ -856,18 +973,39 @@
 #endif // !PRODUCT
 }
 
+bool VM_Version::use_biased_locking() {
+#if INCLUDE_RTM_OPT
+  // RTM locking is most useful when there is high lock contention and
+  // low data contention.  With high lock contention the lock is usually
+  // inflated and biased locking is not suitable for that case.
+  // RTM locking code requires that biased locking is off.
+  // Note: we can't switch off UseBiasedLocking in get_processor_features()
+  // because it is used by Thread::allocate() which is called before
+  // VM_Version::initialize().
+  if (UseRTMLocking && UseBiasedLocking) {
+    if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
+      FLAG_SET_DEFAULT(UseBiasedLocking, false);
+    } else {
+      warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
+      UseBiasedLocking = false;
+    }
+  }
+#endif
+  return UseBiasedLocking;
+}
+
 void VM_Version::initialize() {
   ResourceMark rm;
   // Making this stub must be FIRST use of assembler
 
-  stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
+  stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
   if (stub_blob == NULL) {
-    vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
+    vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
   }
   CodeBuffer c(stub_blob);
   VM_Version_StubGenerator g(&c);
-  getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
-                                   g.generate_getPsrInfo());
+  get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
+                                     g.generate_get_cpu_info());
 
   get_processor_features();
 }
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -207,7 +207,9 @@
                         : 2,
                    bmi2 : 1,
                    erms : 1,
-                        : 22;
+                        : 1,
+                   rtm  : 1,
+                        : 20;
     } bits;
   };
 
@@ -229,6 +231,9 @@
                                // 0 if this instruction is not available
   static const char* _features_str;
 
+  static address   _cpuinfo_segv_addr; // address of instruction which causes SEGV
+  static address   _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
+
   enum {
     CPU_CX8    = (1 << 0), // next bits are from cpuid 1 (EDX)
     CPU_CMOV   = (1 << 1),
@@ -254,7 +259,8 @@
     CPU_ERMS   = (1 << 20), // enhanced 'rep movsb/stosb' instructions
     CPU_CLMUL  = (1 << 21), // carryless multiply for CRC
     CPU_BMI1   = (1 << 22),
-    CPU_BMI2   = (1 << 23)
+    CPU_BMI2   = (1 << 23),
+    CPU_RTM    = (1 << 24)  // Restricted Transactional Memory instructions
   } cpuFeatureFlags;
 
   enum {
@@ -361,6 +367,9 @@
     // extended control register XCR0 (the XFEATURE_ENABLED_MASK register)
     XemXcr0Eax   xem_xcr0_eax;
     uint32_t     xem_xcr0_edx; // reserved
+
+    // Space to save ymm registers after signal handle
+    int          ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
   };
 
   // The actual cpuid info block
@@ -438,6 +447,8 @@
       result |= CPU_ERMS;
     if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
       result |= CPU_CLMUL;
+    if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
+      result |= CPU_RTM;
 
     // AMD features.
     if (is_amd()) {
@@ -460,6 +471,21 @@
     return result;
   }
 
+  static bool os_supports_avx_vectors() {
+    if (!supports_avx()) {
+      return false;
+    }
+    // Verify that OS save/restore all bits of AVX registers
+    // during signal processing.
+    int nreg = 2 LP64_ONLY(+2);
+    for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
+      if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   static void get_processor_features();
 
 public:
@@ -476,10 +502,27 @@
   static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
   static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
   static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
+  static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
+
+  // The value used to check ymm register after signal handle
+  static int ymm_test_value()    { return 0xCAFEBABE; }
+
+  static void get_cpu_info_wrapper();
+  static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
+  static bool  is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
+  static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
+  static address  cpuinfo_cont_addr()           { return _cpuinfo_cont_addr; }
+
+  static void clean_cpuFeatures()   { _cpuFeatures = 0; }
+  static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
+
 
   // Initialization
   static void initialize();
 
+  // Override Abstract_VM_Version implementation
+  static bool use_biased_locking();
+
   // Asserts
   static void assert_is_initialized() {
     assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
@@ -572,6 +615,7 @@
   static bool supports_aes()      { return (_cpuFeatures & CPU_AES) != 0; }
   static bool supports_erms()     { return (_cpuFeatures & CPU_ERMS) != 0; }
   static bool supports_clmul()    { return (_cpuFeatures & CPU_CLMUL) != 0; }
+  static bool supports_rtm()      { return (_cpuFeatures & CPU_RTM) != 0; }
   static bool supports_bmi1()     { return (_cpuFeatures & CPU_BMI1) != 0; }
   static bool supports_bmi2()     { return (_cpuFeatures & CPU_BMI2) != 0; }
   // Intel features
--- a/hotspot/src/cpu/x86/vm/x86.ad	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/x86.ad	Wed Jul 05 19:35:40 2017 +0200
@@ -474,7 +474,125 @@
 
 %}
 
+
+//----------SOURCE BLOCK-------------------------------------------------------
+// This is a block of C++ code which provides values, functions, and
+// definitions necessary in the rest of the architecture description
+
+source_hpp %{
+// Header information of the source block.
+// Method declarations/definitions which are used outside
+// the ad-scope can conveniently be defined here.
+//
+// To keep related declarations/definitions/uses close together,
+// we switch between source %{ }% and source_hpp %{ }% freely as needed.
+
+class CallStubImpl {
+ 
+  //--------------------------------------------------------------
+  //---<  Used for optimization in Compile::shorten_branches  >---
+  //--------------------------------------------------------------
+
+ public:
+  // Size of call trampoline stub.
+  static uint size_call_trampoline() {
+    return 0; // no call trampolines on this platform
+  }
+  
+  // number of relocations needed by a call trampoline stub
+  static uint reloc_call_trampoline() { 
+    return 0; // no call trampolines on this platform
+  }
+};
+
+class HandlerImpl {
+
+ public:
+
+  static int emit_exception_handler(CodeBuffer &cbuf);
+  static int emit_deopt_handler(CodeBuffer& cbuf);
+
+  static uint size_exception_handler() {
+    // NativeCall instruction size is the same as NativeJump.
+    // exception handler starts out as jump and can be patched to
+    // a call be deoptimization.  (4932387)
+    // Note that this value is also credited (in output.cpp) to
+    // the size of the code section.
+    return NativeJump::instruction_size;
+  }
+
+#ifdef _LP64
+  static uint size_deopt_handler() {
+    // three 5 byte instructions
+    return 15;
+  }
+#else
+  static uint size_deopt_handler() {
+    // NativeCall instruction size is the same as NativeJump.
+    // exception handler starts out as jump and can be patched to
+    // a call be deoptimization.  (4932387)
+    // Note that this value is also credited (in output.cpp) to
+    // the size of the code section.
+    return 5 + NativeJump::instruction_size; // pushl(); jmp;
+  }
+#endif
+};
+
+%} // end source_hpp
+
 source %{
+
+// Emit exception handler code.
+// Stuff framesize into a register and call a VM stub routine.
+int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
+
+  // Note that the code buffer's insts_mark is always relative to insts.
+  // That's why we must use the macroassembler to generate a handler.
+  MacroAssembler _masm(&cbuf);
+  address base = __ start_a_stub(size_exception_handler());
+  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  int offset = __ offset();
+  __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
+  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
+  __ end_a_stub();
+  return offset;
+}
+
+// Emit deopt handler code.
+int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
+
+  // Note that the code buffer's insts_mark is always relative to insts.
+  // That's why we must use the macroassembler to generate a handler.
+  MacroAssembler _masm(&cbuf);
+  address base = __ start_a_stub(size_deopt_handler());
+  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  int offset = __ offset();
+
+#ifdef _LP64
+  address the_pc = (address) __ pc();
+  Label next;
+  // push a "the_pc" on the stack without destroying any registers
+  // as they all may be live.
+
+  // push address of "next"
+  __ call(next, relocInfo::none); // reloc none is fine since it is a disp32
+  __ bind(next);
+  // adjust it so it matches "the_pc"
+  __ subptr(Address(rsp, 0), __ offset() - offset);
+#else
+  InternalAddress here(__ pc());
+  __ pushptr(here.addr());
+#endif
+
+  __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
+  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
+  __ end_a_stub();
+  return offset;
+}
+
+
+//=============================================================================
+
   // Float masks come from different places depending on platform.
 #ifdef _LP64
   static address float_signmask()  { return StubRoutines::x86::float_sign_mask(); }
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 19:35:40 2017 +0200
@@ -1297,59 +1297,6 @@
 
 
 //=============================================================================
-uint size_exception_handler() {
-  // NativeCall instruction size is the same as NativeJump.
-  // exception handler starts out as jump and can be patched to
-  // a call be deoptimization.  (4932387)
-  // Note that this value is also credited (in output.cpp) to
-  // the size of the code section.
-  return NativeJump::instruction_size;
-}
-
-// Emit exception handler code.  Stuff framesize into a register
-// and call a VM stub routine.
-int emit_exception_handler(CodeBuffer& cbuf) {
-
-  // Note that the code buffer's insts_mark is always relative to insts.
-  // That's why we must use the macroassembler to generate a handler.
-  MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
-  int offset = __ offset();
-  __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
-  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
-  __ end_a_stub();
-  return offset;
-}
-
-uint size_deopt_handler() {
-  // NativeCall instruction size is the same as NativeJump.
-  // exception handler starts out as jump and can be patched to
-  // a call be deoptimization.  (4932387)
-  // Note that this value is also credited (in output.cpp) to
-  // the size of the code section.
-  return 5 + NativeJump::instruction_size; // pushl(); jmp;
-}
-
-// Emit deopt handler code.
-int emit_deopt_handler(CodeBuffer& cbuf) {
-
-  // Note that the code buffer's insts_mark is always relative to insts.
-  // That's why we must use the macroassembler to generate a handler.
-  MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
-  int offset = __ offset();
-  InternalAddress here(__ pc());
-  __ pushptr(here.addr());
-
-  __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
-  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
-  __ end_a_stub();
-  return offset;
-}
 
 int Matcher::regnum_to_fpu_offset(int regnum) {
   return regnum - 32; // The FP registers are in the second chunk
@@ -12925,13 +12872,31 @@
 
 // inlined locking and unlocking
 
+instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eDXRegI scr, rRegI cx1, rRegI cx2) %{
+  predicate(Compile::current()->use_rtm());
+  match(Set cr (FastLock object box));
+  effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box);
+  ins_cost(300);
+  format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %}
+  ins_encode %{
+    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
+                 $scr$$Register, $cx1$$Register, $cx2$$Register,
+                 _counters, _rtm_counters, _stack_rtm_counters,
+                 ((Method*)(ra_->C->method()->constant_encoding()))->method_data(),
+                 true, ra_->C->profile_rtm());
+  %}
+  ins_pipe(pipe_slow);
+%}
+
 instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr) %{
+  predicate(!Compile::current()->use_rtm());
   match(Set cr (FastLock object box));
   effect(TEMP tmp, TEMP scr, USE_KILL box);
   ins_cost(300);
   format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr" %}
   ins_encode %{
-    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters);
+    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
+                 $scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false);
   %}
   ins_pipe(pipe_slow);
 %}
@@ -12942,7 +12907,7 @@
   ins_cost(300);
   format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %}
   ins_encode %{
-    __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
+    __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm());
   %}
   ins_pipe(pipe_slow);
 %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 19:35:40 2017 +0200
@@ -1439,66 +1439,9 @@
   return MachNode::size(ra_); // too many variables; just compute it
                               // the hard way
 }
-
+ 
 
 //=============================================================================
-uint size_exception_handler()
-{
-  // NativeCall instruction size is the same as NativeJump.
-  // Note that this value is also credited (in output.cpp) to
-  // the size of the code section.
-  return NativeJump::instruction_size;
-}
-
-// Emit exception handler code.
-int emit_exception_handler(CodeBuffer& cbuf)
-{
-
-  // Note that the code buffer's insts_mark is always relative to insts.
-  // That's why we must use the macroassembler to generate a handler.
-  MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
-  int offset = __ offset();
-  __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
-  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
-  __ end_a_stub();
-  return offset;
-}
-
-uint size_deopt_handler()
-{
-  // three 5 byte instructions
-  return 15;
-}
-
-// Emit deopt handler code.
-int emit_deopt_handler(CodeBuffer& cbuf)
-{
-
-  // Note that the code buffer's insts_mark is always relative to insts.
-  // That's why we must use the macroassembler to generate a handler.
-  MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_deopt_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
-  int offset = __ offset();
-  address the_pc = (address) __ pc();
-  Label next;
-  // push a "the_pc" on the stack without destroying any registers
-  // as they all may be live.
-
-  // push address of "next"
-  __ call(next, relocInfo::none); // reloc none is fine since it is a disp32
-  __ bind(next);
-  // adjust it so it matches "the_pc"
-  __ subptr(Address(rsp, 0), __ offset() - offset);
-  __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
-  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
-  __ end_a_stub();
-  return offset;
-}
 
 int Matcher::regnum_to_fpu_offset(int regnum)
 {
@@ -11387,13 +11330,31 @@
 // ============================================================================
 // inlined locking and unlocking
 
+instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rdx_RegI scr, rRegI cx1, rRegI cx2) %{
+  predicate(Compile::current()->use_rtm());
+  match(Set cr (FastLock object box));
+  effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box);
+  ins_cost(300);
+  format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %}
+  ins_encode %{
+    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
+                 $scr$$Register, $cx1$$Register, $cx2$$Register,
+                 _counters, _rtm_counters, _stack_rtm_counters,
+                 ((Method*)(ra_->C->method()->constant_encoding()))->method_data(),
+                 true, ra_->C->profile_rtm());
+  %}
+  ins_pipe(pipe_slow);
+%}
+
 instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
+  predicate(!Compile::current()->use_rtm());
   match(Set cr (FastLock object box));
   effect(TEMP tmp, TEMP scr, USE_KILL box);
   ins_cost(300);
   format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %}
   ins_encode %{
-    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters);
+    __ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
+                 $scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false);
   %}
   ins_pipe(pipe_slow);
 %}
@@ -11404,7 +11365,7 @@
   ins_cost(300);
   format %{ "fastunlock $object,$box\t! kills $box,$tmp" %}
   ins_encode %{
-    __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
+    __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm());
   %}
   ins_pipe(pipe_slow);
 %}
--- a/hotspot/src/os/aix/vm/mutex_aix.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/aix/vm/mutex_aix.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,6 @@
 
 #include "os_aix.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
-#include "thread_aix.inline.hpp"
+#include "runtime/thread.inline.hpp"
 
 #endif // OS_AIX_VM_MUTEX_AIX_INLINE_HPP
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,26 +60,16 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/statSampler.hpp"
 #include "runtime/stubRoutines.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/threadCritical.hpp"
 #include "runtime/timer.hpp"
 #include "services/attachListener.hpp"
 #include "services/runtimeService.hpp"
-#include "thread_aix.inline.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/events.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/vmError.hpp"
-#ifdef TARGET_ARCH_ppc
-# include "assembler_ppc.inline.hpp"
-# include "nativeInst_ppc.hpp"
-#endif
-#ifdef COMPILER1
-#include "c1/c1_Runtime1.hpp"
-#endif
-#ifdef COMPILER2
-#include "opto/runtime.hpp"
-#endif
 
 // put OS-includes here (sorted alphabetically)
 #include <errno.h>
@@ -378,13 +368,14 @@
   assert(_page_size == SIZE_4K, "surprise!");
 
 
-  // query default data page size (default page size for C-Heap, pthread stacks and .bss).
+  // Query default data page size (default page size for C-Heap, pthread stacks and .bss).
   // Default data page size is influenced either by linker options (-bdatapsize)
   // or by environment variable LDR_CNTRL (suboption DATAPSIZE). If none is given,
   // default should be 4K.
   size_t data_page_size = SIZE_4K;
   {
     void* p = ::malloc(SIZE_16M);
+    guarantee(p != NULL, "malloc failed");
     data_page_size = os::Aix::query_pagesize(p);
     ::free(p);
   }
@@ -511,85 +502,76 @@
 
 } // end os::Aix::query_multipage_support()
 
-
-// The code for this method was initially derived from the version in os_linux.cpp
+// The code for this method was initially derived from the version in os_linux.cpp.
 void os::init_system_properties_values() {
-  // The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
+
 #define DEFAULT_LIBPATH "/usr/lib:/lib"
 #define EXTENSIONS_DIR  "/lib/ext"
 #define ENDORSED_DIR    "/lib/endorsed"
 
+  // Buffer that fits several sprintfs.
+  // Note that the space for the trailing null is provided
+  // by the nulls included by the sizeof operator.
+  const size_t bufsize =
+    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR), // extensions dir
+         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+  char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
   // sysclasspath, java_home, dll_dir
-  char *home_path;
-  char *dll_path;
-  char *pslash;
-  char buf[MAXPATHLEN];
-  os::jvm_path(buf, sizeof(buf));
-
-  // Found the full path to libjvm.so.
-  // Now cut the path to <java_home>/jre if we can.
-  *(strrchr(buf, '/')) = '\0'; // get rid of /libjvm.so
-  pslash = strrchr(buf, '/');
-  if (pslash != NULL) {
-    *pslash = '\0';            // get rid of /{client|server|hotspot}
-  }
-
-  dll_path = malloc(strlen(buf) + 1);
-  strcpy(dll_path, buf);
-  Arguments::set_dll_dir(dll_path);
-
-  if (pslash != NULL) {
+  {
+    char *pslash;
+    os::jvm_path(buf, bufsize);
+
+    // Found the full path to libjvm.so.
+    // Now cut the path to <java_home>/jre if we can.
+    *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
     pslash = strrchr(buf, '/');
     if (pslash != NULL) {
-      *pslash = '\0';          // get rid of /<arch>
+      *pslash = '\0';            // Get rid of /{client|server|hotspot}.
+    }
+    Arguments::set_dll_dir(buf);
+
+    if (pslash != NULL) {
       pslash = strrchr(buf, '/');
       if (pslash != NULL) {
-        *pslash = '\0';        // get rid of /lib
+        *pslash = '\0';          // Get rid of /<arch>.
+        pslash = strrchr(buf, '/');
+        if (pslash != NULL) {
+          *pslash = '\0';        // Get rid of /lib.
+        }
       }
     }
-  }
-
-  home_path = malloc(strlen(buf) + 1);
-  strcpy(home_path, buf);
-  Arguments::set_java_home(home_path);
-
-  if (!set_boot_path('/', ':')) return;
-
-  // Where to look for native libraries
-
-  // On Aix we get the user setting of LIBPATH
+    Arguments::set_java_home(buf);
+    set_boot_path('/', ':');
+  }
+
+  // Where to look for native libraries.
+
+  // On Aix we get the user setting of LIBPATH.
   // Eventually, all the library path setting will be done here.
-  char *ld_library_path;
-
-  // Construct the invariant part of ld_library_path.
-  ld_library_path = (char *) malloc(sizeof(DEFAULT_LIBPATH));
-  sprintf(ld_library_path, DEFAULT_LIBPATH);
-
-  // Get the user setting of LIBPATH, and prepended it.
-  char *v = ::getenv("LIBPATH");
-  if (v == NULL) {
-    v = "";
-  }
-
-  char *t = ld_library_path;
-  // That's +1 for the colon and +1 for the trailing '\0'
-  ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1);
-  sprintf(ld_library_path, "%s:%s", v, t);
-
+  // Get the user setting of LIBPATH.
+  const char *v = ::getenv("LIBPATH");
+  const char *v_colon = ":";
+  if (v == NULL) { v = ""; v_colon = ""; }
+
+  // Concatenate user and invariant part of ld_library_path.
+  // That's +1 for the colon and +1 for the trailing '\0'.
+  char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char, strlen(v) + 1 + sizeof(DEFAULT_LIBPATH) + 1, mtInternal);
+  sprintf(ld_library_path, "%s%s" DEFAULT_LIBPATH, v, v_colon);
   Arguments::set_library_path(ld_library_path);
-
-  // Extensions directories
-  char* cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(EXTENSIONS_DIR));
-  sprintf(cbuf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
-  Arguments::set_ext_dirs(cbuf);
+  FREE_C_HEAP_ARRAY(char, ld_library_path, mtInternal);
+
+  // Extensions directories.
+  sprintf(buf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
+  Arguments::set_ext_dirs(buf);
 
   // Endorsed standards default directory.
-  cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
-  sprintf(cbuf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(cbuf);
-
-#undef malloc
+  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(buf);
+
+  FREE_C_HEAP_ARRAY(char, buf, mtInternal);
+
 #undef DEFAULT_LIBPATH
 #undef EXTENSIONS_DIR
 #undef ENDORSED_DIR
@@ -3593,6 +3575,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if (os::Aix::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Aix::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Aix::get_our_sigflags(sig));
--- a/hotspot/src/os/aix/vm/threadCritical_aix.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/aix/vm/threadCritical_aix.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 
 #include "precompiled.hpp"
 #include "runtime/threadCritical.hpp"
-#include "thread_aix.inline.hpp"
+#include "runtime/thread.inline.hpp"
 
 // put OS-includes here
 # include <pthread.h>
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -306,9 +306,6 @@
 #endif
 
 void os::init_system_properties_values() {
-//  char arch[12];
-//  sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
-
   // The next steps are taken in the product version:
   //
   // Obtain the JAVA_HOME value from the location of libjvm.so.
@@ -335,199 +332,205 @@
   // Important note: if the location of libjvm.so changes this
   // code needs to be changed accordingly.
 
-  // The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
-#define getenv(n) ::getenv(n)
-
-/*
- * See ld(1):
- *      The linker uses the following search paths to locate required
- *      shared libraries:
- *        1: ...
- *        ...
- *        7: The default directories, normally /lib and /usr/lib.
- */
+// See ld(1):
+//      The linker uses the following search paths to locate required
+//      shared libraries:
+//        1: ...
+//        ...
+//        7: The default directories, normally /lib and /usr/lib.
 #ifndef DEFAULT_LIBPATH
 #define DEFAULT_LIBPATH "/lib:/usr/lib"
 #endif
 
+// Base path of extensions installed on the system.
+#define SYS_EXT_DIR     "/usr/java/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
 #define ENDORSED_DIR    "/lib/endorsed"
-#define REG_DIR         "/usr/java/packages"
-
-#ifdef __APPLE__
+
+#ifndef __APPLE__
+
+  // Buffer that fits several sprintfs.
+  // Note that the space for the colon and the trailing null are provided
+  // by the nulls included by the sizeof operator.
+  const size_t bufsize =
+    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
+         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+  char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
+  // sysclasspath, java_home, dll_dir
+  {
+    char *pslash;
+    os::jvm_path(buf, bufsize);
+
+    // Found the full path to libjvm.so.
+    // Now cut the path to <java_home>/jre if we can.
+    *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
+    pslash = strrchr(buf, '/');
+    if (pslash != NULL) {
+      *pslash = '\0';            // Get rid of /{client|server|hotspot}.
+    }
+    Arguments::set_dll_dir(buf);
+
+    if (pslash != NULL) {
+      pslash = strrchr(buf, '/');
+      if (pslash != NULL) {
+        *pslash = '\0';          // Get rid of /<arch>.
+        pslash = strrchr(buf, '/');
+        if (pslash != NULL) {
+          *pslash = '\0';        // Get rid of /lib.
+        }
+      }
+    }
+    Arguments::set_java_home(buf);
+    set_boot_path('/', ':');
+  }
+
+  // Where to look for native libraries.
+  //
+  // Note: Due to a legacy implementation, most of the library path
+  // is set in the launcher. This was to accomodate linking restrictions
+  // on legacy Bsd implementations (which are no longer supported).
+  // Eventually, all the library path setting will be done here.
+  //
+  // However, to prevent the proliferation of improperly built native
+  // libraries, the new path component /usr/java/packages is added here.
+  // Eventually, all the library path setting will be done here.
+  {
+    // Get the user setting of LD_LIBRARY_PATH, and prepended it. It
+    // should always exist (until the legacy problem cited above is
+    // addressed).
+    const char *v = ::getenv("LD_LIBRARY_PATH");
+    const char *v_colon = ":";
+    if (v == NULL) { v = ""; v_colon = ""; }
+    // That's +1 for the colon and +1 for the trailing '\0'.
+    char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char,
+                                                     strlen(v) + 1 +
+                                                     sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1,
+                                                     mtInternal);
+    sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
+    Arguments::set_library_path(ld_library_path);
+    FREE_C_HEAP_ARRAY(char, ld_library_path, mtInternal);
+  }
+
+  // Extensions directories.
+  sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
+  Arguments::set_ext_dirs(buf);
+
+  // Endorsed standards default directory.
+  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(buf);
+
+  FREE_C_HEAP_ARRAY(char, buf, mtInternal);
+
+#else // __APPLE__
+
 #define SYS_EXTENSIONS_DIR   "/Library/Java/Extensions"
 #define SYS_EXTENSIONS_DIRS  SYS_EXTENSIONS_DIR ":/Network" SYS_EXTENSIONS_DIR ":/System" SYS_EXTENSIONS_DIR ":/usr/lib/java"
-        const char *user_home_dir = get_home();
-        // the null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir
-        int system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) +
-            sizeof(SYS_EXTENSIONS_DIRS);
-#endif
-
+
+  const char *user_home_dir = get_home();
+  // The null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir.
+  size_t system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) +
+    sizeof(SYS_EXTENSIONS_DIRS);
+
+  // Buffer that fits several sprintfs.
+  // Note that the space for the colon and the trailing null are provided
+  // by the nulls included by the sizeof operator.
+  const size_t bufsize =
+    MAX3((size_t)MAXPATHLEN,  // for dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + system_ext_size, // extensions dir
+         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+  char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
+  // sysclasspath, java_home, dll_dir
   {
-    /* sysclasspath, java_home, dll_dir */
-    {
-        char *home_path;
-        char *dll_path;
-        char *pslash;
-        char buf[MAXPATHLEN];
-        os::jvm_path(buf, sizeof(buf));
-
-        // Found the full path to libjvm.so.
-        // Now cut the path to <java_home>/jre if we can.
-        *(strrchr(buf, '/')) = '\0';  /* get rid of /libjvm.so */
-        pslash = strrchr(buf, '/');
-        if (pslash != NULL)
-            *pslash = '\0';           /* get rid of /{client|server|hotspot} */
-        dll_path = malloc(strlen(buf) + 1);
-        if (dll_path == NULL)
-            return;
-        strcpy(dll_path, buf);
-        Arguments::set_dll_dir(dll_path);
-
-        if (pslash != NULL) {
-            pslash = strrchr(buf, '/');
-            if (pslash != NULL) {
-                *pslash = '\0';       /* get rid of /<arch> (/lib on macosx) */
-#ifndef __APPLE__
-                pslash = strrchr(buf, '/');
-                if (pslash != NULL)
-                    *pslash = '\0';   /* get rid of /lib */
-#endif
-            }
-        }
-
-        home_path = malloc(strlen(buf) + 1);
-        if (home_path == NULL)
-            return;
-        strcpy(home_path, buf);
-        Arguments::set_java_home(home_path);
-
-        if (!set_boot_path('/', ':'))
-            return;
+    char *pslash;
+    os::jvm_path(buf, bufsize);
+
+    // Found the full path to libjvm.so.
+    // Now cut the path to <java_home>/jre if we can.
+    *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
+    pslash = strrchr(buf, '/');
+    if (pslash != NULL) {
+      *pslash = '\0';            // Get rid of /{client|server|hotspot}.
+    }
+    Arguments::set_dll_dir(buf);
+
+    if (pslash != NULL) {
+      pslash = strrchr(buf, '/');
+      if (pslash != NULL) {
+        *pslash = '\0';          // Get rid of /lib.
+      }
     }
-
-    /*
-     * Where to look for native libraries
-     *
-     * Note: Due to a legacy implementation, most of the library path
-     * is set in the launcher.  This was to accomodate linking restrictions
-     * on legacy Bsd implementations (which are no longer supported).
-     * Eventually, all the library path setting will be done here.
-     *
-     * However, to prevent the proliferation of improperly built native
-     * libraries, the new path component /usr/java/packages is added here.
-     * Eventually, all the library path setting will be done here.
-     */
-    {
-        char *ld_library_path;
-
-        /*
-         * Construct the invariant part of ld_library_path. Note that the
-         * space for the colon and the trailing null are provided by the
-         * nulls included by the sizeof operator (so actually we allocate
-         * a byte more than necessary).
-         */
-#ifdef __APPLE__
-        ld_library_path = (char *) malloc(system_ext_size);
-        sprintf(ld_library_path, "%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir);
-#else
-        ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") +
-            strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH));
-        sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch);
-#endif
-
-        /*
-         * Get the user setting of LD_LIBRARY_PATH, and prepended it.  It
-         * should always exist (until the legacy problem cited above is
-         * addressed).
-         */
-#ifdef __APPLE__
-        // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code can specify a directory inside an app wrapper
-        char *l = getenv("JAVA_LIBRARY_PATH");
-        if (l != NULL) {
-            char *t = ld_library_path;
-            /* That's +1 for the colon and +1 for the trailing '\0' */
-            ld_library_path = (char *) malloc(strlen(l) + 1 + strlen(t) + 1);
-            sprintf(ld_library_path, "%s:%s", l, t);
-            free(t);
-        }
-
-        char *v = getenv("DYLD_LIBRARY_PATH");
-#else
-        char *v = getenv("LD_LIBRARY_PATH");
-#endif
-        if (v != NULL) {
-            char *t = ld_library_path;
-            /* That's +1 for the colon and +1 for the trailing '\0' */
-            ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1);
-            sprintf(ld_library_path, "%s:%s", v, t);
-            free(t);
-        }
-
-#ifdef __APPLE__
-        // Apple's Java6 has "." at the beginning of java.library.path.
-        // OpenJDK on Windows has "." at the end of java.library.path.
-        // OpenJDK on Linux and Solaris don't have "." in java.library.path
-        // at all. To ease the transition from Apple's Java6 to OpenJDK7,
-        // "." is appended to the end of java.library.path. Yes, this
-        // could cause a change in behavior, but Apple's Java6 behavior
-        // can be achieved by putting "." at the beginning of the
-        // JAVA_LIBRARY_PATH environment variable.
-        {
-            char *t = ld_library_path;
-            // that's +3 for appending ":." and the trailing '\0'
-            ld_library_path = (char *) malloc(strlen(t) + 3);
-            sprintf(ld_library_path, "%s:%s", t, ".");
-            free(t);
-        }
-#endif
-
-        Arguments::set_library_path(ld_library_path);
-    }
-
-    /*
-     * Extensions directories.
-     *
-     * Note that the space for the colon and the trailing null are provided
-     * by the nulls included by the sizeof operator (so actually one byte more
-     * than necessary is allocated).
-     */
-    {
-#ifdef __APPLE__
-        char *buf = malloc(strlen(Arguments::get_java_home()) +
-            sizeof(EXTENSIONS_DIR) + system_ext_size);
-        sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":"
-            SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home());
-#else
-        char *buf = malloc(strlen(Arguments::get_java_home()) +
-            sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR));
-        sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR,
-            Arguments::get_java_home());
-#endif
-
-        Arguments::set_ext_dirs(buf);
-    }
-
-    /* Endorsed standards default directory. */
-    {
-        char * buf;
-        buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
-        sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-        Arguments::set_endorsed_dirs(buf);
-    }
+    Arguments::set_java_home(buf);
+    set_boot_path('/', ':');
   }
 
-#ifdef __APPLE__
+  // Where to look for native libraries.
+  //
+  // Note: Due to a legacy implementation, most of the library path
+  // is set in the launcher. This was to accomodate linking restrictions
+  // on legacy Bsd implementations (which are no longer supported).
+  // Eventually, all the library path setting will be done here.
+  //
+  // However, to prevent the proliferation of improperly built native
+  // libraries, the new path component /usr/java/packages is added here.
+  // Eventually, all the library path setting will be done here.
+  {
+    // Get the user setting of LD_LIBRARY_PATH, and prepended it. It
+    // should always exist (until the legacy problem cited above is
+    // addressed).
+    // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code
+    // can specify a directory inside an app wrapper
+    const char *l = ::getenv("JAVA_LIBRARY_PATH");
+    const char *l_colon = ":";
+    if (l == NULL) { l = ""; l_colon = ""; }
+
+    const char *v = ::getenv("DYLD_LIBRARY_PATH");
+    const char *v_colon = ":";
+    if (v == NULL) { v = ""; v_colon = ""; }
+
+    // Apple's Java6 has "." at the beginning of java.library.path.
+    // OpenJDK on Windows has "." at the end of java.library.path.
+    // OpenJDK on Linux and Solaris don't have "." in java.library.path
+    // at all. To ease the transition from Apple's Java6 to OpenJDK7,
+    // "." is appended to the end of java.library.path. Yes, this
+    // could cause a change in behavior, but Apple's Java6 behavior
+    // can be achieved by putting "." at the beginning of the
+    // JAVA_LIBRARY_PATH environment variable.
+    char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char,
+                                                     strlen(v) + 1 + strlen(l) + 1 +
+                                                     system_ext_size + 3,
+                                                     mtInternal);
+    sprintf(ld_library_path, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.",
+            v, v_colon, l, l_colon, user_home_dir);
+    Arguments::set_library_path(ld_library_path);
+    FREE_C_HEAP_ARRAY(char, ld_library_path, mtInternal);
+  }
+
+  // Extensions directories.
+  //
+  // Note that the space for the colon and the trailing null are provided
+  // by the nulls included by the sizeof operator (so actually one byte more
+  // than necessary is allocated).
+  sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS,
+          user_home_dir, Arguments::get_java_home());
+  Arguments::set_ext_dirs(buf);
+
+  // Endorsed standards default directory.
+  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(buf);
+
+  FREE_C_HEAP_ARRAY(char, buf, mtInternal);
+
 #undef SYS_EXTENSIONS_DIR
-#endif
-#undef malloc
-#undef getenv
+#undef SYS_EXTENSIONS_DIRS
+
+#endif // __APPLE__
+
+#undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
 #undef ENDORSED_DIR
-
-  // Done
-  return;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -3091,7 +3094,7 @@
     sigAct.sa_sigaction = signalHandler;
     sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
   }
-#if __APPLE__
+#ifdef __APPLE__
   // Needed for main thread as XNU (Mac OS X kernel) will only deliver SIGSEGV
   // (which starts as SIGBUS) on main thread with faulting address inside "stack+guard pages"
   // if the signal handler declares it will handle it on alternate stack.
@@ -3374,6 +3377,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig));
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -109,6 +109,8 @@
 
 #define MAX_PATH    (2 * K)
 
+#define MAX_SECS 100000000
+
 // for timer info max values which include all bits
 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 
@@ -317,9 +319,6 @@
 }
 
 void os::init_system_properties_values() {
-//  char arch[12];
-//  sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
-
   // The next steps are taken in the product version:
   //
   // Obtain the JAVA_HOME value from the location of libjvm.so.
@@ -346,140 +345,101 @@
   // Important note: if the location of libjvm.so changes this
   // code needs to be changed accordingly.
 
-  // The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
-#define getenv(n) ::getenv(n)
-
-/*
- * See ld(1):
- *      The linker uses the following search paths to locate required
- *      shared libraries:
- *        1: ...
- *        ...
- *        7: The default directories, normally /lib and /usr/lib.
- */
+// See ld(1):
+//      The linker uses the following search paths to locate required
+//      shared libraries:
+//        1: ...
+//        ...
+//        7: The default directories, normally /lib and /usr/lib.
 #if defined(AMD64) || defined(_LP64) && (defined(SPARC) || defined(PPC) || defined(S390))
 #define DEFAULT_LIBPATH "/usr/lib64:/lib64:/lib:/usr/lib"
 #else
 #define DEFAULT_LIBPATH "/lib:/usr/lib"
 #endif
 
+// Base path of extensions installed on the system.
+#define SYS_EXT_DIR     "/usr/java/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
 #define ENDORSED_DIR    "/lib/endorsed"
-#define REG_DIR         "/usr/java/packages"
-
+
+  // Buffer that fits several sprintfs.
+  // Note that the space for the colon and the trailing null are provided
+  // by the nulls included by the sizeof operator.
+  const size_t bufsize =
+    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
+         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+  char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
+  // sysclasspath, java_home, dll_dir
   {
-    /* sysclasspath, java_home, dll_dir */
-    {
-        char *home_path;
-        char *dll_path;
-        char *pslash;
-        char buf[MAXPATHLEN];
-        os::jvm_path(buf, sizeof(buf));
-
-        // Found the full path to libjvm.so.
-        // Now cut the path to <java_home>/jre if we can.
-        *(strrchr(buf, '/')) = '\0';  /* get rid of /libjvm.so */
+    char *pslash;
+    os::jvm_path(buf, bufsize);
+
+    // Found the full path to libjvm.so.
+    // Now cut the path to <java_home>/jre if we can.
+    *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
+    pslash = strrchr(buf, '/');
+    if (pslash != NULL) {
+      *pslash = '\0';            // Get rid of /{client|server|hotspot}.
+    }
+    Arguments::set_dll_dir(buf);
+
+    if (pslash != NULL) {
+      pslash = strrchr(buf, '/');
+      if (pslash != NULL) {
+        *pslash = '\0';          // Get rid of /<arch>.
         pslash = strrchr(buf, '/');
-        if (pslash != NULL)
-            *pslash = '\0';           /* get rid of /{client|server|hotspot} */
-        dll_path = malloc(strlen(buf) + 1);
-        if (dll_path == NULL)
-            return;
-        strcpy(dll_path, buf);
-        Arguments::set_dll_dir(dll_path);
-
         if (pslash != NULL) {
-            pslash = strrchr(buf, '/');
-            if (pslash != NULL) {
-                *pslash = '\0';       /* get rid of /<arch> */
-                pslash = strrchr(buf, '/');
-                if (pslash != NULL)
-                    *pslash = '\0';   /* get rid of /lib */
-            }
+          *pslash = '\0';        // Get rid of /lib.
         }
-
-        home_path = malloc(strlen(buf) + 1);
-        if (home_path == NULL)
-            return;
-        strcpy(home_path, buf);
-        Arguments::set_java_home(home_path);
-
-        if (!set_boot_path('/', ':'))
-            return;
+      }
     }
-
-    /*
-     * Where to look for native libraries
-     *
-     * Note: Due to a legacy implementation, most of the library path
-     * is set in the launcher.  This was to accomodate linking restrictions
-     * on legacy Linux implementations (which are no longer supported).
-     * Eventually, all the library path setting will be done here.
-     *
-     * However, to prevent the proliferation of improperly built native
-     * libraries, the new path component /usr/java/packages is added here.
-     * Eventually, all the library path setting will be done here.
-     */
-    {
-        char *ld_library_path;
-
-        /*
-         * Construct the invariant part of ld_library_path. Note that the
-         * space for the colon and the trailing null are provided by the
-         * nulls included by the sizeof operator (so actually we allocate
-         * a byte more than necessary).
-         */
-        ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") +
-            strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH));
-        sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch);
-
-        /*
-         * Get the user setting of LD_LIBRARY_PATH, and prepended it.  It
-         * should always exist (until the legacy problem cited above is
-         * addressed).
-         */
-        char *v = getenv("LD_LIBRARY_PATH");
-        if (v != NULL) {
-            char *t = ld_library_path;
-            /* That's +1 for the colon and +1 for the trailing '\0' */
-            ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1);
-            sprintf(ld_library_path, "%s:%s", v, t);
-        }
-        Arguments::set_library_path(ld_library_path);
-    }
-
-    /*
-     * Extensions directories.
-     *
-     * Note that the space for the colon and the trailing null are provided
-     * by the nulls included by the sizeof operator (so actually one byte more
-     * than necessary is allocated).
-     */
-    {
-        char *buf = malloc(strlen(Arguments::get_java_home()) +
-            sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR));
-        sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR,
-            Arguments::get_java_home());
-        Arguments::set_ext_dirs(buf);
-    }
-
-    /* Endorsed standards default directory. */
-    {
-        char * buf;
-        buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
-        sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-        Arguments::set_endorsed_dirs(buf);
-    }
-  }
-
-#undef malloc
-#undef getenv
+    Arguments::set_java_home(buf);
+    set_boot_path('/', ':');
+  }
+
+  // Where to look for native libraries.
+  //
+  // Note: Due to a legacy implementation, most of the library path
+  // is set in the launcher. This was to accomodate linking restrictions
+  // on legacy Linux implementations (which are no longer supported).
+  // Eventually, all the library path setting will be done here.
+  //
+  // However, to prevent the proliferation of improperly built native
+  // libraries, the new path component /usr/java/packages is added here.
+  // Eventually, all the library path setting will be done here.
+  {
+    // Get the user setting of LD_LIBRARY_PATH, and prepended it. It
+    // should always exist (until the legacy problem cited above is
+    // addressed).
+    const char *v = ::getenv("LD_LIBRARY_PATH");
+    const char *v_colon = ":";
+    if (v == NULL) { v = ""; v_colon = ""; }
+    // That's +1 for the colon and +1 for the trailing '\0'.
+    char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char,
+                                                     strlen(v) + 1 +
+                                                     sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1,
+                                                     mtInternal);
+    sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
+    Arguments::set_library_path(ld_library_path);
+    FREE_C_HEAP_ARRAY(char, ld_library_path, mtInternal);
+  }
+
+  // Extensions directories.
+  sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
+  Arguments::set_ext_dirs(buf);
+
+  // Endorsed standards default directory.
+  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(buf);
+
+  FREE_C_HEAP_ARRAY(char, buf, mtInternal);
+
+#undef DEFAULT_LIBPATH
+#undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
 #undef ENDORSED_DIR
-
-  // Done
-  return;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1961,7 +1921,11 @@
     {EM_SPARC32PLUS, EM_SPARC,   ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
     {EM_SPARCV9,     EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
     {EM_PPC,         EM_PPC,     ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
+#if defined(VM_LITTLE_ENDIAN)
+    {EM_PPC64,       EM_PPC64,   ELFCLASS64, ELFDATA2LSB, (char*)"Power PC 64"},
+#else
     {EM_PPC64,       EM_PPC64,   ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
+#endif
     {EM_ARM,         EM_ARM,     ELFCLASS32,   ELFDATA2LSB, (char*)"ARM"},
     {EM_S390,        EM_S390,    ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
     {EM_ALPHA,       EM_ALPHA,   ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"},
@@ -2434,7 +2398,6 @@
     sem_t _semaphore;
 };
 
-
 Semaphore::Semaphore() {
   sem_init(&_semaphore, 0, 0);
 }
@@ -2456,8 +2419,22 @@
 }
 
 bool Semaphore::timedwait(unsigned int sec, int nsec) {
+
   struct timespec ts;
-  unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
+  // Semaphore's are always associated with CLOCK_REALTIME
+  os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
+  // see unpackTime for discussion on overflow checking
+  if (sec >= MAX_SECS) {
+    ts.tv_sec += MAX_SECS;
+    ts.tv_nsec = 0;
+  } else {
+    ts.tv_sec += sec;
+    ts.tv_nsec += nsec;
+    if (ts.tv_nsec >= NANOSECS_PER_SEC) {
+      ts.tv_nsec -= NANOSECS_PER_SEC;
+      ++ts.tv_sec; // note: this must be <= max_secs
+    }
+  }
 
   while (1) {
     int result = sem_timedwait(&_semaphore, &ts);
@@ -4560,6 +4537,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Linux::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Linux::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Linux::get_our_sigflags(sig));
@@ -5656,7 +5638,6 @@
  * is no need to track notifications.
  */
 
-#define MAX_SECS 100000000
 /*
  * This code is common to linux and solaris and will be moved to a
  * common place in dolphin.
--- a/hotspot/src/os/solaris/vm/osThread_solaris.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -41,7 +41,6 @@
   _thread_id                         = 0;
   sigemptyset(&_caller_sigmask);
 
-  _saved_interrupt_thread_state      = _thread_new;
   _vm_created_thread                 = false;
 }
 
--- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -82,20 +82,6 @@
   void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
   static void SR_handler(Thread* thread, ucontext_t* uc);
 
- // ***************************************************************
- // java.lang.Thread.interrupt state.
- // ***************************************************************
-
- private:
-
-  JavaThreadState      _saved_interrupt_thread_state;       // the thread state before a system call -- restored afterward
-
- public:
-
-
-  JavaThreadState   saved_interrupt_thread_state()                              { return _saved_interrupt_thread_state; }
-  void              set_saved_interrupt_thread_state(JavaThreadState state)     { _saved_interrupt_thread_state = state; }
-
   static void       handle_spinlock_contention(int tries);                      // Used for thread local eden locking
 
   // ***************************************************************
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -311,33 +311,6 @@
   return localtime_r(clock, res);
 }
 
-// interruptible infrastructure
-
-// setup_interruptible saves the thread state before going into an
-// interruptible system call.
-// The saved state is used to restore the thread to
-// its former state whether or not an interrupt is received.
-// Used by classloader os::read
-// os::restartable_read calls skip this layer and stay in _thread_in_native
-
-void os::Solaris::setup_interruptible(JavaThread* thread) {
-
-  JavaThreadState thread_state = thread->thread_state();
-
-  assert(thread_state != _thread_blocked, "Coming from the wrong thread");
-  assert(thread_state != _thread_in_native, "Native threads skip setup_interruptible");
-  OSThread* osthread = thread->osthread();
-  osthread->set_saved_interrupt_thread_state(thread_state);
-  thread->frame_anchor()->make_walkable(thread);
-  ThreadStateTransition::transition(thread, thread_state, _thread_blocked);
-}
-
-JavaThread* os::Solaris::setup_interruptible() {
-  JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread();
-  setup_interruptible(thread);
-  return thread;
-}
-
 void os::Solaris::try_enable_extended_io() {
   typedef int (*enable_extended_FILE_stdio_t)(int, int);
 
@@ -353,41 +326,6 @@
   }
 }
 
-
-#ifdef ASSERT
-
-JavaThread* os::Solaris::setup_interruptible_native() {
-  JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread();
-  JavaThreadState thread_state = thread->thread_state();
-  assert(thread_state == _thread_in_native, "Assumed thread_in_native");
-  return thread;
-}
-
-void os::Solaris::cleanup_interruptible_native(JavaThread* thread) {
-  JavaThreadState thread_state = thread->thread_state();
-  assert(thread_state == _thread_in_native, "Assumed thread_in_native");
-}
-#endif
-
-// cleanup_interruptible reverses the effects of setup_interruptible
-// setup_interruptible_already_blocked() does not need any cleanup.
-
-void os::Solaris::cleanup_interruptible(JavaThread* thread) {
-  OSThread* osthread = thread->osthread();
-
-  ThreadStateTransition::transition(thread, _thread_blocked, osthread->saved_interrupt_thread_state());
-}
-
-// I/O interruption related counters called in _INTERRUPTIBLE
-
-void os::Solaris::bump_interrupted_before_count() {
-  RuntimeService::record_interrupted_before_count();
-}
-
-void os::Solaris::bump_interrupted_during_count() {
-  RuntimeService::record_interrupted_during_count();
-}
-
 static int _processors_online = 0;
 
          jint os::Solaris::_os_thread_limit = 0;
@@ -642,9 +580,6 @@
 
 
 void os::init_system_properties_values() {
-  char arch[12];
-  sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
-
   // The next steps are taken in the product version:
   //
   // Obtain the JAVA_HOME value from the location of libjvm.so.
@@ -671,218 +606,174 @@
   // Important note: if the location of libjvm.so changes this
   // code needs to be changed accordingly.
 
-  // The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
-#define free(p) FREE_C_HEAP_ARRAY(char, p, mtInternal)
-#define getenv(n) ::getenv(n)
-
+// Base path of extensions installed on the system.
+#define SYS_EXT_DIR     "/usr/jdk/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
 #define ENDORSED_DIR    "/lib/endorsed"
-#define COMMON_DIR      "/usr/jdk/packages"
-
+
+  char cpu_arch[12];
+  // Buffer that fits several sprintfs.
+  // Note that the space for the colon and the trailing null are provided
+  // by the nulls included by the sizeof operator.
+  const size_t bufsize =
+    MAX4((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch), // invariant ld_library_path
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
+         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+  char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
+  // sysclasspath, java_home, dll_dir
   {
-    /* sysclasspath, java_home, dll_dir */
-    {
-        char *home_path;
-        char *dll_path;
-        char *pslash;
-        char buf[MAXPATHLEN];
-        os::jvm_path(buf, sizeof(buf));
-
-        // Found the full path to libjvm.so.
-        // Now cut the path to <java_home>/jre if we can.
-        *(strrchr(buf, '/')) = '\0';  /* get rid of /libjvm.so */
-        pslash = strrchr(buf, '/');
-        if (pslash != NULL)
-            *pslash = '\0';           /* get rid of /{client|server|hotspot} */
-        dll_path = malloc(strlen(buf) + 1);
-        if (dll_path == NULL)
-            return;
-        strcpy(dll_path, buf);
-        Arguments::set_dll_dir(dll_path);
-
-        if (pslash != NULL) {
-            pslash = strrchr(buf, '/');
-            if (pslash != NULL) {
-                *pslash = '\0';       /* get rid of /<arch> */
-                pslash = strrchr(buf, '/');
-                if (pslash != NULL)
-                    *pslash = '\0';   /* get rid of /lib */
-            }
-        }
-
-        home_path = malloc(strlen(buf) + 1);
-        if (home_path == NULL)
-            return;
-        strcpy(home_path, buf);
-        Arguments::set_java_home(home_path);
-
-        if (!set_boot_path('/', ':'))
-            return;
+    char *pslash;
+    os::jvm_path(buf, bufsize);
+
+    // Found the full path to libjvm.so.
+    // Now cut the path to <java_home>/jre if we can.
+    *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
+    pslash = strrchr(buf, '/');
+    if (pslash != NULL) {
+      *pslash = '\0';            // Get rid of /{client|server|hotspot}.
     }
-
-    /*
-     * Where to look for native libraries
-     */
-    {
-      // Use dlinfo() to determine the correct java.library.path.
-      //
-      // If we're launched by the Java launcher, and the user
-      // does not set java.library.path explicitly on the commandline,
-      // the Java launcher sets LD_LIBRARY_PATH for us and unsets
-      // LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64.  In this case
-      // dlinfo returns LD_LIBRARY_PATH + crle settings (including
-      // /usr/lib), which is exactly what we want.
-      //
-      // If the user does set java.library.path, it completely
-      // overwrites this setting, and always has.
-      //
-      // If we're not launched by the Java launcher, we may
-      // get here with any/all of the LD_LIBRARY_PATH[_32|64]
-      // settings.  Again, dlinfo does exactly what we want.
-
-      Dl_serinfo     _info, *info = &_info;
-      Dl_serpath     *path;
-      char*          library_path;
-      char           *common_path;
-      int            i;
-
-      // determine search path count and required buffer size
-      if (dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info) == -1) {
-        vm_exit_during_initialization("dlinfo SERINFOSIZE request", dlerror());
-      }
-
-      // allocate new buffer and initialize
-      info = (Dl_serinfo*)malloc(_info.dls_size);
-      if (info == NULL) {
-        vm_exit_out_of_memory(_info.dls_size, OOM_MALLOC_ERROR,
-                              "init_system_properties_values info");
-      }
-      info->dls_size = _info.dls_size;
-      info->dls_cnt = _info.dls_cnt;
-
-      // obtain search path information
-      if (dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info) == -1) {
-        free(info);
-        vm_exit_during_initialization("dlinfo SERINFO request", dlerror());
+    Arguments::set_dll_dir(buf);
+
+    if (pslash != NULL) {
+      pslash = strrchr(buf, '/');
+      if (pslash != NULL) {
+        *pslash = '\0';          // Get rid of /<arch>.
+        pslash = strrchr(buf, '/');
+        if (pslash != NULL) {
+          *pslash = '\0';        // Get rid of /lib.
+        }
       }
-
-      path = &info->dls_serpath[0];
-
-      // Note: Due to a legacy implementation, most of the library path
-      // is set in the launcher.  This was to accomodate linking restrictions
-      // on legacy Solaris implementations (which are no longer supported).
-      // Eventually, all the library path setting will be done here.
-      //
-      // However, to prevent the proliferation of improperly built native
-      // libraries, the new path component /usr/jdk/packages is added here.
-
-      // Determine the actual CPU architecture.
-      char cpu_arch[12];
-      sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch));
+    }
+    Arguments::set_java_home(buf);
+    set_boot_path('/', ':');
+  }
+
+  // Where to look for native libraries.
+  {
+    // Use dlinfo() to determine the correct java.library.path.
+    //
+    // If we're launched by the Java launcher, and the user
+    // does not set java.library.path explicitly on the commandline,
+    // the Java launcher sets LD_LIBRARY_PATH for us and unsets
+    // LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64.  In this case
+    // dlinfo returns LD_LIBRARY_PATH + crle settings (including
+    // /usr/lib), which is exactly what we want.
+    //
+    // If the user does set java.library.path, it completely
+    // overwrites this setting, and always has.
+    //
+    // If we're not launched by the Java launcher, we may
+    // get here with any/all of the LD_LIBRARY_PATH[_32|64]
+    // settings.  Again, dlinfo does exactly what we want.
+
+    Dl_serinfo     info_sz, *info = &info_sz;
+    Dl_serpath     *path;
+    char           *library_path;
+    char           *common_path = buf;
+
+    // Determine search path count and required buffer size.
+    if (dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info) == -1) {
+      FREE_C_HEAP_ARRAY(char, buf,  mtInternal);
+      vm_exit_during_initialization("dlinfo SERINFOSIZE request", dlerror());
+    }
+
+    // Allocate new buffer and initialize.
+    info = (Dl_serinfo*)NEW_C_HEAP_ARRAY(char, info_sz.dls_size, mtInternal);
+    info->dls_size = info_sz.dls_size;
+    info->dls_cnt = info_sz.dls_cnt;
+
+    // Obtain search path information.
+    if (dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info) == -1) {
+      FREE_C_HEAP_ARRAY(char, buf,  mtInternal);
+      FREE_C_HEAP_ARRAY(char, info, mtInternal);
+      vm_exit_during_initialization("dlinfo SERINFO request", dlerror());
+    }
+
+    path = &info->dls_serpath[0];
+
+    // Note: Due to a legacy implementation, most of the library path
+    // is set in the launcher. This was to accomodate linking restrictions
+    // on legacy Solaris implementations (which are no longer supported).
+    // Eventually, all the library path setting will be done here.
+    //
+    // However, to prevent the proliferation of improperly built native
+    // libraries, the new path component /usr/jdk/packages is added here.
+
+    // Determine the actual CPU architecture.
+    sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch));
 #ifdef _LP64
-      // If we are a 64-bit vm, perform the following translations:
-      //   sparc   -> sparcv9
-      //   i386    -> amd64
-      if (strcmp(cpu_arch, "sparc") == 0)
-        strcat(cpu_arch, "v9");
-      else if (strcmp(cpu_arch, "i386") == 0)
-        strcpy(cpu_arch, "amd64");
+    // If we are a 64-bit vm, perform the following translations:
+    //   sparc   -> sparcv9
+    //   i386    -> amd64
+    if (strcmp(cpu_arch, "sparc") == 0) {
+      strcat(cpu_arch, "v9");
+    } else if (strcmp(cpu_arch, "i386") == 0) {
+      strcpy(cpu_arch, "amd64");
+    }
 #endif
 
-      // Construct the invariant part of ld_library_path. Note that the
-      // space for the colon and the trailing null are provided by the
-      // nulls included by the sizeof operator.
-      size_t bufsize = sizeof(COMMON_DIR) + sizeof("/lib/") + strlen(cpu_arch);
-      common_path = malloc(bufsize);
-      if (common_path == NULL) {
-        free(info);
-        vm_exit_out_of_memory(bufsize, OOM_MALLOC_ERROR,
-                              "init_system_properties_values common_path");
-      }
-      sprintf(common_path, COMMON_DIR "/lib/%s", cpu_arch);
-
-      // struct size is more than sufficient for the path components obtained
-      // through the dlinfo() call, so only add additional space for the path
-      // components explicitly added here.
-      bufsize = info->dls_size + strlen(common_path);
-      library_path = malloc(bufsize);
-      if (library_path == NULL) {
-        free(info);
-        free(common_path);
-        vm_exit_out_of_memory(bufsize, OOM_MALLOC_ERROR,
-                              "init_system_properties_values library_path");
+    // Construct the invariant part of ld_library_path.
+    sprintf(common_path, SYS_EXT_DIR "/lib/%s", cpu_arch);
+
+    // Struct size is more than sufficient for the path components obtained
+    // through the dlinfo() call, so only add additional space for the path
+    // components explicitly added here.
+    size_t library_path_size = info->dls_size + strlen(common_path);
+    library_path = (char *)NEW_C_HEAP_ARRAY(char, library_path_size, mtInternal);
+    library_path[0] = '\0';
+
+    // Construct the desired Java library path from the linker's library
+    // search path.
+    //
+    // For compatibility, it is optimal that we insert the additional path
+    // components specific to the Java VM after those components specified
+    // in LD_LIBRARY_PATH (if any) but before those added by the ld.so
+    // infrastructure.
+    if (info->dls_cnt == 0) { // Not sure this can happen, but allow for it.
+      strcpy(library_path, common_path);
+    } else {
+      int inserted = 0;
+      int i;
+      for (i = 0; i < info->dls_cnt; i++, path++) {
+        uint_t flags = path->dls_flags & LA_SER_MASK;
+        if (((flags & LA_SER_LIBPATH) == 0) && !inserted) {
+          strcat(library_path, common_path);
+          strcat(library_path, os::path_separator());
+          inserted = 1;
+        }
+        strcat(library_path, path->dls_name);
+        strcat(library_path, os::path_separator());
       }
-      library_path[0] = '\0';
-
-      // Construct the desired Java library path from the linker's library
-      // search path.
-      //
-      // For compatibility, it is optimal that we insert the additional path
-      // components specific to the Java VM after those components specified
-      // in LD_LIBRARY_PATH (if any) but before those added by the ld.so
-      // infrastructure.
-      if (info->dls_cnt == 0) { // Not sure this can happen, but allow for it
-        strcpy(library_path, common_path);
-      } else {
-        int inserted = 0;
-        for (i = 0; i < info->dls_cnt; i++, path++) {
-          uint_t flags = path->dls_flags & LA_SER_MASK;
-          if (((flags & LA_SER_LIBPATH) == 0) && !inserted) {
-            strcat(library_path, common_path);
-            strcat(library_path, os::path_separator());
-            inserted = 1;
-          }
-          strcat(library_path, path->dls_name);
-          strcat(library_path, os::path_separator());
-        }
-        // eliminate trailing path separator
-        library_path[strlen(library_path)-1] = '\0';
-      }
-
-      // happens before argument parsing - can't use a trace flag
-      // tty->print_raw("init_system_properties_values: native lib path: ");
-      // tty->print_raw_cr(library_path);
-
-      // callee copies into its own buffer
-      Arguments::set_library_path(library_path);
-
-      free(common_path);
-      free(library_path);
-      free(info);
+      // Eliminate trailing path separator.
+      library_path[strlen(library_path)-1] = '\0';
     }
 
-    /*
-     * Extensions directories.
-     *
-     * Note that the space for the colon and the trailing null are provided
-     * by the nulls included by the sizeof operator (so actually one byte more
-     * than necessary is allocated).
-     */
-    {
-        char *buf = (char *) malloc(strlen(Arguments::get_java_home()) +
-            sizeof(EXTENSIONS_DIR) + sizeof(COMMON_DIR) +
-            sizeof(EXTENSIONS_DIR));
-        sprintf(buf, "%s" EXTENSIONS_DIR ":" COMMON_DIR EXTENSIONS_DIR,
-            Arguments::get_java_home());
-        Arguments::set_ext_dirs(buf);
-    }
-
-    /* Endorsed standards default directory. */
-    {
-        char * buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
-        sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-        Arguments::set_endorsed_dirs(buf);
-    }
-  }
-
-#undef malloc
-#undef free
-#undef getenv
+    // happens before argument parsing - can't use a trace flag
+    // tty->print_raw("init_system_properties_values: native lib path: ");
+    // tty->print_raw_cr(library_path);
+
+    // Callee copies into its own buffer.
+    Arguments::set_library_path(library_path);
+
+    FREE_C_HEAP_ARRAY(char, library_path, mtInternal);
+    FREE_C_HEAP_ARRAY(char, info, mtInternal);
+  }
+
+  // Extensions directories.
+  sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
+  Arguments::set_ext_dirs(buf);
+
+  // Endorsed standards default directory.
+  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(buf);
+
+  FREE_C_HEAP_ARRAY(char, buf, mtInternal);
+
+#undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
 #undef ENDORSED_DIR
-#undef COMMON_DIR
-
 }
 
 void os::breakpoint() {
@@ -3366,11 +3257,20 @@
 
 // Read calls from inside the vm need to perform state transitions
 size_t os::read(int fd, void *buf, unsigned int nBytes) {
-  INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
+  size_t res;
+  JavaThread* thread = (JavaThread*)Thread::current();
+  assert(thread->thread_state() == _thread_in_vm, "Assumed _thread_in_vm");
+  ThreadBlockInVM tbiv(thread);
+  RESTARTABLE(::read(fd, buf, (size_t) nBytes), res);
+  return res;
 }
 
 size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
-  INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
+  size_t res;
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE(::read(fd, buf, (size_t) nBytes), res);
+  return res;
 }
 
 void os::naked_short_sleep(jlong ms) {
@@ -4471,6 +4371,11 @@
     tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
     // No need to check this sig any longer
     sigaddset(&check_signal_done, sig);
+    // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN
+    if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) {
+      tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell",
+                    exception_name(sig, buf, O_BUFLEN));
+    }
   } else if(os::Solaris::get_our_sigflags(sig) != 0 && act.sa_flags != os::Solaris::get_our_sigflags(sig)) {
     tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
     tty->print("expected:" PTR32_FORMAT, os::Solaris::get_our_sigflags(sig));
@@ -5305,6 +5210,8 @@
 }
 
 int os::available(int fd, jlong *bytes) {
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
   jlong cur, end;
   int mode;
   struct stat64 buf64;
@@ -5312,14 +5219,9 @@
   if (::fstat64(fd, &buf64) >= 0) {
     mode = buf64.st_mode;
     if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
-      /*
-      * XXX: is the following call interruptible? If so, this might
-      * need to go through the INTERRUPT_IO() wrapper as for other
-      * blocking, interruptible calls in this file.
-      */
       int n,ioctl_return;
 
-      INTERRUPTIBLE(::ioctl(fd, FIONREAD, &n),ioctl_return,os::Solaris::clear_interrupted);
+      RESTARTABLE(::ioctl(fd, FIONREAD, &n), ioctl_return);
       if (ioctl_return>= 0) {
           *bytes = n;
         return 1;
@@ -6250,7 +6152,11 @@
 }
 
 size_t os::write(int fd, const void *buf, unsigned int nBytes) {
-  INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted);
+  size_t res;
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
+  return res;
 }
 
 int os::close(int fd) {
@@ -6262,11 +6168,15 @@
 }
 
 int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
-  INTERRUPTIBLE_RETURN_INT((int)::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE_RETURN_INT((int)::recv(fd, buf, nBytes, flags));
 }
 
 int os::send(int fd, char* buf, size_t nBytes, uint flags) {
-  INTERRUPTIBLE_RETURN_INT((int)::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE_RETURN_INT((int)::send(fd, buf, nBytes, flags));
 }
 
 int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
@@ -6287,11 +6197,14 @@
   pfd.fd = fd;
   pfd.events = POLLIN;
 
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+
   gettimeofday(&t, &aNull);
   prevtime = ((julong)t.tv_sec * 1000)  +  t.tv_usec / 1000;
 
   for(;;) {
-    INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted);
+    res = ::poll(&pfd, 1, timeout);
     if(res == OS_ERR && errno == EINTR) {
         if(timeout != -1) {
           gettimeofday(&t, &aNull);
@@ -6307,17 +6220,30 @@
 
 int os::connect(int fd, struct sockaddr *him, socklen_t len) {
   int _result;
-  INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result,\
-                          os::Solaris::clear_interrupted);
-
-  // Depending on when thread interruption is reset, _result could be
-  // one of two values when errno == EINTR
-
-  if (((_result == OS_INTRPT) || (_result == OS_ERR))
-      && (errno == EINTR)) {
+  _result = ::connect(fd, him, len);
+
+  // On Solaris, when a connect() call is interrupted, the connection
+  // can be established asynchronously (see 6343810). Subsequent calls
+  // to connect() must check the errno value which has the semantic
+  // described below (copied from the connect() man page). Handling
+  // of asynchronously established connections is required for both
+  // blocking and non-blocking sockets.
+  //     EINTR            The  connection  attempt  was   interrupted
+  //                      before  any data arrived by the delivery of
+  //                      a signal. The connection, however, will  be
+  //                      established asynchronously.
+  //
+  //     EINPROGRESS      The socket is non-blocking, and the connec-
+  //                      tion  cannot  be completed immediately.
+  //
+  //     EALREADY         The socket is non-blocking,  and a previous
+  //                      connection  attempt  has  not yet been com-
+  //                      pleted.
+  //
+  //     EISCONN          The socket is already connected.
+  if (_result == OS_ERR && errno == EINTR) {
      /* restarting a connect() changes its errno semantics */
-     INTERRUPTIBLE(::connect(fd, him, len), _result,\
-                   os::Solaris::clear_interrupted);
+     RESTARTABLE(::connect(fd, him, len), _result);
      /* undo these changes */
      if (_result == OS_ERR) {
        if (errno == EALREADY) {
@@ -6335,20 +6261,23 @@
   if (fd < 0) {
     return OS_ERR;
   }
-  INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him, len),\
-                           os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE_RETURN_INT((int)::accept(fd, him, len));
 }
 
 int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
                  sockaddr* from, socklen_t* fromlen) {
-  INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen),\
-                           os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
 }
 
 int os::sendto(int fd, char* buf, size_t len, uint flags,
                struct sockaddr* to, socklen_t tolen) {
-  INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen),\
-                           os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+  RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
 }
 
 int os::socket_available(int fd, jint *pbytes) {
@@ -6363,8 +6292,9 @@
 }
 
 int os::bind(int fd, struct sockaddr* him, socklen_t len) {
-   INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\
-                                      os::Solaris::clear_interrupted);
+  assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
+          "Assumed _thread_in_native");
+   return ::bind(fd, him, len);
 }
 
 // Get the default path to the core file
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -311,24 +311,6 @@
                                        outdata, validity) : -1;
   }
 
-  enum {
-    clear_interrupted = true
-  };
-  static void setup_interruptible(JavaThread* thread);
-  static void setup_interruptible_already_blocked(JavaThread* thread);
-  static JavaThread* setup_interruptible();
-  static void cleanup_interruptible(JavaThread* thread);
-
-  // perf counter incrementers used by _INTERRUPTIBLE
-
-  static void bump_interrupted_before_count();
-  static void bump_interrupted_during_count();
-
-#ifdef ASSERT
-  static JavaThread* setup_interruptible_native();
-  static void cleanup_interruptible_native(JavaThread* thread);
-#endif
-
   static sigset_t* unblocked_signals();
   static sigset_t* vm_signals();
   static sigset_t* allowdebug_blocked_signals();
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -111,104 +111,7 @@
 //////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
-// macros for interruptible io and system calls and system call restarting
-
-#define _INTERRUPTIBLE(_setup, _cmd, _result, _thread, _clear, _before, _after, _int_enable) \
-do { \
-  _setup; \
-  _before; \
-  OSThread* _osthread = _thread->osthread(); \
-  if (_int_enable && _thread->has_last_Java_frame()) { \
-    /* this is java interruptible io stuff */ \
-    if (os::is_interrupted(_thread, _clear))  { \
-      os::Solaris::bump_interrupted_before_count(); \
-      _result = OS_INTRPT; \
-    } else { \
-      /* _cmd always expands to an assignment to _result */ \
-      if ((_cmd) < 0 && errno == EINTR  \
-       && os::is_interrupted(_thread, _clear)) { \
-        os::Solaris::bump_interrupted_during_count(); \
-        _result = OS_INTRPT; \
-      } \
-    } \
-  } else { \
-    /* this is normal blocking io stuff */ \
-    _cmd; \
-  } \
-  _after; \
-} while(false)
-
-// Interruptible io support + restarting of interrupted system calls
-
-#ifndef ASSERT
-
-#define INTERRUPTIBLE(_cmd, _result, _clear) do { \
-  _INTERRUPTIBLE( JavaThread* _thread = (JavaThread*)ThreadLocalStorage::thread(),_result = _cmd, _result, _thread, _clear, , , UseVMInterruptibleIO); \
-} while((_result == OS_ERR) && (errno == EINTR))
-
-#else
-
-// This adds an assertion that it is only called from thread_in_native
-// The call overhead is skipped for performance in product mode
-#define INTERRUPTIBLE(_cmd, _result, _clear) do { \
-  _INTERRUPTIBLE(JavaThread* _thread = os::Solaris::setup_interruptible_native(), _result = _cmd, _result, _thread, _clear, , os::Solaris::cleanup_interruptible_native(_thread), UseVMInterruptibleIO ); \
-} while((_result == OS_ERR) && (errno == EINTR))
-
-#endif
-
-// Used for calls from _thread_in_vm, not from _thread_in_native
-#define INTERRUPTIBLE_VM(_cmd, _result, _clear) do { \
-  _INTERRUPTIBLE(JavaThread* _thread = os::Solaris::setup_interruptible(), _result = _cmd, _result, _thread, _clear, , os::Solaris::cleanup_interruptible(_thread), UseVMInterruptibleIO ); \
-} while((_result == OS_ERR) && (errno == EINTR))
-
-/* Use NORESTART when the system call cannot return EINTR, when something other
-   than a system call is being invoked, or when the caller must do EINTR
-   handling. */
-
-#ifndef ASSERT
-
-#define INTERRUPTIBLE_NORESTART(_cmd, _result, _clear) \
-  _INTERRUPTIBLE( JavaThread* _thread = (JavaThread*)ThreadLocalStorage::thread(),_result = _cmd, _result, _thread, _clear, , , UseVMInterruptibleIO)
-
-#else
-
-// This adds an assertion that it is only called from thread_in_native
-// The call overhead is skipped for performance in product mode
-#define INTERRUPTIBLE_NORESTART(_cmd, _result, _clear) \
-  _INTERRUPTIBLE(JavaThread* _thread = os::Solaris::setup_interruptible_native(), _result = _cmd, _result, _thread, _clear, , os::Solaris::cleanup_interruptible_native(_thread), UseVMInterruptibleIO )
-
-#endif
-
-// Don't attend to UseVMInterruptibleIO. Always allow interruption.
-// Also assumes that it is called from the _thread_blocked state.
-// Used by os_sleep().
-
-#define INTERRUPTIBLE_NORESTART_VM_ALWAYS(_cmd, _result, _thread, _clear) \
-  _INTERRUPTIBLE(os::Solaris::setup_interruptible_already_blocked(_thread), _result = _cmd, _result, _thread, _clear, , , true )
-
-#define INTERRUPTIBLE_RETURN_INT(_cmd, _clear) do { \
-  int _result; \
-  do { \
-    INTERRUPTIBLE(_cmd, _result, _clear); \
-  } while((_result == OS_ERR) && (errno == EINTR)); \
-  return _result; \
-} while(false)
-
-#define INTERRUPTIBLE_RETURN_INT_VM(_cmd, _clear) do { \
-  int _result; \
-  do { \
-    INTERRUPTIBLE_VM(_cmd, _result, _clear); \
-  } while((_result == OS_ERR) && (errno == EINTR)); \
-  return _result; \
-} while(false)
-
-#define INTERRUPTIBLE_RETURN_INT_NORESTART(_cmd, _clear) do { \
-  int _result; \
-  INTERRUPTIBLE_NORESTART(_cmd, _result, _clear); \
-  return _result; \
-} while(false)
-
-/* Use the RESTARTABLE macros when interruptible io is not needed */
+// macros for restartable system calls
 
 #define RESTARTABLE(_cmd, _result) do { \
   do { \
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -2425,6 +2425,12 @@
     }
   }
 
+  if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
+      VM_Version::is_cpuinfo_segv_addr(pc)) {
+    // Verify that OS save/restore AVX registers.
+    return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
+  }
+
   if (t != NULL && t->is_Java_thread()) {
     JavaThread* thread = (JavaThread*) t;
     bool in_java = thread->thread_state() == _thread_in_Java;
@@ -2696,7 +2702,6 @@
 }
 #endif
 
-#ifndef PRODUCT
 void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) {
   // Install a win32 structured exception handler around the test
   // function call so the VM can generate an error dump if needed.
@@ -2707,7 +2712,6 @@
     // Nothing to do.
   }
 }
-#endif
 
 // Virtual Memory
 
--- a/hotspot/src/os/windows/vm/os_windows.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -101,9 +101,7 @@
   static address fast_jni_accessor_wrapper(BasicType);
 #endif
 
-#ifndef PRODUCT
   static void call_test_func_with_wrapper(void (*funcPtr)(void));
-#endif
 
   // filter function to ignore faults on serializations page
   static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -111,9 +111,7 @@
   return win32::_has_performance_count;
 }
 
-#ifndef PRODUCT
-  #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
-            os::win32::call_test_func_with_wrapper(f)
-#endif
+#define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
+        os::win32::call_test_func_with_wrapper(f)
 
 #endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,8 +49,8 @@
 #include "runtime/osThread.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
-#include "thread_aix.inline.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 #ifdef COMPILER1
--- a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * 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,14 +25,14 @@
 
 #include "precompiled.hpp"
 #include "runtime/threadLocalStorage.hpp"
-#include "thread_aix.inline.hpp"
+#include "runtime/thread.hpp"
 
 void ThreadLocalStorage::generate_code_for_get_thread() {
-    // nothing we can do here for user-level thread
+  // Nothing we can do here for user-level thread.
 }
 
 void ThreadLocalStorage::pd_init() {
-  // Nothing to do
+  // Nothing to do.
 }
 
 void ThreadLocalStorage::pd_set_thread(Thread* thread) {
--- a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
  */
 
 #include "precompiled.hpp"
-#include "runtime/frame.inline.hpp"
-#include "thread_aix.inline.hpp"
+#include "runtime/frame.hpp"
+#include "runtime/thread.hpp"
 
 // Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
 bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
--- a/hotspot/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -42,7 +42,6 @@
 #endif // AMD64
 
 define_pd_global(intx, CompilerThreadStackSize,  0);
-define_pd_global(uintx, SurvivorRatio,           8);
 
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -492,6 +492,11 @@
       }
     }
 
+    if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+      // Verify that OS save/restore AVX registers.
+      stub = VM_Version::cpuinfo_cont_addr();
+    }
+
     // We test if stub is already set (by the stack overflow code
     // above) so it is not overwritten by the code that follows. This
     // check is not required on other platforms, because on other
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os_cpu/linux_ppc/vm/bytes_linux_ppc.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Google Inc.  All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
+#define OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
+
+#if defined(VM_LITTLE_ENDIAN)
+#include <byteswap.h>
+
+// Efficient swapping of data bytes from Java byte
+// ordering to native byte ordering and vice versa.
+inline u2 Bytes::swap_u2(u2 x) { return bswap_16(x); }
+inline u4 Bytes::swap_u4(u4 x) { return bswap_32(x); }
+inline u8 Bytes::swap_u8(u8 x) { return bswap_64(x); }
+#endif // VM_LITTLE_ENDIAN
+
+#endif // OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
--- a/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
  */
 
 #include "precompiled.hpp"
-#include "runtime/frame.inline.hpp"
-#include "thread_linux.inline.hpp"
+#include "runtime/frame.hpp"
+#include "runtime/thread.hpp"
 
 // Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Linux/PPC.
 bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -338,6 +338,11 @@
       }
     }
 
+    if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+      // Verify that OS save/restore AVX registers.
+      stub = VM_Version::cpuinfo_cont_addr();
+    }
+
     if (thread->thread_state() == _thread_in_Java) {
       // Java thread running in Java code => find exception handler if any
       // a fault inside compiled code, the interpreter, or a stub
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -459,6 +459,11 @@
       }
     }
 
+    if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+      // Verify that OS save/restore AVX registers.
+      stub = VM_Version::cpuinfo_cont_addr();
+    }
+
     if (thread->thread_state() == _thread_in_vm) {
       if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
         stub = StubRoutines::handler_for_unsafe_access();
--- a/hotspot/src/share/vm/adlc/main.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/adlc/main.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -243,7 +243,6 @@
   AD.addInclude(AD._CPP_file, "vmreg_arm.inline.hpp");
 #endif
 #ifdef TARGET_ARCH_ppc
-  AD.addInclude(AD._CPP_file, "assembler_ppc.inline.hpp");
   AD.addInclude(AD._CPP_file, "nativeInst_ppc.hpp");
   AD.addInclude(AD._CPP_file, "vmreg_ppc.inline.hpp");
 #endif
@@ -274,6 +273,7 @@
   AD.addInclude(AD._DFA_file, "opto/cfgnode.hpp");  // Use PROB_MAX in predicate.
   AD.addInclude(AD._DFA_file, "opto/matcher.hpp");
   AD.addInclude(AD._DFA_file, "opto/opcodes.hpp");
+  AD.addInclude(AD._DFA_file, "opto/convertnode.hpp");
   // Make sure each .cpp file starts with include lines:
   // files declaring and defining generators for Mach* Objects (hpp,cpp)
   // Generate the result files:
--- a/hotspot/src/share/vm/adlc/output_c.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/adlc/output_c.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1582,6 +1582,8 @@
 
       if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) {
         fprintf(fp, "  ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt);
+        fprintf(fp, "  ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n",cnt);
+        fprintf(fp, "  ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n",cnt);
       }
 
       // Fill in the bottom_type where requested
@@ -3963,6 +3965,8 @@
   }
   if( inst->is_ideal_fastlock() ) {
     fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
+    fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
+    fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent);
   }
 
 }
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -2526,7 +2526,7 @@
     // need to free up storage used for OSR entry point
     LIR_Opr osrBuffer = block()->next()->operand();
     BasicTypeList signature;
-    signature.append(T_INT);
+    signature.append(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); // pass a pointer to osrBuffer
     CallingConvention* cc = frame_map()->c_calling_convention(&signature);
     __ move(osrBuffer, cc->args()->at(0));
     __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end),
--- a/hotspot/src/share/vm/c1/c1_globals.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_globals.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -308,9 +308,6 @@
   develop(intx, InstructionCountCutoff, 37000,                              \
           "If GraphBuilder adds this many instructions, bails out")         \
                                                                             \
-  product_pd(intx, SafepointPollOffset,                                     \
-          "Offset added to polling address (Intel only)")                   \
-                                                                            \
   develop(bool, ComputeExactFPURegisterUsage, true,                         \
           "Compute additional live set for fpu registers to simplify fpu stack merge (Intel only)") \
                                                                             \
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -961,7 +961,8 @@
                             AbstractCompiler* compiler,
                             int comp_level,
                             bool has_unsafe_access,
-                            bool has_wide_vectors) {
+                            bool has_wide_vectors,
+                            RTMState  rtm_state) {
   VM_ENTRY_MARK;
   nmethod* nm = NULL;
   {
@@ -1002,6 +1003,15 @@
 
     methodHandle method(THREAD, target->get_Method());
 
+#if INCLUDE_RTM_OPT
+    if (!failing() && (rtm_state != NoRTM) &&
+        (method()->method_data() != NULL) &&
+        (method()->method_data()->rtm_state() != rtm_state)) {
+      // Preemptive decompile if rtm state was changed.
+      record_failure("RTM state change invalidated rtm code");
+    }
+#endif
+
     if (failing()) {
       // While not a true deoptimization, it is a preemptive decompile.
       MethodData* mdo = method()->method_data();
@@ -1028,13 +1038,15 @@
                                frame_words, oop_map_set,
                                handler_table, inc_table,
                                compiler, comp_level);
-
     // Free codeBlobs
     code_buffer->free_blob();
 
     if (nm != NULL) {
       nm->set_has_unsafe_access(has_unsafe_access);
       nm->set_has_wide_vectors(has_wide_vectors);
+#if INCLUDE_RTM_OPT
+      nm->set_rtm_state(rtm_state);
+#endif
 
       // Record successful registration.
       // (Put nm into the task handle *before* publishing to the Java heap.)
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -365,7 +365,8 @@
                        AbstractCompiler*         compiler,
                        int                       comp_level,
                        bool                      has_unsafe_access,
-                       bool                      has_wide_vectors);
+                       bool                      has_wide_vectors,
+                       RTMState                  rtm_state = NoRTM);
 
 
   // Access to certain well known ciObjects.
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -581,14 +581,14 @@
  * Check whether profiling provides a type for the argument i to the
  * call at bci bci
  *
- * @param bci  bci of the call
- * @param i    argument number
- * @return     profiled type
+ * @param [in]bci         bci of the call
+ * @param [in]i           argument number
+ * @param [out]type       profiled type of argument, NULL if none
+ * @param [out]maybe_null true if null was seen for argument
+ * @return                true if profiling exists
  *
- * If the profile reports that the argument may be null, return false
- * at least for now.
  */
-ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
+bool ciMethod::argument_profiled_type(int bci, int i, ciKlass*& type, bool& maybe_null) {
   if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
     ciProfileData* data = method_data()->bci_to_data(bci);
     if (data != NULL) {
@@ -596,82 +596,77 @@
         assert_virtual_call_type_ok(bci);
         ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
         if (i >= call->number_of_arguments()) {
-          return NULL;
+          return false;
         }
-        ciKlass* type = call->valid_argument_type(i);
-        if (type != NULL && !call->argument_maybe_null(i)) {
-          return type;
-        }
+        type = call->valid_argument_type(i);
+        maybe_null = call->argument_maybe_null(i);
+        return true;
       } else if (data->is_CallTypeData()) {
         assert_call_type_ok(bci);
         ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
         if (i >= call->number_of_arguments()) {
-          return NULL;
+          return false;
         }
-        ciKlass* type = call->valid_argument_type(i);
-        if (type != NULL && !call->argument_maybe_null(i)) {
-          return type;
-        }
+        type = call->valid_argument_type(i);
+        maybe_null = call->argument_maybe_null(i);
+        return true;
       }
     }
   }
-  return NULL;
+  return false;
 }
 
 /**
  * Check whether profiling provides a type for the return value from
  * the call at bci bci
  *
- * @param bci  bci of the call
- * @return     profiled type
+ * @param [in]bci         bci of the call
+ * @param [out]type       profiled type of argument, NULL if none
+ * @param [out]maybe_null true if null was seen for argument
+ * @return                true if profiling exists
  *
- * If the profile reports that the argument may be null, return false
- * at least for now.
  */
-ciKlass* ciMethod::return_profiled_type(int bci) {
+bool ciMethod::return_profiled_type(int bci, ciKlass*& type, bool& maybe_null) {
   if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) {
     ciProfileData* data = method_data()->bci_to_data(bci);
     if (data != NULL) {
       if (data->is_VirtualCallTypeData()) {
         assert_virtual_call_type_ok(bci);
         ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
-        ciKlass* type = call->valid_return_type();
-        if (type != NULL && !call->return_maybe_null()) {
-          return type;
-        }
+        type = call->valid_return_type();
+        maybe_null = call->return_maybe_null();
+        return true;
       } else if (data->is_CallTypeData()) {
         assert_call_type_ok(bci);
         ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
-        ciKlass* type = call->valid_return_type();
-        if (type != NULL && !call->return_maybe_null()) {
-          return type;
-        }
+        type = call->valid_return_type();
+        maybe_null = call->return_maybe_null();
+        return true;
       }
     }
   }
-  return NULL;
+  return false;
 }
 
 /**
  * Check whether profiling provides a type for the parameter i
  *
- * @param i    parameter number
- * @return     profiled type
+ * @param [in]i           parameter number
+ * @param [out]type       profiled type of parameter, NULL if none
+ * @param [out]maybe_null true if null was seen for parameter
+ * @return                true if profiling exists
  *
- * If the profile reports that the argument may be null, return false
- * at least for now.
  */
-ciKlass* ciMethod::parameter_profiled_type(int i) {
+bool ciMethod::parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null) {
   if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
     ciParametersTypeData* parameters = method_data()->parameters_type_data();
     if (parameters != NULL && i < parameters->number_of_parameters()) {
-      ciKlass* type = parameters->valid_parameter_type(i);
-      if (type != NULL && !parameters->parameter_maybe_null(i)) {
-        return type;
-      }
+      type = parameters->valid_parameter_type(i);
+      maybe_null = parameters->parameter_maybe_null(i);
+      return true;
     }
   }
-  return NULL;
+  return false;
 }
 
 
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -234,10 +234,10 @@
   ciCallProfile call_profile_at_bci(int bci);
   int           interpreter_call_site_count(int bci);
 
-  // Does type profiling provide a useful type at this point?
-  ciKlass*      argument_profiled_type(int bci, int i);
-  ciKlass*      parameter_profiled_type(int i);
-  ciKlass*      return_profiled_type(int bci);
+  // Does type profiling provide any useful information at this point?
+  bool          argument_profiled_type(int bci, int i, ciKlass*& type, bool& maybe_null);
+  bool          parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null);
+  bool          return_profiled_type(int bci, ciKlass*& type, bool& maybe_null);
 
   ciField*      get_field_at_bci( int bci, bool &will_link);
   ciMethod*     get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -478,6 +478,18 @@
 
   int invocation_count() { return _invocation_counter; }
   int backedge_count()   { return _backedge_counter;   }
+
+#if INCLUDE_RTM_OPT
+  // return cached value
+  int rtm_state() {
+    if (is_empty()) {
+      return NoRTM;
+    } else {
+      return get_MethodData()->rtm_state();
+    }
+  }
+#endif
+
   // Transfer information about the method to MethodData*.
   // would_profile means we would like to profile this method,
   // meaning it's not trivial.
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -135,6 +135,14 @@
   }
 }
 
+void ClassLoaderData::methods_do(void f(Method*)) {
+  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
+    if (k->oop_is_instance()) {
+      InstanceKlass::cast(k)->methods_do(f);
+    }
+  }
+}
+
 void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
   // Lock to avoid classes being modified/added/removed during iteration
   MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
@@ -624,6 +632,12 @@
   }
 }
 
+void ClassLoaderDataGraph::methods_do(void f(Method*)) {
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->methods_do(f);
+  }
+}
+
 void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     cld->loaded_classes_do(klass_closure);
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -78,6 +78,7 @@
   static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
   static void classes_do(KlassClosure* klass_closure);
   static void classes_do(void f(Klass* const));
+  static void methods_do(void f(Method*));
   static void loaded_classes_do(KlassClosure* klass_closure);
   static void classes_unloading_do(void f(Klass* const));
   static bool do_unloading(BoolObjectClosure* is_alive);
@@ -189,6 +190,7 @@
   void classes_do(void f(Klass*));
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
+  void methods_do(void f(Method*));
 
   // Deallocate free list during class unloading.
   void free_deallocate_list();
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -61,10 +61,6 @@
 
   static Handle basic_create(int length, TRAPS);
 
-  static void set_value( oop string, typeArrayOop buffer) {
-    assert(initialized, "Must be initialized");
-    string->obj_field_put(value_offset,  (oop)buffer);
-  }
   static void set_offset(oop string, int offset) {
     assert(initialized, "Must be initialized");
     if (offset_offset > 0) {
@@ -122,12 +118,26 @@
     return hash_offset;
   }
 
+  static void set_value(oop string, typeArrayOop buffer) {
+    assert(initialized && (value_offset > 0), "Must be initialized");
+    string->obj_field_put(value_offset, (oop)buffer);
+  }
+  static void set_hash(oop string, unsigned int hash) {
+    assert(initialized && (hash_offset > 0), "Must be initialized");
+    string->int_field_put(hash_offset, hash);
+  }
+
   // Accessors
   static typeArrayOop value(oop java_string) {
     assert(initialized && (value_offset > 0), "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
     return (typeArrayOop) java_string->obj_field(value_offset);
   }
+  static unsigned int hash(oop java_string) {
+    assert(initialized && (hash_offset > 0), "Must be initialized");
+    assert(is_instance(java_string), "must be java_string");
+    return java_string->int_field(hash_offset);
+  }
   static int offset(oop java_string) {
     assert(initialized, "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -35,6 +35,9 @@
 #include "oops/oop.inline2.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "utilities/hashtable.inline.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1StringDedup.hpp"
+#endif
 
 // --------------------------------------------------------------------------
 
@@ -728,6 +731,15 @@
     string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
   }
 
+#if INCLUDE_ALL_GCS
+  if (G1StringDedup::is_enabled()) {
+    // Deduplicate the string before it is interned. Note that we should never
+    // deduplicate a string after it has been interned. Doing so will counteract
+    // compiler optimizations done on e.g. interned string literals.
+    G1StringDedup::deduplicate(string());
+  }
+#endif
+
   // Grab the StringTable_lock before getting the_table() because it could
   // change at safepoint.
   MutexLocker ml(StringTable_lock, THREAD);
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -497,6 +497,7 @@
   template(int_StringBuffer_signature,                "(I)Ljava/lang/StringBuffer;")                              \
   template(char_StringBuffer_signature,               "(C)Ljava/lang/StringBuffer;")                              \
   template(int_String_signature,                      "(I)Ljava/lang/String;")                                    \
+  template(codesource_permissioncollection_signature, "(Ljava/security/CodeSource;Ljava/security/PermissionCollection;)V") \
   /* signature symbols needed by intrinsics */                                                                    \
   VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE)            \
                                                                                                                   \
--- a/hotspot/src/share/vm/code/nmethod.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -460,7 +460,9 @@
   _scavenge_root_link      = NULL;
   _scavenge_root_state     = 0;
   _compiler                = NULL;
-
+#if INCLUDE_RTM_OPT
+  _rtm_state               = NoRTM;
+#endif
 #ifdef HAVE_DTRACE_H
   _trap_offset             = 0;
 #endif // def HAVE_DTRACE_H
--- a/hotspot/src/share/vm/code/nmethod.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -193,6 +193,12 @@
 
   jbyte _scavenge_root_state;
 
+#if INCLUDE_RTM_OPT
+  // RTM state at compile time. Used during deoptimization to decide
+  // whether to restart collecting RTM locking abort statistic again.
+  RTMState _rtm_state;
+#endif
+
   // Nmethod Flushing lock. If non-zero, then the nmethod is not removed
   // and is not made into a zombie. However, once the nmethod is made into
   // a zombie, it will be locked one final time if CompiledMethodUnload
@@ -414,6 +420,12 @@
   bool  is_zombie() const                         { return _state == zombie; }
   bool  is_unloaded() const                       { return _state == unloaded;   }
 
+#if INCLUDE_RTM_OPT
+  // rtm state accessing and manipulating
+  RTMState  rtm_state() const                     { return _rtm_state; }
+  void set_rtm_state(RTMState state)              { _rtm_state = state; }
+#endif
+
   // Make the nmethod non entrant. The nmethod will continue to be
   // alive.  It is used when an uncommon trap happens.  Returns true
   // if this thread changed the state of the nmethod or false if
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -116,10 +116,6 @@
   MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
   virtual void do_oop(oop* p);
   virtual void do_oop(narrowOop* p);
-
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
 };
 
 class Par_MarkRefsIntoClosure: public CMSOopsInGenClosure {
@@ -132,10 +128,6 @@
   Par_MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
   virtual void do_oop(oop* p);
   virtual void do_oop(narrowOop* p);
-
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
 };
 
 // A variant of the above used in certain kinds of CMS
@@ -152,10 +144,6 @@
                             CMSBitMap* cms_bm);
   virtual void do_oop(oop* p);
   virtual void do_oop(narrowOop* p);
-
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
 };
 
 // The non-parallel version (the parallel version appears further below).
@@ -181,10 +169,6 @@
   virtual void do_oop(narrowOop* p);
   inline void do_oop_nv(oop* p)       { PushAndMarkClosure::do_oop_work(p); }
   inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); }
-
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
 };
 
 // In the parallel case, the bit map and the
@@ -211,10 +195,6 @@
   virtual void do_oop(narrowOop* p);
   inline void do_oop_nv(oop* p)       { Par_PushAndMarkClosure::do_oop_work(p); }
   inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); }
-
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
 };
 
 // The non-parallel version (the parallel version appears further below).
@@ -245,9 +225,6 @@
   inline void do_oop_nv(oop* p)       { MarkRefsIntoAndScanClosure::do_oop_work(p); }
   inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
 
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
   void set_freelistLock(Mutex* m) {
     _freelistLock = m;
   }
@@ -282,9 +259,6 @@
   inline void do_oop_nv(oop* p)       { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
   inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
 
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_read;
-  }
   void trim_queue(uint size);
 };
 
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -793,53 +793,6 @@
   }
 }
 
-// Apply the given closure to each oop in the space \intersect memory region.
-void CompactibleFreeListSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  assert_lock_strong(freelistLock());
-  if (is_empty()) {
-    return;
-  }
-  MemRegion cur = MemRegion(bottom(), end());
-  mr = mr.intersection(cur);
-  if (mr.is_empty()) {
-    return;
-  }
-  if (mr.equals(cur)) {
-    oop_iterate(cl);
-    return;
-  }
-  assert(mr.end() <= end(), "just took an intersection above");
-  HeapWord* obj_addr = block_start(mr.start());
-  HeapWord* t = mr.end();
-
-  SpaceMemRegionOopsIterClosure smr_blk(cl, mr);
-  if (block_is_obj(obj_addr)) {
-    // Handle first object specially.
-    oop obj = oop(obj_addr);
-    obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk));
-  } else {
-    FreeChunk* fc = (FreeChunk*)obj_addr;
-    obj_addr += fc->size();
-  }
-  while (obj_addr < t) {
-    HeapWord* obj = obj_addr;
-    obj_addr += block_size(obj_addr);
-    // If "obj_addr" is not greater than top, then the
-    // entire object "obj" is within the region.
-    if (obj_addr <= t) {
-      if (block_is_obj(obj)) {
-        oop(obj)->oop_iterate(cl);
-      }
-    } else {
-      // "obj" extends beyond end of region
-      if (block_is_obj(obj)) {
-        oop(obj)->oop_iterate(&smr_blk);
-      }
-      break;
-    }
-  }
-}
-
 // NOTE: In the following methods, in order to safely be able to
 // apply the closure to an object, we need to be sure that the
 // object has been initialized. We are guaranteed that an object
@@ -898,42 +851,60 @@
                                                   UpwardsObjectClosure* cl) {
   assert_locked(freelistLock());
   NOT_PRODUCT(verify_objects_initialized());
-  Space::object_iterate_mem(mr, cl);
+  assert(!mr.is_empty(), "Should be non-empty");
+  // We use MemRegion(bottom(), end()) rather than used_region() below
+  // because the two are not necessarily equal for some kinds of
+  // spaces, in particular, certain kinds of free list spaces.
+  // We could use the more complicated but more precise:
+  // MemRegion(used_region().start(), round_to(used_region().end(), CardSize))
+  // but the slight imprecision seems acceptable in the assertion check.
+  assert(MemRegion(bottom(), end()).contains(mr),
+         "Should be within used space");
+  HeapWord* prev = cl->previous();   // max address from last time
+  if (prev >= mr.end()) { // nothing to do
+    return;
+  }
+  // This assert will not work when we go from cms space to perm
+  // space, and use same closure. Easy fix deferred for later. XXX YSR
+  // assert(prev == NULL || contains(prev), "Should be within space");
+
+  bool last_was_obj_array = false;
+  HeapWord *blk_start_addr, *region_start_addr;
+  if (prev > mr.start()) {
+    region_start_addr = prev;
+    blk_start_addr    = prev;
+    // The previous invocation may have pushed "prev" beyond the
+    // last allocated block yet there may be still be blocks
+    // in this region due to a particular coalescing policy.
+    // Relax the assertion so that the case where the unallocated
+    // block is maintained and "prev" is beyond the unallocated
+    // block does not cause the assertion to fire.
+    assert((BlockOffsetArrayUseUnallocatedBlock &&
+            (!is_in(prev))) ||
+           (blk_start_addr == block_start(region_start_addr)), "invariant");
+  } else {
+    region_start_addr = mr.start();
+    blk_start_addr    = block_start(region_start_addr);
+  }
+  HeapWord* region_end_addr = mr.end();
+  MemRegion derived_mr(region_start_addr, region_end_addr);
+  while (blk_start_addr < region_end_addr) {
+    const size_t size = block_size(blk_start_addr);
+    if (block_is_obj(blk_start_addr)) {
+      last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr);
+    } else {
+      last_was_obj_array = false;
+    }
+    blk_start_addr += size;
+  }
+  if (!last_was_obj_array) {
+    assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()),
+           "Should be within (closed) used space");
+    assert(blk_start_addr > prev, "Invariant");
+    cl->set_previous(blk_start_addr); // min address for next time
+  }
 }
 
-// Callers of this iterator beware: The closure application should
-// be robust in the face of uninitialized objects and should (always)
-// return a correct size so that the next addr + size below gives us a
-// valid block boundary. [See for instance,
-// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
-// in ConcurrentMarkSweepGeneration.cpp.]
-HeapWord*
-CompactibleFreeListSpace::object_iterate_careful(ObjectClosureCareful* cl) {
-  assert_lock_strong(freelistLock());
-  HeapWord *addr, *last;
-  size_t size;
-  for (addr = bottom(), last  = end();
-       addr < last; addr += size) {
-    FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->is_free()) {
-      // Since we hold the free list lock, which protects direct
-      // allocation in this generation by mutators, a free object
-      // will remain free throughout this iteration code.
-      size = fc->size();
-    } else {
-      // Note that the object need not necessarily be initialized,
-      // because (for instance) the free list lock does NOT protect
-      // object initialization. The closure application below must
-      // therefore be correct in the face of uninitialized objects.
-      size = cl->do_object_careful(oop(addr));
-      if (size == 0) {
-        // An unparsable object found. Signal early termination.
-        return addr;
-      }
-    }
-  }
-  return NULL;
-}
 
 // Callers of this iterator beware: The closure application should
 // be robust in the face of uninitialized objects and should (always)
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -338,10 +338,6 @@
                      unallocated_block() : end());
   }
 
-  bool is_in(const void* p) const {
-    return used_region().contains(p);
-  }
-
   virtual bool is_free_block(const HeapWord* p) const;
 
   // Resizing support
@@ -351,7 +347,6 @@
   Mutex* freelistLock() const { return &_freelistLock; }
 
   // Iteration support
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void oop_iterate(ExtendedOopClosure* cl);
 
   void object_iterate(ObjectClosure* blk);
@@ -364,6 +359,12 @@
   // obj_is_alive() to determine whether it is safe to iterate of
   // an object.
   void safe_object_iterate(ObjectClosure* blk);
+
+  // Iterate over all objects that intersect with mr, calling "cl->do_object"
+  // on each.  There is an exception to this: if this closure has already
+  // been invoked on an object, it may skip such objects in some cases.  This is
+  // Most likely to happen in an "upwards" (ascending address) iteration of
+  // MemRegions.
   void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
 
   // Requires that "mr" be entirely within the space.
@@ -372,11 +373,8 @@
   // terminate the iteration and return the address of the start of the
   // subregion that isn't done.  Return of "NULL" indicates that the
   // iteration completed.
-  virtual HeapWord*
-       object_iterate_careful_m(MemRegion mr,
-                                ObjectClosureCareful* cl);
-  virtual HeapWord*
-       object_iterate_careful(ObjectClosureCareful* cl);
+  HeapWord* object_iterate_careful_m(MemRegion mr,
+                                     ObjectClosureCareful* cl);
 
   // Override: provides a DCTO_CL specific to this kind of space.
   DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -2496,7 +2496,8 @@
 }
 
 void CMSCollector::report_heap_summary(GCWhen::Type when) {
-  _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_metaspace_summary);
+  _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary);
+  _gc_tracer_cm->report_metaspace_summary(when, _last_metaspace_summary);
 }
 
 void CMSCollector::collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause) {
@@ -3163,16 +3164,6 @@
 }
 
 void
-ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  if (freelistLock()->owned_by_self()) {
-    Generation::oop_iterate(mr, cl);
-  } else {
-    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
-    Generation::oop_iterate(mr, cl);
-  }
-}
-
-void
 ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
   if (freelistLock()->owned_by_self()) {
     Generation::oop_iterate(cl);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1285,7 +1285,6 @@
   void save_sweep_limit();
 
   // More iteration support
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   virtual void oop_iterate(ExtendedOopClosure* cl);
   virtual void safe_object_iterate(ObjectClosure* cl);
   virtual void object_iterate(ObjectClosure* cl);
@@ -1499,6 +1498,19 @@
   }
 };
 
+// A version of ObjectClosure with "memory" (see _previous_address below)
+class UpwardsObjectClosure: public BoolObjectClosure {
+  HeapWord* _previous_address;
+ public:
+  UpwardsObjectClosure() : _previous_address(NULL) { }
+  void set_previous(HeapWord* addr) { _previous_address = addr; }
+  HeapWord* previous()              { return _previous_address; }
+  // A return value of "true" can be used by the caller to decide
+  // if this object's end should *NOT* be recorded in
+  // _previous_address above.
+  virtual bool do_object_bm(oop obj, MemRegion mr) = 0;
+};
+
 // This closure is used during the second checkpointing phase
 // to rescan the marked objects on the dirty cards in the mod
 // union table and the card table proper. It's invoked via
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1809,8 +1809,8 @@
   uint _regions_claimed;
   size_t _freed_bytes;
   FreeRegionList* _local_cleanup_list;
-  OldRegionSet* _old_proxy_set;
-  HumongousRegionSet* _humongous_proxy_set;
+  HeapRegionSetCount _old_regions_removed;
+  HeapRegionSetCount _humongous_regions_removed;
   HRRSCleanupTask* _hrrs_cleanup_task;
   double _claimed_region_time;
   double _max_region_time;
@@ -1819,19 +1819,19 @@
   G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
                              int worker_num,
                              FreeRegionList* local_cleanup_list,
-                             OldRegionSet* old_proxy_set,
-                             HumongousRegionSet* humongous_proxy_set,
                              HRRSCleanupTask* hrrs_cleanup_task) :
     _g1(g1), _worker_num(worker_num),
     _max_live_bytes(0), _regions_claimed(0),
     _freed_bytes(0),
     _claimed_region_time(0.0), _max_region_time(0.0),
     _local_cleanup_list(local_cleanup_list),
-    _old_proxy_set(old_proxy_set),
-    _humongous_proxy_set(humongous_proxy_set),
+    _old_regions_removed(),
+    _humongous_regions_removed(),
     _hrrs_cleanup_task(hrrs_cleanup_task) { }
 
   size_t freed_bytes() { return _freed_bytes; }
+  const HeapRegionSetCount& old_regions_removed() { return _old_regions_removed; }
+  const HeapRegionSetCount& humongous_regions_removed() { return _humongous_regions_removed; }
 
   bool doHeapRegion(HeapRegion *hr) {
     if (hr->continuesHumongous()) {
@@ -1844,13 +1844,22 @@
     _regions_claimed++;
     hr->note_end_of_marking();
     _max_live_bytes += hr->max_live_bytes();
-    _g1->free_region_if_empty(hr,
-                              &_freed_bytes,
-                              _local_cleanup_list,
-                              _old_proxy_set,
-                              _humongous_proxy_set,
-                              _hrrs_cleanup_task,
-                              true /* par */);
+
+    if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) {
+      _freed_bytes += hr->used();
+      hr->set_containing_set(NULL);
+      if (hr->isHumongous()) {
+        assert(hr->startsHumongous(), "we should only see starts humongous");
+        _humongous_regions_removed.increment(1u, hr->capacity());
+        _g1->free_humongous_region(hr, _local_cleanup_list, true);
+      } else {
+        _old_regions_removed.increment(1u, hr->capacity());
+        _g1->free_region(hr, _local_cleanup_list, true);
+      }
+    } else {
+      hr->rem_set()->do_cleanup_work(_hrrs_cleanup_task);
+    }
+
     double region_time = (os::elapsedTime() - start);
     _claimed_region_time += region_time;
     if (region_time > _max_region_time) {
@@ -1883,12 +1892,8 @@
   void work(uint worker_id) {
     double start = os::elapsedTime();
     FreeRegionList local_cleanup_list("Local Cleanup List");
-    OldRegionSet old_proxy_set("Local Cleanup Old Proxy Set");
-    HumongousRegionSet humongous_proxy_set("Local Cleanup Humongous Proxy Set");
     HRRSCleanupTask hrrs_cleanup_task;
     G1NoteEndOfConcMarkClosure g1_note_end(_g1h, worker_id, &local_cleanup_list,
-                                           &old_proxy_set,
-                                           &humongous_proxy_set,
                                            &hrrs_cleanup_task);
     if (G1CollectedHeap::use_parallel_gc_threads()) {
       _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id,
@@ -1900,13 +1905,10 @@
     assert(g1_note_end.complete(), "Shouldn't have yielded!");
 
     // Now update the lists
-    _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(),
-                                            NULL /* free_list */,
-                                            &old_proxy_set,
-                                            &humongous_proxy_set,
-                                            true /* par */);
+    _g1h->remove_from_old_sets(g1_note_end.old_regions_removed(), g1_note_end.humongous_regions_removed());
     {
       MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
+      _g1h->decrement_summary_bytes(g1_note_end.freed_bytes());
       _max_live_bytes += g1_note_end.max_live_bytes();
       _freed_bytes += g1_note_end.freed_bytes();
 
@@ -1920,14 +1922,14 @@
 
       G1HRPrinter* hr_printer = _g1h->hr_printer();
       if (hr_printer->is_active()) {
-        HeapRegionLinkedListIterator iter(&local_cleanup_list);
+        FreeRegionListIterator iter(&local_cleanup_list);
         while (iter.more_available()) {
           HeapRegion* hr = iter.get_next();
           hr_printer->cleanup(hr);
         }
       }
 
-      _cleanup_list->add_as_tail(&local_cleanup_list);
+      _cleanup_list->add_ordered(&local_cleanup_list);
       assert(local_cleanup_list.is_empty(), "post-condition");
 
       HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task);
@@ -1971,7 +1973,6 @@
     return;
   }
 
-  HRSPhaseSetter x(HRSPhaseCleanup);
   g1h->verify_region_sets_optional();
 
   if (VerifyDuringGC) {
@@ -2017,8 +2018,8 @@
     // that calculated by walking the marking bitmap.
 
     // Bitmaps to hold expected values
-    BitMap expected_region_bm(_region_bm.size(), false);
-    BitMap expected_card_bm(_card_bm.size(), false);
+    BitMap expected_region_bm(_region_bm.size(), true);
+    BitMap expected_card_bm(_card_bm.size(), true);
 
     G1ParVerifyFinalCountTask g1_par_verify_task(g1h,
                                                  &_region_bm,
@@ -2144,7 +2145,7 @@
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  _cleanup_list.verify_optional();
+  _cleanup_list.verify_list();
   FreeRegionList tmp_free_list("Tmp Free List");
 
   if (G1ConcRegionFreeingVerbose) {
@@ -2157,9 +2158,9 @@
   // so it's not necessary to take any locks
   while (!_cleanup_list.is_empty()) {
     HeapRegion* hr = _cleanup_list.remove_head();
-    assert(hr != NULL, "the list was not empty");
+    assert(hr != NULL, "Got NULL from a non-empty list");
     hr->par_clear();
-    tmp_free_list.add_as_tail(hr);
+    tmp_free_list.add_ordered(hr);
 
     // Instead of adding one region at a time to the secondary_free_list,
     // we accumulate them in the local list and move them a few at a
@@ -2179,7 +2180,7 @@
 
       {
         MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
-        g1h->secondary_free_list_add_as_tail(&tmp_free_list);
+        g1h->secondary_free_list_add(&tmp_free_list);
         SecondaryFreeList_lock->notify_all();
       }
 
@@ -2528,6 +2529,11 @@
     assert(!rp->discovery_enabled(), "Post condition");
   }
 
+  if (has_overflown()) {
+    // We can not trust g1_is_alive if the marking stack overflowed
+    return;
+  }
+
   g1h->unlink_string_and_symbol_table(&g1_is_alive,
                                       /* process_strings */ false, // currently strings are always roots
                                       /* process_symbols */ true);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 
-#include "gc_implementation/g1/heapRegionSets.hpp"
+#include "gc_implementation/g1/heapRegionSet.hpp"
 #include "utilities/taskqueue.hpp"
 
 class G1CollectedHeap;
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/g1/dirtyCardQueue.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -24,6 +24,14 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1BiasedArray.hpp"
+#include "memory/padded.inline.hpp"
+
+// Allocate a new array, generic version.
+address G1BiasedMappedArrayBase::create_new_base_array(size_t length, size_t elem_size) {
+  assert(length > 0, "just checking");
+  assert(elem_size > 0, "just checking");
+  return PaddedPrimitiveArray<u_char, mtGC>::create_unfreeable(length * elem_size);
+}
 
 #ifndef PRODUCT
 void G1BiasedMappedArrayBase::verify_index(idx_t index) const {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,8 +25,8 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP
 
+#include "memory/allocation.hpp"
 #include "utilities/debug.hpp"
-#include "memory/allocation.inline.hpp"
 
 // Implements the common base functionality for arrays that contain provisions
 // for accessing its elements using a biased index.
@@ -48,11 +48,7 @@
     _bias(0), _shift_by(0) { }
 
   // Allocate a new array, generic version.
-  static address create_new_base_array(size_t length, size_t elem_size) {
-    assert(length > 0, "just checking");
-    assert(elem_size > 0, "just checking");
-    return NEW_C_HEAP_ARRAY(u_char, length * elem_size, mtGC);
-  }
+  static address create_new_base_array(size_t length, size_t elem_size);
 
   // Initialize the members of this class. The biased start address of this array
   // is the bias (in elements) multiplied by the element size.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 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 "code/nmethod.hpp"
+#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
+#include "memory/iterator.hpp"
+
+G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) {
+  _top = bottom();
+}
+
+void G1CodeRootChunk::reset() {
+  _next = _prev = NULL;
+  _top = bottom();
+}
+
+void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
+  nmethod** cur = bottom();
+  while (cur != _top) {
+    cl->do_code_blob(*cur);
+    cur++;
+  }
+}
+
+FreeList<G1CodeRootChunk> G1CodeRootSet::_free_list;
+size_t G1CodeRootSet::_num_chunks_handed_out = 0;
+
+G1CodeRootChunk* G1CodeRootSet::new_chunk() {
+  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
+  if (result == NULL) {
+    result = new G1CodeRootChunk();
+  }
+  G1CodeRootSet::_num_chunks_handed_out++;
+  result->reset();
+  return result;
+}
+
+void G1CodeRootSet::free_chunk(G1CodeRootChunk* chunk) {
+  _free_list.return_chunk_at_head(chunk);
+  G1CodeRootSet::_num_chunks_handed_out--;
+}
+
+void G1CodeRootSet::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
+  G1CodeRootSet::_num_chunks_handed_out -= list->count();
+  _free_list.prepend(list);
+}
+
+void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
+  size_t keep = G1CodeRootSet::_num_chunks_handed_out * keep_ratio / 100;
+
+  if (keep >= (size_t)_free_list.count()) {
+    return;
+  }
+
+  FreeList<G1CodeRootChunk> temp;
+  temp.initialize();
+  temp.set_size(G1CodeRootChunk::word_size());
+
+  _free_list.getFirstNChunksFromList((size_t)_free_list.count() - keep, &temp);
+
+  G1CodeRootChunk* cur = temp.get_chunk_at_head();
+  while (cur != NULL) {
+    delete cur;
+    cur = temp.get_chunk_at_head();
+  }
+}
+
+size_t G1CodeRootSet::static_mem_size() {
+  return sizeof(_free_list) + sizeof(_num_chunks_handed_out);
+}
+
+size_t G1CodeRootSet::fl_mem_size() {
+  return _free_list.count() * _free_list.size();
+}
+
+void G1CodeRootSet::initialize() {
+  _free_list.initialize();
+  _free_list.set_size(G1CodeRootChunk::word_size());
+}
+
+G1CodeRootSet::G1CodeRootSet() : _list(), _length(0) {
+  _list.initialize();
+  _list.set_size(G1CodeRootChunk::word_size());
+}
+
+G1CodeRootSet::~G1CodeRootSet() {
+  clear();
+}
+
+void G1CodeRootSet::add(nmethod* method) {
+  if (!contains(method)) {
+    // Try to add the nmethod. If there is not enough space, get a new chunk.
+    if (_list.head() == NULL || _list.head()->is_full()) {
+      G1CodeRootChunk* cur = new_chunk();
+      _list.return_chunk_at_head(cur);
+    }
+    bool result = _list.head()->add(method);
+    guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
+    _length++;
+  }
+}
+
+void G1CodeRootSet::remove(nmethod* method) {
+  G1CodeRootChunk* found = find(method);
+  if (found != NULL) {
+    bool result = found->remove(method);
+    guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method));
+    // eventually free completely emptied chunk
+    if (found->is_empty()) {
+      _list.remove_chunk(found);
+      free(found);
+    }
+    _length--;
+  }
+  assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
+}
+
+nmethod* G1CodeRootSet::pop() {
+  do {
+    G1CodeRootChunk* cur = _list.head();
+    if (cur == NULL) {
+      assert(_length == 0, "when there are no chunks, there should be no elements");
+      return NULL;
+    }
+    nmethod* result = cur->pop();
+    if (result != NULL) {
+      _length--;
+      return result;
+    } else {
+      free(_list.get_chunk_at_head());
+    }
+  } while (true);
+}
+
+G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
+  G1CodeRootChunk* cur = _list.head();
+  while (cur != NULL) {
+    if (cur->contains(method)) {
+      return cur;
+    }
+    cur = (G1CodeRootChunk*)cur->next();
+  }
+  return NULL;
+}
+
+void G1CodeRootSet::free(G1CodeRootChunk* chunk) {
+  free_chunk(chunk);
+}
+
+bool G1CodeRootSet::contains(nmethod* method) {
+  return find(method) != NULL;
+}
+
+void G1CodeRootSet::clear() {
+  free_all_chunks(&_list);
+  _length = 0;
+}
+
+void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
+  G1CodeRootChunk* cur = _list.head();
+  while (cur != NULL) {
+    cur->nmethods_do(blk);
+    cur = (G1CodeRootChunk*)cur->next();
+  }
+}
+
+size_t G1CodeRootSet::mem_size() {
+  return sizeof(this) + _list.count() * _list.size();
+}
+
+#ifndef PRODUCT
+
+void G1CodeRootSet::test() {
+  initialize();
+
+  assert(_free_list.count() == 0, "Free List must be empty");
+  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+
+  // The number of chunks that we allocate for purge testing.
+  size_t const num_chunks = 10;
+  {
+    G1CodeRootSet set1;
+    assert(set1.is_empty(), "Code root set must be initially empty but is not.");
+
+    set1.add((nmethod*)1);
+    assert(_num_chunks_handed_out == 1,
+           err_msg("Must have allocated and handed out one chunk, but handed out "
+                   SIZE_FORMAT" chunks", _num_chunks_handed_out));
+    assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
+                                       SIZE_FORMAT" elements", set1.length()));
+
+    // G1CodeRootChunk::word_size() is larger than G1CodeRootChunk::num_entries which
+    // we cannot access.
+    for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
+      set1.add((nmethod*)1);
+    }
+    assert(_num_chunks_handed_out == 1,
+           err_msg("Duplicate detection must have prevented allocation of further "
+                   "chunks but contains "SIZE_FORMAT, _num_chunks_handed_out));
+    assert(set1.length() == 1,
+           err_msg("Duplicate detection should not have increased the set size but "
+                   "is "SIZE_FORMAT, set1.length()));
+
+    size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;
+    for (size_t i = 0; i < num_total_after_add - 1; i++) {
+      set1.add((nmethod*)(2 + i));
+    }
+    assert(_num_chunks_handed_out > 1,
+           "After adding more code roots, more than one chunks should have been handed out");
+    assert(set1.length() == num_total_after_add,
+           err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
+                   "need to be in the set, but there are only "SIZE_FORMAT,
+                   num_total_after_add, set1.length()));
+
+    size_t num_popped = 0;
+    while (set1.pop() != NULL) {
+      num_popped++;
+    }
+    assert(num_popped == num_total_after_add,
+           err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
+                   "were added", num_popped, num_total_after_add));
+    assert(_num_chunks_handed_out == 0,
+           err_msg("After popping all elements, all chunks must have been returned "
+                   "but are still "SIZE_FORMAT, _num_chunks_handed_out));
+
+    purge_chunks(0);
+    assert(_free_list.count() == 0,
+           err_msg("After purging everything, the free list must be empty but still "
+                   "contains "SIZE_FORMAT" chunks", _free_list.count()));
+
+    // Add some more handed out chunks.
+    size_t i = 0;
+    while (_num_chunks_handed_out < num_chunks) {
+      set1.add((nmethod*)i);
+      i++;
+    }
+
+    {
+      // Generate chunks on the free list.
+      G1CodeRootSet set2;
+      size_t i = 0;
+      while (_num_chunks_handed_out < num_chunks * 2) {
+        set2.add((nmethod*)i);
+        i++;
+      }
+      // Exit of the scope of the set2 object will call the destructor that generates
+      // num_chunks elements on the free list.
+    }
+
+    assert(_num_chunks_handed_out == num_chunks,
+           err_msg("Deletion of the second set must have resulted in giving back "
+                   "those, but there is still "SIZE_FORMAT" handed out, expecting "
+                   SIZE_FORMAT, _num_chunks_handed_out, num_chunks));
+    assert((size_t)_free_list.count() == num_chunks,
+           err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
+                   "but there are only "SIZE_FORMAT, num_chunks, _free_list.count()));
+
+    size_t const test_percentage = 50;
+    purge_chunks(test_percentage);
+    assert(_num_chunks_handed_out == num_chunks,
+           err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT,
+                   _num_chunks_handed_out));
+    assert((size_t)_free_list.count() == (ssize_t)(num_chunks * test_percentage / 100),
+           err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks"
+                   "but there are "SSIZE_FORMAT, test_percentage, num_chunks,
+                   _free_list.count()));
+    // Purge the remainder of the chunks on the free list.
+    purge_chunks(0);
+    assert(_free_list.count() == 0, "Free List must be empty");
+    assert(_num_chunks_handed_out == num_chunks,
+           err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set "
+                   "but there are "SIZE_FORMAT, num_chunks, _num_chunks_handed_out));
+
+    // Exit of the scope of the set1 object will call the destructor that generates
+    // num_chunks additional elements on the free list.
+  }
+
+  assert(_num_chunks_handed_out == 0,
+         err_msg("Deletion of the only set must have resulted in no chunks handed "
+                 "out, but there is still "SIZE_FORMAT" handed out", _num_chunks_handed_out));
+  assert((size_t)_free_list.count() == num_chunks,
+         err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
+                 "but there are only "SSIZE_FORMAT, num_chunks, _free_list.count()));
+
+  // Restore initial state.
+  purge_chunks(0);
+  assert(_free_list.count() == 0, "Free List must be empty");
+  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+}
+
+void TestCodeCacheRemSet_test() {
+  G1CodeRootSet::test();
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/freeList.hpp"
+#include "runtime/globals.hpp"
+
+class CodeBlobClosure;
+
+class G1CodeRootChunk : public CHeapObj<mtGC> {
+ private:
+  static const int NUM_ENTRIES = 32;
+ public:
+  G1CodeRootChunk*     _next;
+  G1CodeRootChunk*     _prev;
+
+  nmethod** _top;
+
+  nmethod* _data[NUM_ENTRIES];
+
+  nmethod** bottom() const {
+    return (nmethod**) &(_data[0]);
+  }
+
+  nmethod** end() const {
+    return (nmethod**) &(_data[NUM_ENTRIES]);
+  }
+
+ public:
+  G1CodeRootChunk();
+  ~G1CodeRootChunk() {}
+
+  static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); }
+
+  // FreeList "interface" methods
+
+  G1CodeRootChunk* next() const         { return _next; }
+  G1CodeRootChunk* prev() const         { return _prev; }
+  void set_next(G1CodeRootChunk* v)     { _next = v; assert(v != this, "Boom");}
+  void set_prev(G1CodeRootChunk* v)     { _prev = v; assert(v != this, "Boom");}
+  void clear_next()       { set_next(NULL); }
+  void clear_prev()       { set_prev(NULL); }
+
+  size_t size() const { return word_size(); }
+
+  void link_next(G1CodeRootChunk* ptr)  { set_next(ptr); }
+  void link_prev(G1CodeRootChunk* ptr)  { set_prev(ptr); }
+  void link_after(G1CodeRootChunk* ptr) {
+    link_next(ptr);
+    if (ptr != NULL) ptr->link_prev((G1CodeRootChunk*)this);
+  }
+
+  bool is_free()                 { return true; }
+
+  // New G1CodeRootChunk routines
+
+  void reset();
+
+  bool is_empty() const {
+    return _top == bottom();
+  }
+
+  bool is_full() const {
+    return _top == (nmethod**)end();
+  }
+
+  bool contains(nmethod* method) {
+    nmethod** cur = bottom();
+    while (cur != _top) {
+      if (*cur == method) return true;
+      cur++;
+    }
+    return false;
+  }
+
+  bool add(nmethod* method) {
+    if (is_full()) return false;
+    *_top = method;
+    _top++;
+    return true;
+  }
+
+  bool remove(nmethod* method) {
+    nmethod** cur = bottom();
+    while (cur != _top) {
+      if (*cur == method) {
+        memmove(cur, cur + 1, (_top - (cur + 1)) * sizeof(nmethod**));
+        _top--;
+        return true;
+      }
+      cur++;
+    }
+    return false;
+  }
+
+  void nmethods_do(CodeBlobClosure* blk);
+
+  nmethod* pop() {
+    if (is_empty()) {
+      return NULL;
+    }
+    _top--;
+    return *_top;
+  }
+};
+
+// Implements storage for a set of code roots.
+// All methods that modify the set are not thread-safe except if otherwise noted.
+class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
+ private:
+  // Global free chunk list management
+  static FreeList<G1CodeRootChunk> _free_list;
+  // Total number of chunks handed out
+  static size_t _num_chunks_handed_out;
+
+  static G1CodeRootChunk* new_chunk();
+  static void free_chunk(G1CodeRootChunk* chunk);
+  // Free all elements of the given list.
+  static void free_all_chunks(FreeList<G1CodeRootChunk>* list);
+
+  // Return the chunk that contains the given nmethod, NULL otherwise.
+  // Scans the list of chunks backwards, as this method is used to add new
+  // entries, which are typically added in bulk for a single nmethod.
+  G1CodeRootChunk* find(nmethod* method);
+  void free(G1CodeRootChunk* chunk);
+
+  size_t _length;
+  FreeList<G1CodeRootChunk> _list;
+
+ public:
+  G1CodeRootSet();
+  ~G1CodeRootSet();
+
+  static void initialize();
+  static void purge_chunks(size_t keep_ratio);
+
+  static size_t static_mem_size();
+  static size_t fl_mem_size();
+
+  // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
+  // method is likely to be repeatedly called with the same nmethod.
+  void add(nmethod* method);
+
+  void remove(nmethod* method);
+  nmethod* pop();
+
+  bool contains(nmethod* method);
+
+  void clear();
+
+  void nmethods_do(CodeBlobClosure* blk) const;
+
+  bool is_empty() { return length() == 0; }
+
+  // Length in elements
+  size_t length() const { return _length; }
+
+  // Memory size in bytes taken by this set.
+  size_t mem_size();
+
+  static void test() PRODUCT_RETURN;
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -39,6 +39,7 @@
 #include "gc_implementation/g1/g1MarkSweep.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
@@ -169,14 +170,6 @@
   int calls() { return _calls; }
 };
 
-class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
-public:
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
-    *card_ptr = CardTableModRefBS::dirty_card_val();
-    return true;
-  }
-};
-
 YoungList::YoungList(G1CollectedHeap* g1h) :
     _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0),
     _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) {
@@ -524,7 +517,7 @@
 // Private methods.
 
 HeapRegion*
-G1CollectedHeap::new_region_try_secondary_free_list() {
+G1CollectedHeap::new_region_try_secondary_free_list(bool is_old) {
   MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
   while (!_secondary_free_list.is_empty() || free_regions_coming()) {
     if (!_secondary_free_list.is_empty()) {
@@ -540,7 +533,7 @@
 
       assert(!_free_list.is_empty(), "if the secondary_free_list was not "
              "empty we should have moved at least one entry to the free_list");
-      HeapRegion* res = _free_list.remove_head();
+      HeapRegion* res = _free_list.remove_region(is_old);
       if (G1ConcRegionFreeingVerbose) {
         gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
                                "allocated "HR_FORMAT" from secondary_free_list",
@@ -562,7 +555,7 @@
   return NULL;
 }
 
-HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool do_expand) {
+HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool is_old, bool do_expand) {
   assert(!isHumongous(word_size) || word_size <= HeapRegion::GrainWords,
          "the only time we use this to allocate a humongous region is "
          "when we are allocating a single humongous region");
@@ -574,19 +567,21 @@
         gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
                                "forced to look at the secondary_free_list");
       }
-      res = new_region_try_secondary_free_list();
+      res = new_region_try_secondary_free_list(is_old);
       if (res != NULL) {
         return res;
       }
     }
   }
-  res = _free_list.remove_head_or_null();
+
+  res = _free_list.remove_region(is_old);
+
   if (res == NULL) {
     if (G1ConcRegionFreeingVerbose) {
       gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
                              "res == NULL, trying the secondary_free_list");
     }
-    res = new_region_try_secondary_free_list();
+    res = new_region_try_secondary_free_list(is_old);
   }
   if (res == NULL && do_expand && _expand_heap_after_alloc_failure) {
     // Currently, only attempts to allocate GC alloc regions set
@@ -603,12 +598,9 @@
     if (expand(word_size * HeapWordSize)) {
       // Given that expand() succeeded in expanding the heap, and we
       // always expand the heap by an amount aligned to the heap
-      // region size, the free list should in theory not be empty. So
-      // it would probably be OK to use remove_head(). But the extra
-      // check for NULL is unlikely to be a performance issue here (we
-      // just expanded the heap!) so let's just be conservative and
-      // use remove_head_or_null().
-      res = _free_list.remove_head_or_null();
+      // region size, the free list should in theory not be empty.
+      // In either case remove_region() will check for NULL.
+      res = _free_list.remove_region(is_old);
     } else {
       _expand_heap_after_alloc_failure = false;
     }
@@ -626,7 +618,7 @@
     // Only one region to allocate, no need to go through the slower
     // path. The caller will attempt the expansion if this fails, so
     // let's not try to expand here too.
-    HeapRegion* hr = new_region(word_size, false /* do_expand */);
+    HeapRegion* hr = new_region(word_size, true /* is_old */, false /* do_expand */);
     if (hr != NULL) {
       first = hr->hrs_index();
     } else {
@@ -1298,7 +1290,6 @@
 
   size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes();
 
-  HRSPhaseSetter x(HRSPhaseFullGC);
   verify_region_sets_optional();
 
   const bool do_clear_all_soft_refs = clear_all_soft_refs ||
@@ -1928,10 +1919,10 @@
   _g1mm(NULL),
   _refine_cte_cl(NULL),
   _full_collection(false),
-  _free_list("Master Free List"),
-  _secondary_free_list("Secondary Free List"),
-  _old_set("Old Set"),
-  _humongous_set("Master Humongous Set"),
+  _free_list("Master Free List", new MasterFreeRegionListMtSafeChecker()),
+  _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
+  _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
+  _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
   _free_regions_coming(false),
   _young_list(new YoungList(this)),
   _gc_time_stamp(0),
@@ -1963,7 +1954,7 @@
   int n_queues = MAX2((int)ParallelGCThreads, 1);
   _task_queues = new RefToScanQueueSet(n_queues);
 
-  int n_rem_sets = HeapRegionRemSet::num_par_rem_sets();
+  uint n_rem_sets = HeapRegionRemSet::num_par_rem_sets();
   assert(n_rem_sets > 0, "Invariant.");
 
   _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC);
@@ -2079,7 +2070,7 @@
   guarantee(HeapRegion::CardsPerRegion < max_cards_per_region,
             "too many cards per region");
 
-  HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
+  FreeRegionList::set_unrealistically_long_length(max_regions() + 1);
 
   _bot_shared = new G1BlockOffsetSharedArray(_reserved,
                                              heap_word_size(init_byte_size));
@@ -2182,6 +2173,8 @@
   // values in the heap have been properly initialized.
   _g1mm = new G1MonitoringSupport(this);
 
+  G1StringDedup::initialize();
+
   return JNI_OK;
 }
 
@@ -2369,8 +2362,12 @@
 };
 
 size_t G1CollectedHeap::recalculate_used() const {
+  double recalculate_used_start = os::elapsedTime();
+
   SumUsedClosure blk;
   heap_region_iterate(&blk);
+
+  g1_policy()->phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0);
   return blk.result();
 }
 
@@ -3462,6 +3459,11 @@
     if (!silent) gclog_or_tty->print("RemSet ");
     rem_set()->verify();
 
+    if (G1StringDedup::is_enabled()) {
+      if (!silent) gclog_or_tty->print("StrDedup ");
+      G1StringDedup::verify();
+    }
+
     if (failures) {
       gclog_or_tty->print_cr("Heap:");
       // It helps to have the per-region information in the output to
@@ -3479,8 +3481,13 @@
     }
     guarantee(!failures, "there should not have been any failures");
   } else {
-    if (!silent)
-      gclog_or_tty->print("(SKIPPING roots, heapRegionSets, heapRegions, remset) ");
+    if (!silent) {
+      gclog_or_tty->print("(SKIPPING Roots, HeapRegionSets, HeapRegions, RemSet");
+      if (G1StringDedup::is_enabled()) {
+        gclog_or_tty->print(", StrDedup");
+      }
+      gclog_or_tty->print(") ");
+    }
   }
 }
 
@@ -3522,6 +3529,29 @@
   }
 };
 
+bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
+                                       const HeapRegion* hr,
+                                       const VerifyOption vo) const {
+  switch (vo) {
+  case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
+  case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
+  case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
+  default:                            ShouldNotReachHere();
+  }
+  return false; // keep some compilers happy
+}
+
+bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
+                                       const VerifyOption vo) const {
+  switch (vo) {
+  case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
+  case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
+  case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
+  default:                            ShouldNotReachHere();
+  }
+  return false; // keep some compilers happy
+}
+
 void G1CollectedHeap::print_on(outputStream* st) const {
   st->print(" %-20s", "garbage-first heap");
   st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
@@ -3573,6 +3603,9 @@
   st->cr();
   _cm->print_worker_threads_on(st);
   _cg1r->print_worker_threads_on(st);
+  if (G1StringDedup::is_enabled()) {
+    G1StringDedup::print_worker_threads_on(st);
+  }
 }
 
 void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const {
@@ -3581,6 +3614,9 @@
   }
   tc->do_thread(_cmThread);
   _cg1r->threads_do(tc);
+  if (G1StringDedup::is_enabled()) {
+    G1StringDedup::threads_do(tc);
+  }
 }
 
 void G1CollectedHeap::print_tracing_info() const {
@@ -3887,7 +3923,6 @@
   print_heap_before_gc();
   trace_heap_before_gc(_gc_tracer_stw);
 
-  HRSPhaseSetter x(HRSPhaseEvacuation);
   verify_region_sets_optional();
   verify_dirty_young_regions();
 
@@ -4386,6 +4421,8 @@
 void G1CollectedHeap::remove_self_forwarding_pointers() {
   assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
 
+  double remove_self_forwards_start = os::elapsedTime();
+
   G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
 
   if (G1CollectedHeap::use_parallel_gc_threads()) {
@@ -4413,6 +4450,8 @@
   }
   _objs_with_preserved_marks.clear(true);
   _preserved_marks_of_objs.clear(true);
+
+  g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0);
 }
 
 void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
@@ -4634,9 +4673,7 @@
 #endif // ASSERT
 
 void G1ParScanThreadState::trim_queue() {
-  assert(_evac_cl != NULL, "not set");
   assert(_evac_failure_cl != NULL, "not set");
-  assert(_partial_scan_cl != NULL, "not set");
 
   StarTask ref;
   do {
@@ -4727,6 +4764,12 @@
   oop forward_ptr = old->forward_to_atomic(obj);
   if (forward_ptr == NULL) {
     Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
+
+    // alloc_purpose is just a hint to allocate() above, recheck the type of region
+    // we actually allocated from and update alloc_purpose accordingly
+    HeapRegion* to_region = _g1h->heap_region_containing_raw(obj_ptr);
+    alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured;
+
     if (g1p->track_object_age(alloc_purpose)) {
       // We could simply do obj->incr_age(). However, this causes a
       // performance issue. obj->incr_age() will first check whether
@@ -4754,6 +4797,13 @@
       obj->set_mark(m);
     }
 
+    if (G1StringDedup::is_enabled()) {
+      G1StringDedup::enqueue_from_evacuation(from_region->is_young(),
+                                             to_region->is_young(),
+                                             queue_num(),
+                                             obj);
+    }
+
     size_t* surv_young_words = surviving_young_words();
     surv_young_words[young_index] += word_sz;
 
@@ -4832,55 +4882,6 @@
 template void G1ParCopyClosure<G1BarrierEvac, false>::do_oop_work(oop* p);
 template void G1ParCopyClosure<G1BarrierEvac, false>::do_oop_work(narrowOop* p);
 
-template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) {
-  assert(has_partial_array_mask(p), "invariant");
-  oop from_obj = clear_partial_array_mask(p);
-
-  assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
-  assert(from_obj->is_objArray(), "must be obj array");
-  objArrayOop from_obj_array = objArrayOop(from_obj);
-  // The from-space object contains the real length.
-  int length                 = from_obj_array->length();
-
-  assert(from_obj->is_forwarded(), "must be forwarded");
-  oop to_obj                 = from_obj->forwardee();
-  assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
-  objArrayOop to_obj_array   = objArrayOop(to_obj);
-  // We keep track of the next start index in the length field of the
-  // to-space object.
-  int next_index             = to_obj_array->length();
-  assert(0 <= next_index && next_index < length,
-         err_msg("invariant, next index: %d, length: %d", next_index, length));
-
-  int start                  = next_index;
-  int end                    = length;
-  int remainder              = end - start;
-  // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
-  if (remainder > 2 * ParGCArrayScanChunk) {
-    end = start + ParGCArrayScanChunk;
-    to_obj_array->set_length(end);
-    // Push the remainder before we process the range in case another
-    // worker has run out of things to do and can steal it.
-    oop* from_obj_p = set_partial_array_mask(from_obj);
-    _par_scan_state->push_on_queue(from_obj_p);
-  } else {
-    assert(length == end, "sanity");
-    // We'll process the final range for this object. Restore the length
-    // so that the heap remains parsable in case of evacuation failure.
-    to_obj_array->set_length(end);
-  }
-  _scanner.set_region(_g1->heap_region_containing_raw(to_obj));
-  // Process indexes [start,end). It will also process the header
-  // along with the first chunk (i.e., the chunk with start == 0).
-  // Note that at this point the length field of to_obj_array is not
-  // correct given that we are using it to keep track of the next
-  // start index. oop_iterate_range() (thankfully!) ignores the length
-  // field and only relies on the start / end parameters.  It does
-  // however return the size of the object which will be incorrect. So
-  // we have to ignore it even if we wanted to use it.
-  to_obj_array->oop_iterate_range(&_scanner, start, end);
-}
-
 class G1ParEvacuateFollowersClosure : public VoidClosure {
 protected:
   G1CollectedHeap*              _g1h;
@@ -5022,13 +5023,9 @@
       ReferenceProcessor*             rp = _g1h->ref_processor_stw();
 
       G1ParScanThreadState            pss(_g1h, worker_id, rp);
-      G1ParScanHeapEvacClosure        scan_evac_cl(_g1h, &pss, rp);
       G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
-      G1ParScanPartialArrayClosure    partial_scan_cl(_g1h, &pss, rp);
-
-      pss.set_evac_closure(&scan_evac_cl);
+
       pss.set_evac_failure_closure(&evac_failure_cl);
-      pss.set_partial_scan_closure(&partial_scan_cl);
 
       G1ParScanExtRootClosure        only_scan_root_cl(_g1h, &pss, rp);
       G1ParScanMetadataClosure       only_scan_metadata_cl(_g1h, &pss, rp);
@@ -5270,6 +5267,33 @@
                            g1_unlink_task.strings_processed(), g1_unlink_task.strings_removed(),
                            g1_unlink_task.symbols_processed(), g1_unlink_task.symbols_removed());
   }
+
+  if (G1StringDedup::is_enabled()) {
+    G1StringDedup::unlink(is_alive);
+  }
+}
+
+class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
+public:
+  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+    *card_ptr = CardTableModRefBS::dirty_card_val();
+    return true;
+  }
+};
+
+void G1CollectedHeap::redirty_logged_cards() {
+  guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
+  double redirty_logged_cards_start = os::elapsedTime();
+
+  RedirtyLoggedCardTableEntryFastClosure redirty;
+  dirty_card_queue_set().set_closure(&redirty);
+  dirty_card_queue_set().apply_closure_to_all_completed_buffers();
+
+  DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
+  dcq.merge_bufferlists(&dirty_card_queue_set());
+  assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
+
+  g1_policy()->phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0);
 }
 
 // Weak Reference Processing support
@@ -5453,14 +5477,9 @@
     G1STWIsAliveClosure is_alive(_g1h);
 
     G1ParScanThreadState            pss(_g1h, worker_id, NULL);
-
-    G1ParScanHeapEvacClosure        scan_evac_cl(_g1h, &pss, NULL);
     G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-    G1ParScanPartialArrayClosure    partial_scan_cl(_g1h, &pss, NULL);
-
-    pss.set_evac_closure(&scan_evac_cl);
+
     pss.set_evac_failure_closure(&evac_failure_cl);
-    pss.set_partial_scan_closure(&partial_scan_cl);
 
     G1ParScanExtRootClosure        only_copy_non_heap_cl(_g1h, &pss, NULL);
     G1ParScanMetadataClosure       only_copy_metadata_cl(_g1h, &pss, NULL);
@@ -5565,13 +5584,9 @@
     HandleMark   hm;
 
     G1ParScanThreadState            pss(_g1h, worker_id, NULL);
-    G1ParScanHeapEvacClosure        scan_evac_cl(_g1h, &pss, NULL);
     G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-    G1ParScanPartialArrayClosure    partial_scan_cl(_g1h, &pss, NULL);
-
-    pss.set_evac_closure(&scan_evac_cl);
+
     pss.set_evac_failure_closure(&evac_failure_cl);
-    pss.set_partial_scan_closure(&partial_scan_cl);
 
     assert(pss.refs()->is_empty(), "both queue and overflow should be empty");
 
@@ -5695,13 +5710,9 @@
   // We do not embed a reference processor in the copying/scanning
   // closures while we're actually processing the discovered
   // reference objects.
-  G1ParScanHeapEvacClosure        scan_evac_cl(this, &pss, NULL);
   G1ParScanHeapEvacFailureClosure evac_failure_cl(this, &pss, NULL);
-  G1ParScanPartialArrayClosure    partial_scan_cl(this, &pss, NULL);
-
-  pss.set_evac_closure(&scan_evac_cl);
+
   pss.set_evac_failure_closure(&evac_failure_cl);
-  pss.set_partial_scan_closure(&partial_scan_cl);
 
   assert(pss.refs()->is_empty(), "pre-condition");
 
@@ -5883,6 +5894,9 @@
     G1STWIsAliveClosure is_alive(this);
     G1KeepAliveClosure keep_alive(this);
     JNIHandles::weak_oops_do(&is_alive, &keep_alive);
+    if (G1StringDedup::is_enabled()) {
+      G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive);
+    }
   }
 
   release_gc_alloc_regions(n_workers, evacuation_info);
@@ -5900,6 +5914,8 @@
   // strong code roots for a particular heap region.
   migrate_strong_code_roots();
 
+  purge_code_root_memory();
+
   if (g1_policy()->during_initial_mark_pause()) {
     // Reset the claim values set during marking the strong code roots
     reset_heap_region_claim_values();
@@ -5926,41 +5942,15 @@
   enqueue_discovered_references(n_workers);
 
   if (G1DeferredRSUpdate) {
-    RedirtyLoggedCardTableEntryFastClosure redirty;
-    dirty_card_queue_set().set_closure(&redirty);
-    dirty_card_queue_set().apply_closure_to_all_completed_buffers();
-
-    DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
-    dcq.merge_bufferlists(&dirty_card_queue_set());
-    assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
+    redirty_logged_cards();
   }
   COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 }
 
-void G1CollectedHeap::free_region_if_empty(HeapRegion* hr,
-                                     size_t* pre_used,
-                                     FreeRegionList* free_list,
-                                     OldRegionSet* old_proxy_set,
-                                     HumongousRegionSet* humongous_proxy_set,
-                                     HRRSCleanupTask* hrrs_cleanup_task,
-                                     bool par) {
-  if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) {
-    if (hr->isHumongous()) {
-      assert(hr->startsHumongous(), "we should only see starts humongous");
-      free_humongous_region(hr, pre_used, free_list, humongous_proxy_set, par);
-    } else {
-      _old_set.remove_with_proxy(hr, old_proxy_set);
-      free_region(hr, pre_used, free_list, par);
-    }
-  } else {
-    hr->rem_set()->do_cleanup_work(hrrs_cleanup_task);
-  }
-}
-
 void G1CollectedHeap::free_region(HeapRegion* hr,
-                                  size_t* pre_used,
                                   FreeRegionList* free_list,
-                                  bool par) {
+                                  bool par,
+                                  bool locked) {
   assert(!hr->isHumongous(), "this is only for non-humongous regions");
   assert(!hr->is_empty(), "the region should not be empty");
   assert(free_list != NULL, "pre-condition");
@@ -5971,70 +5961,56 @@
   if (!hr->is_young()) {
     _cg1r->hot_card_cache()->reset_card_counts(hr);
   }
-  *pre_used += hr->used();
-  hr->hr_clear(par, true /* clear_space */);
-  free_list->add_as_head(hr);
+  hr->hr_clear(par, true /* clear_space */, locked /* locked */);
+  free_list->add_ordered(hr);
 }
 
 void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
-                                     size_t* pre_used,
                                      FreeRegionList* free_list,
-                                     HumongousRegionSet* humongous_proxy_set,
                                      bool par) {
   assert(hr->startsHumongous(), "this is only for starts humongous regions");
   assert(free_list != NULL, "pre-condition");
-  assert(humongous_proxy_set != NULL, "pre-condition");
-
-  size_t hr_used = hr->used();
+
   size_t hr_capacity = hr->capacity();
-  size_t hr_pre_used = 0;
-  _humongous_set.remove_with_proxy(hr, humongous_proxy_set);
   // We need to read this before we make the region non-humongous,
   // otherwise the information will be gone.
   uint last_index = hr->last_hc_index();
   hr->set_notHumongous();
-  free_region(hr, &hr_pre_used, free_list, par);
+  free_region(hr, free_list, par);
 
   uint i = hr->hrs_index() + 1;
   while (i < last_index) {
     HeapRegion* curr_hr = region_at(i);
     assert(curr_hr->continuesHumongous(), "invariant");
     curr_hr->set_notHumongous();
-    free_region(curr_hr, &hr_pre_used, free_list, par);
+    free_region(curr_hr, free_list, par);
     i += 1;
   }
-  assert(hr_pre_used == hr_used,
-         err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" "
-                 "should be the same", hr_pre_used, hr_used));
-  *pre_used += hr_pre_used;
-}
-
-void G1CollectedHeap::update_sets_after_freeing_regions(size_t pre_used,
-                                       FreeRegionList* free_list,
-                                       OldRegionSet* old_proxy_set,
-                                       HumongousRegionSet* humongous_proxy_set,
-                                       bool par) {
-  if (pre_used > 0) {
-    Mutex* lock = (par) ? ParGCRareEvent_lock : NULL;
-    MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
-    assert(_summary_bytes_used >= pre_used,
-           err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" "
-                   "should be >= pre_used: "SIZE_FORMAT,
-                   _summary_bytes_used, pre_used));
-    _summary_bytes_used -= pre_used;
-  }
-  if (free_list != NULL && !free_list->is_empty()) {
+}
+
+void G1CollectedHeap::remove_from_old_sets(const HeapRegionSetCount& old_regions_removed,
+                                       const HeapRegionSetCount& humongous_regions_removed) {
+  if (old_regions_removed.length() > 0 || humongous_regions_removed.length() > 0) {
+    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+    _old_set.bulk_remove(old_regions_removed);
+    _humongous_set.bulk_remove(humongous_regions_removed);
+  }
+
+}
+
+void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) {
+  assert(list != NULL, "list can't be null");
+  if (!list->is_empty()) {
     MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
-    _free_list.add_as_head(free_list);
-  }
-  if (old_proxy_set != NULL && !old_proxy_set->is_empty()) {
-    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
-    _old_set.update_from_proxy(old_proxy_set);
-  }
-  if (humongous_proxy_set != NULL && !humongous_proxy_set->is_empty()) {
-    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
-    _humongous_set.update_from_proxy(humongous_proxy_set);
-  }
+    _free_list.add_ordered(list);
+  }
+}
+
+void G1CollectedHeap::decrement_summary_bytes(size_t bytes) {
+  assert(_summary_bytes_used >= bytes,
+         err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" should be >= bytes: "SIZE_FORMAT,
+                  _summary_bytes_used, bytes));
+  _summary_bytes_used -= bytes;
 }
 
 class G1ParCleanupCTTask : public AbstractGangTask {
@@ -6194,7 +6170,7 @@
       }
     }
 
-    rs_lengths += cur->rem_set()->occupied();
+    rs_lengths += cur->rem_set()->occupied_locked();
 
     HeapRegion* next = cur->next_in_collection_set();
     assert(cur->in_collection_set(), "bad CS");
@@ -6227,7 +6203,8 @@
 
       // And the region is empty.
       assert(!used_mr.is_empty(), "Should not have empty regions in a CS.");
-      free_region(cur, &pre_used, &local_free_list, false /* par */);
+      pre_used += cur->used();
+      free_region(cur, &local_free_list, false /* par */, true /* locked */);
     } else {
       cur->uninstall_surv_rate_group();
       if (cur->is_young()) {
@@ -6255,10 +6232,8 @@
     young_time_ms += elapsed_ms;
   }
 
-  update_sets_after_freeing_regions(pre_used, &local_free_list,
-                                    NULL /* old_proxy_set */,
-                                    NULL /* humongous_proxy_set */,
-                                    false /* par */);
+  prepend_to_freelist(&local_free_list);
+  decrement_summary_bytes(pre_used);
   policy->phase_times()->record_young_free_cset_time_ms(young_time_ms);
   policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms);
 }
@@ -6370,10 +6345,10 @@
 
 class TearDownRegionSetsClosure : public HeapRegionClosure {
 private:
-  OldRegionSet *_old_set;
+  HeapRegionSet *_old_set;
 
 public:
-  TearDownRegionSetsClosure(OldRegionSet* old_set) : _old_set(old_set) { }
+  TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { }
 
   bool doHeapRegion(HeapRegion* r) {
     if (r->is_empty()) {
@@ -6402,9 +6377,10 @@
     TearDownRegionSetsClosure cl(&_old_set);
     heap_region_iterate(&cl);
 
-    // Need to do this after the heap iteration to be able to
-    // recognize the young regions and ignore them during the iteration.
-    _young_list->empty_list();
+    // Note that emptying the _young_list is postponed and instead done as
+    // the first step when rebuilding the regions sets again. The reason for
+    // this is that during a full GC string deduplication needs to know if
+    // a collected region was young or old when the full GC was initiated.
   }
   _free_list.remove_all();
 }
@@ -6412,13 +6388,13 @@
 class RebuildRegionSetsClosure : public HeapRegionClosure {
 private:
   bool            _free_list_only;
-  OldRegionSet*   _old_set;
+  HeapRegionSet*   _old_set;
   FreeRegionList* _free_list;
   size_t          _total_used;
 
 public:
   RebuildRegionSetsClosure(bool free_list_only,
-                           OldRegionSet* old_set, FreeRegionList* free_list) :
+                           HeapRegionSet* old_set, FreeRegionList* free_list) :
     _free_list_only(free_list_only),
     _old_set(old_set), _free_list(free_list), _total_used(0) {
     assert(_free_list->is_empty(), "pre-condition");
@@ -6458,6 +6434,10 @@
 void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
   assert_at_safepoint(true /* should_be_vm_thread */);
 
+  if (!free_list_only) {
+    _young_list->empty_list();
+  }
+
   RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_free_list);
   heap_region_iterate(&cl);
 
@@ -6493,6 +6473,7 @@
   bool young_list_full = g1_policy()->is_young_list_full();
   if (force || !young_list_full) {
     HeapRegion* new_alloc_region = new_region(word_size,
+                                              false /* is_old */,
                                               false /* do_expand */);
     if (new_alloc_region != NULL) {
       set_region_short_lived_locked(new_alloc_region);
@@ -6551,14 +6532,16 @@
   assert(FreeList_lock->owned_by_self(), "pre-condition");
 
   if (count < g1_policy()->max_regions(ap)) {
+    bool survivor = (ap == GCAllocForSurvived);
     HeapRegion* new_alloc_region = new_region(word_size,
+                                              !survivor,
                                               true /* do_expand */);
     if (new_alloc_region != NULL) {
       // We really only need to do this for old regions given that we
       // should never scan survivors. But it doesn't hurt to do it
       // for survivors too.
       new_alloc_region->set_saved_mark();
-      if (ap == GCAllocForSurvived) {
+      if (survivor) {
         new_alloc_region->set_survivor();
         _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor);
       } else {
@@ -6615,23 +6598,22 @@
 
 class VerifyRegionListsClosure : public HeapRegionClosure {
 private:
-  FreeRegionList*     _free_list;
-  OldRegionSet*       _old_set;
-  HumongousRegionSet* _humongous_set;
-  uint                _region_count;
+  HeapRegionSet*   _old_set;
+  HeapRegionSet*   _humongous_set;
+  FreeRegionList*  _free_list;
 
 public:
-  VerifyRegionListsClosure(OldRegionSet* old_set,
-                           HumongousRegionSet* humongous_set,
+  HeapRegionSetCount _old_count;
+  HeapRegionSetCount _humongous_count;
+  HeapRegionSetCount _free_count;
+
+  VerifyRegionListsClosure(HeapRegionSet* old_set,
+                           HeapRegionSet* humongous_set,
                            FreeRegionList* free_list) :
-    _old_set(old_set), _humongous_set(humongous_set),
-    _free_list(free_list), _region_count(0) { }
-
-  uint region_count() { return _region_count; }
+    _old_set(old_set), _humongous_set(humongous_set), _free_list(free_list),
+    _old_count(), _humongous_count(), _free_count(){ }
 
   bool doHeapRegion(HeapRegion* hr) {
-    _region_count += 1;
-
     if (hr->continuesHumongous()) {
       return false;
     }
@@ -6639,14 +6621,31 @@
     if (hr->is_young()) {
       // TODO
     } else if (hr->startsHumongous()) {
-      _humongous_set->verify_next_region(hr);
+      assert(hr->containing_set() == _humongous_set, err_msg("Heap region %u is starts humongous but not in humongous set.", hr->hrs_index()));
+      _humongous_count.increment(1u, hr->capacity());
     } else if (hr->is_empty()) {
-      _free_list->verify_next_region(hr);
+      assert(hr->containing_set() == _free_list, err_msg("Heap region %u is empty but not on the free list.", hr->hrs_index()));
+      _free_count.increment(1u, hr->capacity());
     } else {
-      _old_set->verify_next_region(hr);
+      assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrs_index()));
+      _old_count.increment(1u, hr->capacity());
     }
     return false;
   }
+
+  void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, FreeRegionList* free_list) {
+    guarantee(old_set->length() == _old_count.length(), err_msg("Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count.length()));
+    guarantee(old_set->total_capacity_bytes() == _old_count.capacity(), err_msg("Old set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
+        old_set->total_capacity_bytes(), _old_count.capacity()));
+
+    guarantee(humongous_set->length() == _humongous_count.length(), err_msg("Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count.length()));
+    guarantee(humongous_set->total_capacity_bytes() == _humongous_count.capacity(), err_msg("Hum set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
+        humongous_set->total_capacity_bytes(), _humongous_count.capacity()));
+
+    guarantee(free_list->length() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->length(), _free_count.length()));
+    guarantee(free_list->total_capacity_bytes() == _free_count.capacity(), err_msg("Free list capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
+        free_list->total_capacity_bytes(), _free_count.capacity()));
+  }
 };
 
 HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
@@ -6662,16 +6661,14 @@
   assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
 
   // First, check the explicit lists.
-  _free_list.verify();
+  _free_list.verify_list();
   {
     // Given that a concurrent operation might be adding regions to
     // the secondary free list we have to take the lock before
     // verifying it.
     MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
-    _secondary_free_list.verify();
-  }
-  _old_set.verify();
-  _humongous_set.verify();
+    _secondary_free_list.verify_list();
+  }
 
   // If a concurrent region freeing operation is in progress it will
   // be difficult to correctly attributed any free regions we come
@@ -6694,16 +6691,10 @@
 
   // Finally, make sure that the region accounting in the lists is
   // consistent with what we see in the heap.
-  _old_set.verify_start();
-  _humongous_set.verify_start();
-  _free_list.verify_start();
 
   VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_free_list);
   heap_region_iterate(&cl);
-
-  _old_set.verify_end();
-  _humongous_set.verify_end();
-  _free_list.verify_end();
+  cl.verify_counts(&_old_set, &_humongous_set, &_free_list);
 }
 
 // Optimized nmethod scanning
@@ -6804,6 +6795,13 @@
   g1_policy()->phase_times()->record_strong_code_root_migration_time(migration_time_ms);
 }
 
+void G1CollectedHeap::purge_code_root_memory() {
+  double purge_start = os::elapsedTime();
+  G1CodeRootSet::purge_chunks(G1CodeRootsChunkCacheKeepPercent);
+  double purge_time_ms = (os::elapsedTime() - purge_start) * 1000.0;
+  g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms);
+}
+
 // Mark all the code roots that point into regions *not* in the
 // collection set.
 //
@@ -6874,7 +6872,7 @@
       // Code roots should never be attached to a continuation of a humongous region
       assert(hrrs->strong_code_roots_list_length() == 0,
              err_msg("code roots should never be attached to continuations of humongous region "HR_FORMAT
-                     " starting at "HR_FORMAT", but has "INT32_FORMAT,
+                     " starting at "HR_FORMAT", but has "SIZE_FORMAT,
                      HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()),
                      hrrs->strong_code_roots_list_length()));
       return false;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -34,7 +34,7 @@
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
 #include "gc_implementation/g1/heapRegionSeq.hpp"
-#include "gc_implementation/g1/heapRegionSets.hpp"
+#include "gc_implementation/g1/heapRegionSet.hpp"
 #include "gc_implementation/shared/hSpaceCounters.hpp"
 #include "gc_implementation/shared/parGCAllocBuffer.hpp"
 #include "memory/barrierSet.hpp"
@@ -243,18 +243,18 @@
   MemRegion _g1_committed;
 
   // The master free list. It will satisfy all new region allocations.
-  MasterFreeRegionList      _free_list;
+  FreeRegionList _free_list;
 
   // The secondary free list which contains regions that have been
   // freed up during the cleanup process. This will be appended to the
   // master free list when appropriate.
-  SecondaryFreeRegionList   _secondary_free_list;
+  FreeRegionList _secondary_free_list;
 
   // It keeps track of the old regions.
-  MasterOldRegionSet        _old_set;
+  HeapRegionSet _old_set;
 
   // It keeps track of the humongous regions.
-  MasterHumongousRegionSet  _humongous_set;
+  HeapRegionSet _humongous_set;
 
   // The number of regions we could create by expansion.
   uint _expansion_regions;
@@ -497,13 +497,14 @@
   // check whether there's anything available on the
   // secondary_free_list and/or wait for more regions to appear on
   // that list, if _free_regions_coming is set.
-  HeapRegion* new_region_try_secondary_free_list();
+  HeapRegion* new_region_try_secondary_free_list(bool is_old);
 
   // Try to allocate a single non-humongous HeapRegion sufficient for
   // an allocation of the given word_size. If do_expand is true,
   // attempt to expand the heap if necessary to satisfy the allocation
-  // request.
-  HeapRegion* new_region(size_t word_size, bool do_expand);
+  // request. If the region is to be used as an old region or for a
+  // humongous object, set is_old to true. If not, to false.
+  HeapRegion* new_region(size_t word_size, bool is_old, bool do_expand);
 
   // Attempt to satisfy a humongous allocation request of the given
   // size by finding a contiguous set of free regions of num_regions
@@ -705,19 +706,7 @@
   // This is a fast test on whether a reference points into the
   // collection set or not. Assume that the reference
   // points into the heap.
-  bool in_cset_fast_test(oop obj) {
-    assert(_in_cset_fast_test != NULL, "sanity");
-    assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj));
-    // no need to subtract the bottom of the heap from obj,
-    // _in_cset_fast_test is biased
-    uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
-    bool ret = _in_cset_fast_test[index];
-    // let's make sure the result is consistent with what the slower
-    // test returns
-    assert( ret || !obj_in_cs(obj), "sanity");
-    assert(!ret ||  obj_in_cs(obj), "sanity");
-    return ret;
-  }
+  inline bool in_cset_fast_test(oop obj);
 
   void clear_cset_fast_test() {
     assert(_in_cset_fast_test_base != NULL, "sanity");
@@ -757,6 +746,29 @@
 
   G1HRPrinter* hr_printer() { return &_hr_printer; }
 
+  // Frees a non-humongous region by initializing its contents and
+  // adding it to the free list that's passed as a parameter (this is
+  // usually a local list which will be appended to the master free
+  // list later). The used bytes of freed regions are accumulated in
+  // pre_used. If par is true, the region's RSet will not be freed
+  // up. The assumption is that this will be done later.
+  // The locked parameter indicates if the caller has already taken
+  // care of proper synchronization. This may allow some optimizations.
+  void free_region(HeapRegion* hr,
+                   FreeRegionList* free_list,
+                   bool par,
+                   bool locked = false);
+
+  // Frees a humongous region by collapsing it into individual regions
+  // and calling free_region() for each of them. The freed regions
+  // will be added to the free list that's passed as a parameter (this
+  // is usually a local list which will be appended to the master free
+  // list later). The used bytes of freed regions are accumulated in
+  // pre_used. If par is true, the region's RSet will not be freed
+  // up. The assumption is that this will be done later.
+  void free_humongous_region(HeapRegion* hr,
+                             FreeRegionList* free_list,
+                             bool par);
 protected:
 
   // Shrink the garbage-first heap by at most the given size (in bytes!).
@@ -835,30 +847,6 @@
                                G1KlassScanClosure* scan_klasses,
                                int worker_i);
 
-  // Frees a non-humongous region by initializing its contents and
-  // adding it to the free list that's passed as a parameter (this is
-  // usually a local list which will be appended to the master free
-  // list later). The used bytes of freed regions are accumulated in
-  // pre_used. If par is true, the region's RSet will not be freed
-  // up. The assumption is that this will be done later.
-  void free_region(HeapRegion* hr,
-                   size_t* pre_used,
-                   FreeRegionList* free_list,
-                   bool par);
-
-  // Frees a humongous region by collapsing it into individual regions
-  // and calling free_region() for each of them. The freed regions
-  // will be added to the free list that's passed as a parameter (this
-  // is usually a local list which will be appended to the master free
-  // list later). The used bytes of freed regions are accumulated in
-  // pre_used. If par is true, the region's RSet will not be freed
-  // up. The assumption is that this will be done later.
-  void free_humongous_region(HeapRegion* hr,
-                             size_t* pre_used,
-                             FreeRegionList* free_list,
-                             HumongousRegionSet* humongous_proxy_set,
-                             bool par);
-
   // Notifies all the necessary spaces that the committed space has
   // been updated (either expanded or shrunk). It should be called
   // after _g1_storage is updated.
@@ -1228,21 +1216,17 @@
   bool is_on_master_free_list(HeapRegion* hr) {
     return hr->containing_set() == &_free_list;
   }
-
-  bool is_in_humongous_set(HeapRegion* hr) {
-    return hr->containing_set() == &_humongous_set;
-  }
 #endif // ASSERT
 
   // Wrapper for the region list operations that can be called from
   // methods outside this class.
 
-  void secondary_free_list_add_as_tail(FreeRegionList* list) {
-    _secondary_free_list.add_as_tail(list);
+  void secondary_free_list_add(FreeRegionList* list) {
+    _secondary_free_list.add_ordered(list);
   }
 
   void append_secondary_free_list() {
-    _free_list.add_as_head(&_secondary_free_list);
+    _free_list.add_ordered(&_secondary_free_list);
   }
 
   void append_secondary_free_list_if_not_empty_with_lock() {
@@ -1254,9 +1238,7 @@
     }
   }
 
-  void old_set_remove(HeapRegion* hr) {
-    _old_set.remove(hr);
-  }
+  inline void old_set_remove(HeapRegion* hr);
 
   size_t non_young_capacity_bytes() {
     return _old_set.total_capacity_bytes() + _humongous_set.total_capacity_bytes();
@@ -1284,27 +1266,9 @@
   // True iff an evacuation has failed in the most-recent collection.
   bool evacuation_failed() { return _evacuation_failed; }
 
-  // It will free a region if it has allocated objects in it that are
-  // all dead. It calls either free_region() or
-  // free_humongous_region() depending on the type of the region that
-  // is passed to it.
-  void free_region_if_empty(HeapRegion* hr,
-                            size_t* pre_used,
-                            FreeRegionList* free_list,
-                            OldRegionSet* old_proxy_set,
-                            HumongousRegionSet* humongous_proxy_set,
-                            HRRSCleanupTask* hrrs_cleanup_task,
-                            bool par);
-
-  // It appends the free list to the master free list and updates the
-  // master humongous list according to the contents of the proxy
-  // list. It also adjusts the total used bytes according to pre_used
-  // (if par is true, it will do so by taking the ParGCRareEvent_lock).
-  void update_sets_after_freeing_regions(size_t pre_used,
-                                       FreeRegionList* free_list,
-                                       OldRegionSet* old_proxy_set,
-                                       HumongousRegionSet* humongous_proxy_set,
-                                       bool par);
+  void remove_from_old_sets(const HeapRegionSetCount& old_regions_removed, const HeapRegionSetCount& humongous_regions_removed);
+  void prepend_to_freelist(FreeRegionList* list);
+  void decrement_summary_bytes(size_t bytes);
 
   // Returns "TRUE" iff "p" points into the committed areas of the heap.
   virtual bool is_in(const void* p) const;
@@ -1365,7 +1329,7 @@
   void heap_region_iterate(HeapRegionClosure* blk) const;
 
   // Return the region with the given index. It assumes the index is valid.
-  HeapRegion* region_at(uint index) const { return _hrs.at(index); }
+  inline HeapRegion* region_at(uint index) const;
 
   // Divide the heap region sequence into "chunks" of some size (the number
   // of regions divided by the number of parallel threads times some
@@ -1494,10 +1458,7 @@
     return true;
   }
 
-  bool is_in_young(const oop obj) {
-    HeapRegion* hr = heap_region_containing(obj);
-    return hr != NULL && hr->is_young();
-  }
+  inline bool is_in_young(const oop obj);
 
 #ifdef ASSERT
   virtual bool is_in_partial_collection(const void* p);
@@ -1510,9 +1471,7 @@
   // pre-value that needs to be remembered; for the remembered-set
   // update logging post-barrier, we don't maintain remembered set
   // information for young gen objects.
-  virtual bool can_elide_initializing_store_barrier(oop new_obj) {
-    return is_in_young(new_obj);
-  }
+  virtual inline bool can_elide_initializing_store_barrier(oop new_obj);
 
   // Returns "true" iff the given word_size is "very large".
   static bool isHumongous(size_t word_size) {
@@ -1606,23 +1565,9 @@
 
   // Added if it is NULL it isn't dead.
 
-  bool is_obj_dead(const oop obj) const {
-    const HeapRegion* hr = heap_region_containing(obj);
-    if (hr == NULL) {
-      if (obj == NULL) return false;
-      else return true;
-    }
-    else return is_obj_dead(obj, hr);
-  }
+  inline bool is_obj_dead(const oop obj) const;
 
-  bool is_obj_ill(const oop obj) const {
-    const HeapRegion* hr = heap_region_containing(obj);
-    if (hr == NULL) {
-      if (obj == NULL) return false;
-      else return true;
-    }
-    else return is_obj_ill(obj, hr);
-  }
+  inline bool is_obj_ill(const oop obj) const;
 
   bool allocated_since_marking(oop obj, HeapRegion* hr, VerifyOption vo);
   HeapWord* top_at_mark_start(HeapRegion* hr, VerifyOption vo);
@@ -1659,6 +1604,9 @@
   // that were not successfully evacuated are not migrated.
   void migrate_strong_code_roots();
 
+  // Free up superfluous code root memory.
+  void purge_code_root_memory();
+
   // During an initial mark pause, mark all the code roots that
   // point into regions *not* in the collection set.
   void mark_strong_code_roots(uint worker_id);
@@ -1671,6 +1619,8 @@
   // in symbol table, possibly in parallel.
   void unlink_string_and_symbol_table(BoolObjectClosure* is_alive, bool unlink_strings = true, bool unlink_symbols = true);
 
+  // Redirty logged cards in the refinement queue.
+  void redirty_logged_cards();
   // Verification
 
   // The following is just to alert the verification code
@@ -1711,26 +1661,10 @@
 
   bool is_obj_dead_cond(const oop obj,
                         const HeapRegion* hr,
-                        const VerifyOption vo) const {
-    switch (vo) {
-    case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
-    case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
-    case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
-    default:                            ShouldNotReachHere();
-    }
-    return false; // keep some compilers happy
-  }
+                        const VerifyOption vo) const;
 
   bool is_obj_dead_cond(const oop obj,
-                        const VerifyOption vo) const {
-    switch (vo) {
-    case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
-    case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
-    case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
-    default:                            ShouldNotReachHere();
-    }
-    return false; // keep some compilers happy
-  }
+                        const VerifyOption vo) const;
 
   // Printing
 
@@ -1797,8 +1731,6 @@
   size_t           _undo_waste;
 
   OopsInHeapRegionClosure*      _evac_failure_cl;
-  G1ParScanHeapEvacClosure*     _evac_cl;
-  G1ParScanPartialArrayClosure* _partial_scan_cl;
 
   int  _hash_seed;
   uint _queue_num;
@@ -1826,11 +1758,7 @@
   DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
   G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
 
-  template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) {
-    if (!from->is_survivor()) {
-      _g1_rem->par_write_ref(from, p, tid);
-    }
-  }
+  template <class T> inline void immediate_rs_update(HeapRegion* from, T* p, int tid);
 
   template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
     // If the new value of the field points to the same region or
@@ -1872,13 +1800,7 @@
     refs()->push(ref);
   }
 
-  template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
-    if (G1DeferredRSUpdate) {
-      deferred_rs_update(from, p, tid);
-    } else {
-      immediate_rs_update(from, p, tid);
-    }
-  }
+  template <class T> inline void update_rs(HeapRegion* from, T* p, int tid);
 
   HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
     HeapWord* obj = NULL;
@@ -1926,14 +1848,6 @@
     return _evac_failure_cl;
   }
 
-  void set_evac_closure(G1ParScanHeapEvacClosure* evac_cl) {
-    _evac_cl = evac_cl;
-  }
-
-  void set_partial_scan_closure(G1ParScanPartialArrayClosure* partial_scan_cl) {
-    _partial_scan_cl = partial_scan_cl;
-  }
-
   int* hash_seed() { return &_hash_seed; }
   uint queue_num() { return _queue_num; }
 
@@ -1981,30 +1895,68 @@
                                                  false /* retain */);
     }
   }
+private:
+  #define G1_PARTIAL_ARRAY_MASK 0x2
+
+  inline bool has_partial_array_mask(oop* ref) const {
+    return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
+  }
+
+  // We never encode partial array oops as narrowOop*, so return false immediately.
+  // This allows the compiler to create optimized code when popping references from
+  // the work queue.
+  inline bool has_partial_array_mask(narrowOop* ref) const {
+    assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*");
+    return false;
+  }
+
+  // Only implement set_partial_array_mask() for regular oops, not for narrowOops.
+  // We always encode partial arrays as regular oop, to allow the
+  // specialization for has_partial_array_mask() for narrowOops above.
+  // This means that unintentional use of this method with narrowOops are caught
+  // by the compiler.
+  inline oop* set_partial_array_mask(oop obj) const {
+    assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
+    return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK);
+  }
+
+  inline oop clear_partial_array_mask(oop* ref) const {
+    return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
+  }
+
+  inline void do_oop_partial_array(oop* p);
+
+  // This method is applied to the fields of the objects that have just been copied.
+  template <class T> void do_oop_evac(T* p, HeapRegion* from) {
+    assert(!oopDesc::is_null(oopDesc::load_decode_heap_oop(p)),
+           "Reference should not be NULL here as such are never pushed to the task queue.");
+    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
+
+    // Although we never intentionally push references outside of the collection
+    // set, due to (benign) races in the claim mechanism during RSet scanning more
+    // than one thread might claim the same card. So the same card may be
+    // processed multiple times. So redo this check.
+    if (_g1h->in_cset_fast_test(obj)) {
+      oop forwardee;
+      if (obj->is_forwarded()) {
+        forwardee = obj->forwardee();
+      } else {
+        forwardee = copy_to_survivor_space(obj);
+      }
+      assert(forwardee != NULL, "forwardee should not be NULL");
+      oopDesc::encode_store_heap_oop(p, forwardee);
+    }
+
+    assert(obj != NULL, "Must be");
+    update_rs(from, p, queue_num());
+  }
+public:
 
   oop copy_to_survivor_space(oop const obj);
 
-  template <class T> void deal_with_reference(T* ref_to_scan) {
-    if (has_partial_array_mask(ref_to_scan)) {
-      _partial_scan_cl->do_oop_nv(ref_to_scan);
-    } else {
-      // Note: we can use "raw" versions of "region_containing" because
-      // "obj_to_scan" is definitely in the heap, and is not in a
-      // humongous region.
-      HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
-      _evac_cl->set_region(r);
-      _evac_cl->do_oop_nv(ref_to_scan);
-    }
-  }
+  template <class T> inline void deal_with_reference(T* ref_to_scan);
 
-  void deal_with_reference(StarTask ref) {
-    assert(verify_task(ref), "sanity");
-    if (ref.is_narrow()) {
-      deal_with_reference((narrowOop*)ref);
-    } else {
-      deal_with_reference((oop*)ref);
-    }
-  }
+  inline void deal_with_reference(StarTask ref);
 
 public:
   void trim_queue();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -29,12 +29,17 @@
 #include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1AllocRegion.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1RemSet.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
 // Inline functions for G1CollectedHeap
 
+// Return the region with the given index. It assumes the index is valid.
+inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrs.at(index); }
+
 template <class T>
 inline HeapRegion*
 G1CollectedHeap::heap_region_containing(const T addr) const {
@@ -54,6 +59,10 @@
   return res;
 }
 
+inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
+  _old_set.remove(hr);
+}
+
 inline bool G1CollectedHeap::obj_in_cs(oop obj) {
   HeapRegion* r = _hrs.addr_to_region((HeapWord*) obj);
   return r != NULL && r->in_collection_set();
@@ -150,6 +159,24 @@
   return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj);
 }
 
+
+// This is a fast test on whether a reference points into the
+// collection set or not. Assume that the reference
+// points into the heap.
+inline bool G1CollectedHeap::in_cset_fast_test(oop obj) {
+  assert(_in_cset_fast_test != NULL, "sanity");
+  assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj));
+  // no need to subtract the bottom of the heap from obj,
+  // _in_cset_fast_test is biased
+  uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
+  bool ret = _in_cset_fast_test[index];
+  // let's make sure the result is consistent with what the slower
+  // test returns
+  assert( ret || !obj_in_cs(obj), "sanity");
+  assert(!ret ||  obj_in_cs(obj), "sanity");
+  return ret;
+}
+
 #ifndef PRODUCT
 // Support for G1EvacuationFailureALot
 
@@ -223,4 +250,121 @@
 }
 #endif  // #ifndef PRODUCT
 
+inline bool G1CollectedHeap::is_in_young(const oop obj) {
+  HeapRegion* hr = heap_region_containing(obj);
+  return hr != NULL && hr->is_young();
+}
+
+// We don't need barriers for initializing stores to objects
+// in the young gen: for the SATB pre-barrier, there is no
+// pre-value that needs to be remembered; for the remembered-set
+// update logging post-barrier, we don't maintain remembered set
+// information for young gen objects.
+inline bool G1CollectedHeap::can_elide_initializing_store_barrier(oop new_obj) {
+  return is_in_young(new_obj);
+}
+
+inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
+  const HeapRegion* hr = heap_region_containing(obj);
+  if (hr == NULL) {
+    if (obj == NULL) return false;
+    else return true;
+  }
+  else return is_obj_dead(obj, hr);
+}
+
+inline bool G1CollectedHeap::is_obj_ill(const oop obj) const {
+  const HeapRegion* hr = heap_region_containing(obj);
+  if (hr == NULL) {
+    if (obj == NULL) return false;
+    else return true;
+  }
+  else return is_obj_ill(obj, hr);
+}
+
+template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
+  if (!from->is_survivor()) {
+    _g1_rem->par_write_ref(from, p, tid);
+  }
+}
+
+template <class T> void G1ParScanThreadState::update_rs(HeapRegion* from, T* p, int tid) {
+  if (G1DeferredRSUpdate) {
+    deferred_rs_update(from, p, tid);
+  } else {
+    immediate_rs_update(from, p, tid);
+  }
+}
+
+
+inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
+  assert(has_partial_array_mask(p), "invariant");
+  oop from_obj = clear_partial_array_mask(p);
+
+  assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
+  assert(from_obj->is_objArray(), "must be obj array");
+  objArrayOop from_obj_array = objArrayOop(from_obj);
+  // The from-space object contains the real length.
+  int length                 = from_obj_array->length();
+
+  assert(from_obj->is_forwarded(), "must be forwarded");
+  oop to_obj                 = from_obj->forwardee();
+  assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
+  objArrayOop to_obj_array   = objArrayOop(to_obj);
+  // We keep track of the next start index in the length field of the
+  // to-space object.
+  int next_index             = to_obj_array->length();
+  assert(0 <= next_index && next_index < length,
+         err_msg("invariant, next index: %d, length: %d", next_index, length));
+
+  int start                  = next_index;
+  int end                    = length;
+  int remainder              = end - start;
+  // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
+  if (remainder > 2 * ParGCArrayScanChunk) {
+    end = start + ParGCArrayScanChunk;
+    to_obj_array->set_length(end);
+    // Push the remainder before we process the range in case another
+    // worker has run out of things to do and can steal it.
+    oop* from_obj_p = set_partial_array_mask(from_obj);
+    push_on_queue(from_obj_p);
+  } else {
+    assert(length == end, "sanity");
+    // We'll process the final range for this object. Restore the length
+    // so that the heap remains parsable in case of evacuation failure.
+    to_obj_array->set_length(end);
+  }
+  _scanner.set_region(_g1h->heap_region_containing_raw(to_obj));
+  // Process indexes [start,end). It will also process the header
+  // along with the first chunk (i.e., the chunk with start == 0).
+  // Note that at this point the length field of to_obj_array is not
+  // correct given that we are using it to keep track of the next
+  // start index. oop_iterate_range() (thankfully!) ignores the length
+  // field and only relies on the start / end parameters.  It does
+  // however return the size of the object which will be incorrect. So
+  // we have to ignore it even if we wanted to use it.
+  to_obj_array->oop_iterate_range(&_scanner, start, end);
+}
+
+template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
+  if (!has_partial_array_mask(ref_to_scan)) {
+    // Note: we can use "raw" versions of "region_containing" because
+    // "obj_to_scan" is definitely in the heap, and is not in a
+    // humongous region.
+    HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
+    do_oop_evac(ref_to_scan, r);
+  } else {
+    do_oop_partial_array((oop*)ref_to_scan);
+  }
+}
+
+inline void G1ParScanThreadState::deal_with_reference(StarTask ref) {
+  assert(verify_task(ref), "sanity");
+  if (ref.is_narrow()) {
+    deal_with_reference((narrowOop*)ref);
+  } else {
+    deal_with_reference((oop*)ref);
+  }
+}
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -27,6 +27,7 @@
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1GCPhaseTimes.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
 
 // Helper class for avoiding interleaved logging
 class LineBuffer: public StackObj {
@@ -168,7 +169,9 @@
   _last_termination_attempts(_max_gc_threads, SIZE_FORMAT),
   _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false),
   _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"),
-  _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf")
+  _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"),
+  _cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"),
+  _cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf")
 {
   assert(max_gc_threads > 0, "Must have some GC threads");
 }
@@ -229,6 +232,16 @@
   _last_gc_worker_other_times_ms.verify();
 }
 
+void G1GCPhaseTimes::note_string_dedup_fixup_start() {
+  _cur_string_dedup_queue_fixup_worker_times_ms.reset();
+  _cur_string_dedup_table_fixup_worker_times_ms.reset();
+}
+
+void G1GCPhaseTimes::note_string_dedup_fixup_end() {
+  _cur_string_dedup_queue_fixup_worker_times_ms.verify();
+  _cur_string_dedup_table_fixup_worker_times_ms.verify();
+}
+
 void G1GCPhaseTimes::print_stats(int level, const char* str, double value) {
   LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
 }
@@ -250,6 +263,14 @@
     // Strong code root migration time
     misc_time_ms += _cur_strong_code_root_migration_time_ms;
 
+    // Strong code root purge time
+    misc_time_ms += _cur_strong_code_root_purge_time_ms;
+
+    if (G1StringDedup::is_enabled()) {
+      // String dedup fixup time
+      misc_time_ms += _cur_string_dedup_fixup_time_ms;
+    }
+
     // Subtract the time taken to clean the card table from the
     // current value of "other time"
     misc_time_ms += _cur_clear_ct_time_ms;
@@ -299,20 +320,43 @@
   }
   print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
   print_stats(1, "Code Root Migration", _cur_strong_code_root_migration_time_ms);
+  print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms);
+  if (G1StringDedup::is_enabled()) {
+    print_stats(1, "String Dedup Fixup", _cur_string_dedup_fixup_time_ms, _active_gc_threads);
+    _cur_string_dedup_queue_fixup_worker_times_ms.print(2, "Queue Fixup (ms)");
+    _cur_string_dedup_table_fixup_worker_times_ms.print(2, "Table Fixup (ms)");
+  }
   print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
   double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms();
   print_stats(1, "Other", misc_time_ms);
   if (_cur_verify_before_time_ms > 0.0) {
     print_stats(2, "Verify Before", _cur_verify_before_time_ms);
   }
+  if (G1CollectedHeap::heap()->evacuation_failed()) {
+    double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards +
+      _cur_evac_fail_restore_remsets;
+    print_stats(2, "Evacuation Failure", evac_fail_handling);
+    if (G1Log::finest()) {
+      print_stats(3, "Recalculate Used", _cur_evac_fail_recalc_used);
+      print_stats(3, "Remove Self Forwards", _cur_evac_fail_remove_self_forwards);
+      print_stats(3, "Restore RemSet", _cur_evac_fail_restore_remsets);
+    }
+  }
   print_stats(2, "Choose CSet",
     (_recorded_young_cset_choice_time_ms +
     _recorded_non_young_cset_choice_time_ms));
   print_stats(2, "Ref Proc", _cur_ref_proc_time_ms);
   print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
+  if (G1DeferredRSUpdate) {
+    print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
+  }
   print_stats(2, "Free CSet",
     (_recorded_young_free_cset_time_ms +
     _recorded_non_young_free_cset_time_ms));
+  if (G1Log::finest()) {
+    print_stats(3, "Young Free CSet", _recorded_young_free_cset_time_ms);
+    print_stats(3, "Non-Young Free CSet", _recorded_non_young_free_cset_time_ms);
+  }
   if (_cur_verify_after_time_ms > 0.0) {
     print_stats(2, "Verify After", _cur_verify_after_time_ms);
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -131,6 +131,15 @@
   double _cur_collection_par_time_ms;
   double _cur_collection_code_root_fixup_time_ms;
   double _cur_strong_code_root_migration_time_ms;
+  double _cur_strong_code_root_purge_time_ms;
+
+  double _cur_evac_fail_recalc_used;
+  double _cur_evac_fail_restore_remsets;
+  double _cur_evac_fail_remove_self_forwards;
+
+  double                  _cur_string_dedup_fixup_time_ms;
+  WorkerDataArray<double> _cur_string_dedup_queue_fixup_worker_times_ms;
+  WorkerDataArray<double> _cur_string_dedup_table_fixup_worker_times_ms;
 
   double _cur_clear_ct_time_ms;
   double _cur_ref_proc_time_ms;
@@ -142,6 +151,8 @@
   double _recorded_young_cset_choice_time_ms;
   double _recorded_non_young_cset_choice_time_ms;
 
+  double _recorded_redirty_logged_cards_time_ms;
+
   double _recorded_young_free_cset_time_ms;
   double _recorded_non_young_free_cset_time_ms;
 
@@ -223,6 +234,37 @@
     _cur_strong_code_root_migration_time_ms = ms;
   }
 
+  void record_strong_code_root_purge_time(double ms) {
+    _cur_strong_code_root_purge_time_ms = ms;
+  }
+
+  void record_evac_fail_recalc_used_time(double ms) {
+    _cur_evac_fail_recalc_used = ms;
+  }
+
+  void record_evac_fail_restore_remsets(double ms) {
+    _cur_evac_fail_restore_remsets = ms;
+  }
+
+  void record_evac_fail_remove_self_forwards(double ms) {
+    _cur_evac_fail_remove_self_forwards = ms;
+  }
+
+  void note_string_dedup_fixup_start();
+  void note_string_dedup_fixup_end();
+
+  void record_string_dedup_fixup_time(double ms) {
+    _cur_string_dedup_fixup_time_ms = ms;
+  }
+
+  void record_string_dedup_queue_fixup_worker_time(uint worker_id, double ms) {
+    _cur_string_dedup_queue_fixup_worker_times_ms.set(worker_id, ms);
+  }
+
+  void record_string_dedup_table_fixup_worker_time(uint worker_id, double ms) {
+    _cur_string_dedup_table_fixup_worker_times_ms.set(worker_id, ms);
+  }
+
   void record_ref_proc_time(double ms) {
     _cur_ref_proc_time_ms = ms;
   }
@@ -251,6 +293,10 @@
     _recorded_non_young_cset_choice_time_ms = time_ms;
   }
 
+  void record_redirty_logged_cards_time_ms(double time_ms) {
+    _recorded_redirty_logged_cards_time_ms = time_ms;
+  }
+
   void record_cur_collection_start_sec(double time_ms) {
     _cur_collection_start_sec = time_ms;
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -31,6 +31,7 @@
 #include "code/icBuffer.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/shared/gcHeapSummary.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
@@ -194,17 +195,19 @@
   G1CollectedHeap* _g1h;
   ModRefBarrierSet* _mrbs;
   CompactPoint _cp;
-  HumongousRegionSet _humongous_proxy_set;
+  HeapRegionSetCount _humongous_regions_removed;
 
   void free_humongous_region(HeapRegion* hr) {
     HeapWord* end = hr->end();
-    size_t dummy_pre_used;
     FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
 
     assert(hr->startsHumongous(),
            "Only the start of a humongous region should be freed.");
-    _g1h->free_humongous_region(hr, &dummy_pre_used, &dummy_free_list,
-                                &_humongous_proxy_set, false /* par */);
+
+    hr->set_containing_set(NULL);
+    _humongous_regions_removed.increment(1u, hr->capacity());
+
+    _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */);
     hr->prepare_for_compaction(&_cp);
     // Also clear the part of the card table that will be unused after
     // compaction.
@@ -217,16 +220,13 @@
   : _g1h(G1CollectedHeap::heap()),
     _mrbs(_g1h->g1_barrier_set()),
     _cp(NULL, cs, cs->initialize_threshold()),
-    _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
+    _humongous_regions_removed() { }
 
   void update_sets() {
     // We'll recalculate total used bytes and recreate the free list
     // at the end of the GC, so no point in updating those values here.
-    _g1h->update_sets_after_freeing_regions(0, /* pre_used */
-                                            NULL, /* free_list */
-                                            NULL, /* old_proxy_set */
-                                            &_humongous_proxy_set,
-                                            false /* par */);
+    HeapRegionSetCount empty_set;
+    _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed);
   }
 
   bool doHeapRegion(HeapRegion* hr) {
@@ -317,6 +317,10 @@
   // have been cleared if they pointed to non-surviving objects.)
   sh->process_weak_roots(&GenMarkSweep::adjust_pointer_closure);
 
+  if (G1StringDedup::is_enabled()) {
+    G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
+  }
+
   GenMarkSweep::adjust_marks();
 
   G1AdjustPointersClosure blk;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -80,53 +80,6 @@
   virtual void do_oop(narrowOop* p)    { do_oop_nv(p); }
 };
 
-#define G1_PARTIAL_ARRAY_MASK 0x2
-
-inline bool has_partial_array_mask(oop* ref) {
-  return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
-}
-
-// We never encode partial array oops as narrowOop*, so return false immediately.
-// This allows the compiler to create optimized code when popping references from
-// the work queue.
-inline bool has_partial_array_mask(narrowOop* ref) {
-  assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*");
-  return false;
-}
-
-// Only implement set_partial_array_mask() for regular oops, not for narrowOops.
-// We always encode partial arrays as regular oop, to allow the
-// specialization for has_partial_array_mask() for narrowOops above.
-// This means that unintentional use of this method with narrowOops are caught
-// by the compiler.
-inline oop* set_partial_array_mask(oop obj) {
-  assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
-  return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK);
-}
-
-template <class T> inline oop clear_partial_array_mask(T* ref) {
-  return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
-}
-
-class G1ParScanPartialArrayClosure : public G1ParClosureSuper {
-  G1ParScanClosure _scanner;
-
-public:
-  G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) :
-    G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state, rp)
-  {
-    assert(_ref_processor == NULL, "sanity");
-  }
-
-  G1ParScanClosure* scanner() {
-    return &_scanner;
-  }
-
-  template <class T> void do_oop_nv(T* p);
-  virtual void do_oop(oop* p)       { do_oop_nv(p); }
-  virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
-};
-
 // Add back base class for metadata
 class G1ParCopyHelper : public G1ParClosureSuper {
 protected:
@@ -173,15 +126,8 @@
 typedef G1ParCopyClosure<G1BarrierNone, true> G1ParScanAndMarkExtRootClosure;
 typedef G1ParCopyClosure<G1BarrierKlass, true> G1ParScanAndMarkMetadataClosure;
 
-// The following closure type is defined in g1_specialized_oop_closures.hpp:
-//
-// typedef G1ParCopyClosure<G1BarrierEvac, false> G1ParScanHeapEvacClosure;
-
 // We use a separate closure to handle references during evacuation
 // failure processing.
-// We could have used another instance of G1ParScanHeapEvacClosure
-// (since that closure no longer assumes that the references it
-// handles point into the collection set).
 
 typedef G1ParCopyClosure<G1BarrierEvac, false> G1ParScanHeapEvacFailureClosure;
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -462,8 +462,9 @@
   int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num();
 
   if (_g1->evacuation_failed()) {
+    double restore_remembered_set_start = os::elapsedTime();
+
     // Restore remembered sets for the regions pointing into the collection set.
-
     if (G1DeferredRSUpdate) {
       // If deferred RS updates are enabled then we just need to transfer
       // the completed buffers from (a) the DirtyCardQueueSet used to hold
@@ -482,6 +483,8 @@
       }
       assert(n_completed_buffers == into_cset_n_buffers, "missed some buffers");
     }
+
+    _g1->g1_policy()->phase_times()->record_evac_fail_restore_remsets((os::elapsedTime() - restore_remembered_set_start) * 1000.0);
   }
 
   // Free any completed buffers in the DirtyCardQueueSet used to hold cards
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 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 "classfile/javaClasses.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
+#include "gc_implementation/g1/g1StringDedupQueue.hpp"
+#include "gc_implementation/g1/g1StringDedupStat.hpp"
+#include "gc_implementation/g1/g1StringDedupTable.hpp"
+#include "gc_implementation/g1/g1StringDedupThread.hpp"
+
+bool G1StringDedup::_enabled = false;
+
+void G1StringDedup::initialize() {
+  assert(UseG1GC, "String deduplication only available with G1");
+  if (UseStringDeduplication) {
+    _enabled = true;
+    G1StringDedupQueue::create();
+    G1StringDedupTable::create();
+    G1StringDedupThread::create();
+  }
+}
+
+bool G1StringDedup::is_candidate_from_mark(oop obj) {
+  if (java_lang_String::is_instance(obj)) {
+    bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young();
+    if (from_young && obj->age() < StringDeduplicationAgeThreshold) {
+      // Candidate found. String is being evacuated from young to old but has not
+      // reached the deduplication age threshold, i.e. has not previously been a
+      // candidate during its life in the young generation.
+      return true;
+    }
+  }
+
+  // Not a candidate
+  return false;
+}
+
+void G1StringDedup::enqueue_from_mark(oop java_string) {
+  assert(is_enabled(), "String deduplication not enabled");
+  if (is_candidate_from_mark(java_string)) {
+    G1StringDedupQueue::push(0 /* worker_id */, java_string);
+  }
+}
+
+bool G1StringDedup::is_candidate_from_evacuation(bool from_young, bool to_young, oop obj) {
+  if (from_young && java_lang_String::is_instance(obj)) {
+    if (to_young && obj->age() == StringDeduplicationAgeThreshold) {
+      // Candidate found. String is being evacuated from young to young and just
+      // reached the deduplication age threshold.
+      return true;
+    }
+    if (!to_young && obj->age() < StringDeduplicationAgeThreshold) {
+      // Candidate found. String is being evacuated from young to old but has not
+      // reached the deduplication age threshold, i.e. has not previously been a
+      // candidate during its life in the young generation.
+      return true;
+    }
+  }
+
+  // Not a candidate
+  return false;
+}
+
+void G1StringDedup::enqueue_from_evacuation(bool from_young, bool to_young, uint worker_id, oop java_string) {
+  assert(is_enabled(), "String deduplication not enabled");
+  if (is_candidate_from_evacuation(from_young, to_young, java_string)) {
+    G1StringDedupQueue::push(worker_id, java_string);
+  }
+}
+
+void G1StringDedup::deduplicate(oop java_string) {
+  assert(is_enabled(), "String deduplication not enabled");
+  G1StringDedupStat dummy; // Statistics from this path is never used
+  G1StringDedupTable::deduplicate(java_string, dummy);
+}
+
+void G1StringDedup::oops_do(OopClosure* keep_alive) {
+  assert(is_enabled(), "String deduplication not enabled");
+  unlink_or_oops_do(NULL, keep_alive);
+}
+
+void G1StringDedup::unlink(BoolObjectClosure* is_alive) {
+  assert(is_enabled(), "String deduplication not enabled");
+  // Don't allow a potential resize or rehash during unlink, as the unlink
+  // operation itself might remove enough entries to invalidate such a decision.
+  unlink_or_oops_do(is_alive, NULL, false /* allow_resize_and_rehash */);
+}
+
+//
+// Task for parallel unlink_or_oops_do() operation on the deduplication queue
+// and table.
+//
+class G1StringDedupUnlinkOrOopsDoTask : public AbstractGangTask {
+private:
+  G1StringDedupUnlinkOrOopsDoClosure _cl;
+
+public:
+  G1StringDedupUnlinkOrOopsDoTask(BoolObjectClosure* is_alive,
+                                  OopClosure* keep_alive,
+                                  bool allow_resize_and_rehash) :
+    AbstractGangTask("G1StringDedupUnlinkOrOopsDoTask"),
+    _cl(is_alive, keep_alive, allow_resize_and_rehash) {
+  }
+
+  virtual void work(uint worker_id) {
+    double queue_fixup_start = os::elapsedTime();
+    G1StringDedupQueue::unlink_or_oops_do(&_cl);
+
+    double table_fixup_start = os::elapsedTime();
+    G1StringDedupTable::unlink_or_oops_do(&_cl, worker_id);
+
+    double queue_fixup_time_ms = (table_fixup_start - queue_fixup_start) * 1000.0;
+    double table_fixup_time_ms = (os::elapsedTime() - table_fixup_start) * 1000.0;
+    G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
+    g1p->phase_times()->record_string_dedup_queue_fixup_worker_time(worker_id, queue_fixup_time_ms);
+    g1p->phase_times()->record_string_dedup_table_fixup_worker_time(worker_id, table_fixup_time_ms);
+  }
+};
+
+void G1StringDedup::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, bool allow_resize_and_rehash) {
+  assert(is_enabled(), "String deduplication not enabled");
+  G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
+  g1p->phase_times()->note_string_dedup_fixup_start();
+  double fixup_start = os::elapsedTime();
+
+  G1StringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash);
+  if (G1CollectedHeap::use_parallel_gc_threads()) {
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+    g1h->set_par_threads();
+    g1h->workers()->run_task(&task);
+    g1h->set_par_threads(0);
+  } else {
+    task.work(0);
+  }
+
+  double fixup_time_ms = (os::elapsedTime() - fixup_start) * 1000.0;
+  g1p->phase_times()->record_string_dedup_fixup_time(fixup_time_ms);
+  g1p->phase_times()->note_string_dedup_fixup_end();
+}
+
+void G1StringDedup::threads_do(ThreadClosure* tc) {
+  assert(is_enabled(), "String deduplication not enabled");
+  tc->do_thread(G1StringDedupThread::thread());
+}
+
+void G1StringDedup::print_worker_threads_on(outputStream* st) {
+  assert(is_enabled(), "String deduplication not enabled");
+  G1StringDedupThread::thread()->print_on(st);
+  st->cr();
+}
+
+void G1StringDedup::verify() {
+  assert(is_enabled(), "String deduplication not enabled");
+  G1StringDedupQueue::verify();
+  G1StringDedupTable::verify();
+}
+
+G1StringDedupUnlinkOrOopsDoClosure::G1StringDedupUnlinkOrOopsDoClosure(BoolObjectClosure* is_alive,
+                                                                       OopClosure* keep_alive,
+                                                                       bool allow_resize_and_rehash) :
+  _is_alive(is_alive),
+  _keep_alive(keep_alive),
+  _resized_table(NULL),
+  _rehashed_table(NULL),
+  _next_queue(0),
+  _next_bucket(0) {
+  if (allow_resize_and_rehash) {
+    // If both resize and rehash is needed, only do resize. Rehash of
+    // the table will eventually happen if the situation persists.
+    _resized_table = G1StringDedupTable::prepare_resize();
+    if (!is_resizing()) {
+      _rehashed_table = G1StringDedupTable::prepare_rehash();
+    }
+  }
+}
+
+G1StringDedupUnlinkOrOopsDoClosure::~G1StringDedupUnlinkOrOopsDoClosure() {
+  assert(!is_resizing() || !is_rehashing(), "Can not both resize and rehash");
+  if (is_resizing()) {
+    G1StringDedupTable::finish_resize(_resized_table);
+  } else if (is_rehashing()) {
+    G1StringDedupTable::finish_rehash(_rehashed_table);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
+
+//
+// String Deduplication
+//
+// String deduplication aims to reduce the heap live-set by deduplicating identical
+// instances of String so that they share the same backing character array.
+//
+// The deduplication process is divided in two main parts, 1) finding the objects to
+// deduplicate, and 2) deduplicating those objects. The first part is done as part of
+// a normal GC cycle when objects are marked or evacuated. At this time a check is
+// applied on each object to check if it is a candidate for deduplication. If so, the
+// object is placed on the deduplication queue for later processing. The second part,
+// processing the objects on the deduplication queue, is a concurrent phase which
+// starts right after the stop-the-wold marking/evacuation phase. This phase is
+// executed by the deduplication thread, which pulls deduplication candidates of the
+// deduplication queue and tries to deduplicate them.
+//
+// A deduplication hashtable is used to keep track of all unique character arrays
+// used by String objects. When deduplicating, a lookup is made in this table to see
+// if there is already an identical character array somewhere on the heap. If so, the
+// String object is adjusted to point to that character array, releasing the reference
+// to the original array allowing it to eventually be garbage collected. If the lookup
+// fails the character array is instead inserted into the hashtable so that this array
+// can be shared at some point in the future.
+//
+// Candidate selection
+//
+// An object is considered a deduplication candidate if all of the following
+// statements are true:
+//
+// - The object is an instance of java.lang.String
+//
+// - The object is being evacuated from a young heap region
+//
+// - The object is being evacuated to a young/survivor heap region and the
+//   object's age is equal to the deduplication age threshold
+//
+//   or
+//
+//   The object is being evacuated to an old heap region and the object's age is
+//   less than the deduplication age threshold
+//
+// Once an string object has been promoted to an old region, or its age is higher
+// than the deduplication age threshold, is will never become a candidate again.
+// This approach avoids making the same object a candidate more than once.
+//
+// Interned strings are a bit special. They are explicitly deduplicated just before
+// being inserted into the StringTable (to avoid counteracting C2 optimizations done
+// on string literals), then they also become deduplication candidates if they reach
+// the deduplication age threshold or are evacuated to an old heap region. The second
+// attempt to deduplicate such strings will be in vain, but we have no fast way of
+// filtering them out. This has not shown to be a problem, as the number of interned
+// strings is usually dwarfed by the number of normal (non-interned) strings.
+//
+// For additional information on string deduplication, please see JEP 192,
+// http://openjdk.java.net/jeps/192
+//
+
+#include "memory/allocation.hpp"
+#include "oops/oop.hpp"
+
+class OopClosure;
+class BoolObjectClosure;
+class ThreadClosure;
+class outputStream;
+class G1StringDedupTable;
+
+//
+// Main interface for interacting with string deduplication.
+//
+class G1StringDedup : public AllStatic {
+private:
+  // Single state for checking if both G1 and string deduplication is enabled.
+  static bool _enabled;
+
+  // Candidate selection policies, returns true if the given object is
+  // candidate for string deduplication.
+  static bool is_candidate_from_mark(oop obj);
+  static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop obj);
+
+public:
+  // Returns true if both G1 and string deduplication is enabled.
+  static bool is_enabled() {
+    return _enabled;
+  }
+
+  static void initialize();
+
+  // Immediately deduplicates the given String object, bypassing the
+  // the deduplication queue.
+  static void deduplicate(oop java_string);
+
+  // Enqueues a deduplication candidate for later processing by the deduplication
+  // thread. Before enqueuing, these functions apply the appropriate candidate
+  // selection policy to filters out non-candidates.
+  static void enqueue_from_mark(oop java_string);
+  static void enqueue_from_evacuation(bool from_young, bool to_young,
+                                      unsigned int queue, oop java_string);
+
+  static void oops_do(OopClosure* keep_alive);
+  static void unlink(BoolObjectClosure* is_alive);
+  static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive,
+                                bool allow_resize_and_rehash = true);
+
+  static void threads_do(ThreadClosure* tc);
+  static void print_worker_threads_on(outputStream* st);
+  static void verify();
+};
+
+//
+// This closure encapsulates the state and the closures needed when scanning
+// the deduplication queue and table during the unlink_or_oops_do() operation.
+// A single instance of this closure is created and then shared by all worker
+// threads participating in the scan. The _next_queue and _next_bucket fields
+// provide a simple mechanism for GC workers to claim exclusive access to a
+// queue or a table partition.
+//
+class G1StringDedupUnlinkOrOopsDoClosure : public StackObj {
+private:
+  BoolObjectClosure*  _is_alive;
+  OopClosure*         _keep_alive;
+  G1StringDedupTable* _resized_table;
+  G1StringDedupTable* _rehashed_table;
+  size_t              _next_queue;
+  size_t              _next_bucket;
+
+public:
+  G1StringDedupUnlinkOrOopsDoClosure(BoolObjectClosure* is_alive,
+                                     OopClosure* keep_alive,
+                                     bool allow_resize_and_rehash);
+  ~G1StringDedupUnlinkOrOopsDoClosure();
+
+  bool is_resizing() {
+    return _resized_table != NULL;
+  }
+
+  G1StringDedupTable* resized_table() {
+    return _resized_table;
+  }
+
+  bool is_rehashing() {
+    return _rehashed_table != NULL;
+  }
+
+  // Atomically claims the next available queue for exclusive access by
+  // the current thread. Returns the queue number of the claimed queue.
+  size_t claim_queue() {
+    return (size_t)Atomic::add_ptr(1, &_next_queue) - 1;
+  }
+
+  // Atomically claims the next available table partition for exclusive
+  // access by the current thread. Returns the table bucket number where
+  // the claimed partition starts.
+  size_t claim_table_partition(size_t partition_size) {
+    return (size_t)Atomic::add_ptr(partition_size, &_next_bucket) - partition_size;
+  }
+
+  // Applies and returns the result from the is_alive closure, or
+  // returns true if no such closure was provided.
+  bool is_alive(oop o) {
+    if (_is_alive != NULL) {
+      return _is_alive->do_object_b(o);
+    }
+    return true;
+  }
+
+  // Applies the keep_alive closure, or does nothing if no such
+  // closure was provided.
+  void keep_alive(oop* p) {
+    if (_keep_alive != NULL) {
+      _keep_alive->do_oop(p);
+    }
+  }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 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 "classfile/javaClasses.hpp"
+#include "gc_implementation/g1/g1StringDedupQueue.hpp"
+#include "memory/gcLocker.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "utilities/stack.inline.hpp"
+
+G1StringDedupQueue* G1StringDedupQueue::_queue = NULL;
+const size_t        G1StringDedupQueue::_max_size = 1000000; // Max number of elements per queue
+const size_t        G1StringDedupQueue::_max_cache_size = 0; // Max cache size per queue
+
+G1StringDedupQueue::G1StringDedupQueue() :
+  _cursor(0),
+  _empty(true),
+  _dropped(0) {
+  _nqueues = MAX2(ParallelGCThreads, (size_t)1);
+  _queues = NEW_C_HEAP_ARRAY(G1StringDedupWorkerQueue, _nqueues, mtGC);
+  for (size_t i = 0; i < _nqueues; i++) {
+    new (_queues + i) G1StringDedupWorkerQueue(G1StringDedupWorkerQueue::default_segment_size(), _max_cache_size, _max_size);
+  }
+}
+
+G1StringDedupQueue::~G1StringDedupQueue() {
+  ShouldNotReachHere();
+}
+
+void G1StringDedupQueue::create() {
+  assert(_queue == NULL, "One string deduplication queue allowed");
+  _queue = new G1StringDedupQueue();
+}
+
+void G1StringDedupQueue::wait() {
+  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  while (_queue->_empty) {
+    ml.wait(Mutex::_no_safepoint_check_flag);
+  }
+}
+
+void G1StringDedupQueue::push(uint worker_id, oop java_string) {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
+  assert(worker_id < _queue->_nqueues, "Invalid queue");
+
+  // Push and notify waiter
+  G1StringDedupWorkerQueue& worker_queue = _queue->_queues[worker_id];
+  if (!worker_queue.is_full()) {
+    worker_queue.push(java_string);
+    if (_queue->_empty) {
+      MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+      if (_queue->_empty) {
+        // Mark non-empty and notify waiter
+        _queue->_empty = false;
+        ml.notify();
+      }
+    }
+  } else {
+    // Queue is full, drop the string and update the statistics
+    Atomic::inc_ptr(&_queue->_dropped);
+  }
+}
+
+oop G1StringDedupQueue::pop() {
+  assert(!SafepointSynchronize::is_at_safepoint(), "Must not be at safepoint");
+  No_Safepoint_Verifier nsv;
+
+  // Try all queues before giving up
+  for (size_t tries = 0; tries < _queue->_nqueues; tries++) {
+    // The cursor indicates where we left of last time
+    G1StringDedupWorkerQueue* queue = &_queue->_queues[_queue->_cursor];
+    while (!queue->is_empty()) {
+      oop obj = queue->pop();
+      // The oop we pop can be NULL if it was marked
+      // dead. Just ignore those and pop the next oop.
+      if (obj != NULL) {
+        return obj;
+      }
+    }
+
+    // Try next queue
+    _queue->_cursor = (_queue->_cursor + 1) % _queue->_nqueues;
+  }
+
+  // Mark empty
+  _queue->_empty = true;
+
+  return NULL;
+}
+
+void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl) {
+  // A worker thread first claims a queue, which ensures exclusive
+  // access to that queue, then continues to process it.
+  for (;;) {
+    // Grab next queue to scan
+    size_t queue = cl->claim_queue();
+    if (queue >= _queue->_nqueues) {
+      // End of queues
+      break;
+    }
+
+    // Scan the queue
+    unlink_or_oops_do(cl, queue);
+  }
+}
+
+void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, size_t queue) {
+  assert(queue < _queue->_nqueues, "Invalid queue");
+  StackIterator<oop, mtGC> iter(_queue->_queues[queue]);
+  while (!iter.is_empty()) {
+    oop* p = iter.next_addr();
+    if (*p != NULL) {
+      if (cl->is_alive(*p)) {
+        cl->keep_alive(p);
+      } else {
+        // Clear dead reference
+        *p = NULL;
+      }
+    }
+  }
+}
+
+void G1StringDedupQueue::print_statistics(outputStream* st) {
+  st->print_cr(
+    "   [Queue]\n"
+    "      [Dropped: "UINTX_FORMAT"]", _queue->_dropped);
+}
+
+void G1StringDedupQueue::verify() {
+  for (size_t i = 0; i < _queue->_nqueues; i++) {
+    StackIterator<oop, mtGC> iter(_queue->_queues[i]);
+    while (!iter.is_empty()) {
+      oop obj = iter.next();
+      if (obj != NULL) {
+        guarantee(Universe::heap()->is_in_reserved(obj), "Object must be on the heap");
+        guarantee(!obj->is_forwarded(), "Object must not be forwarded");
+        guarantee(java_lang_String::is_instance(obj), "Object must be a String");
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
+
+#include "memory/allocation.hpp"
+#include "oops/oop.hpp"
+#include "utilities/stack.hpp"
+
+class G1StringDedupUnlinkOrOopsDoClosure;
+
+//
+// The deduplication queue acts as the communication channel between the stop-the-world
+// mark/evacuation phase and the concurrent deduplication phase. Deduplication candidates
+// found during mark/evacuation are placed on this queue for later processing in the
+// deduplication thread. A queue entry is an oop pointing to a String object (as opposed
+// to entries in the deduplication hashtable which points to character arrays).
+//
+// While users of the queue treat it as a single queue, it is implemented as a set of
+// queues, one queue per GC worker thread, to allow lock-free and cache-friendly enqueue
+// operations by the GC workers.
+//
+// The oops in the queue are treated as weak pointers, meaning the objects they point to
+// can become unreachable and pruned (cleared) before being popped by the deduplication
+// thread.
+//
+// Pushing to the queue is thread safe (this relies on each thread using a unique worker
+// id), but only allowed during a safepoint. Popping from the queue is NOT thread safe
+// and can only be done by the deduplication thread outside a safepoint.
+//
+// The StringDedupQueue_lock is only used for blocking and waking up the deduplication
+// thread in case the queue is empty or becomes non-empty, respectively. This lock does
+// not otherwise protect the queue content.
+//
+class G1StringDedupQueue : public CHeapObj<mtGC> {
+private:
+  typedef Stack<oop, mtGC> G1StringDedupWorkerQueue;
+
+  static G1StringDedupQueue* _queue;
+  static const size_t        _max_size;
+  static const size_t        _max_cache_size;
+
+  G1StringDedupWorkerQueue*  _queues;
+  size_t                     _nqueues;
+  size_t                     _cursor;
+  volatile bool              _empty;
+
+  // Statistics counter, only used for logging.
+  uintx                      _dropped;
+
+  G1StringDedupQueue();
+  ~G1StringDedupQueue();
+
+  static void unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, size_t queue);
+
+public:
+  static void create();
+
+  // Blocks and waits for the queue to become non-empty.
+  static void wait();
+
+  // Pushes a deduplication candidate onto a specific GC worker queue.
+  static void push(uint worker_id, oop java_string);
+
+  // Pops a deduplication candidate from any queue, returns NULL if
+  // all queues are empty.
+  static oop pop();
+
+  static void unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl);
+
+  static void print_statistics(outputStream* st);
+  static void verify();
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupStat.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 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 "gc_implementation/g1/g1StringDedupStat.hpp"
+
+G1StringDedupStat::G1StringDedupStat() :
+  _inspected(0),
+  _skipped(0),
+  _hashed(0),
+  _known(0),
+  _new(0),
+  _new_bytes(0),
+  _deduped(0),
+  _deduped_bytes(0),
+  _deduped_young(0),
+  _deduped_young_bytes(0),
+  _deduped_old(0),
+  _deduped_old_bytes(0),
+  _idle(0),
+  _exec(0),
+  _block(0),
+  _start(0.0),
+  _idle_elapsed(0.0),
+  _exec_elapsed(0.0),
+  _block_elapsed(0.0) {
+}
+
+void G1StringDedupStat::add(const G1StringDedupStat& stat) {
+  _inspected           += stat._inspected;
+  _skipped             += stat._skipped;
+  _hashed              += stat._hashed;
+  _known               += stat._known;
+  _new                 += stat._new;
+  _new_bytes           += stat._new_bytes;
+  _deduped             += stat._deduped;
+  _deduped_bytes       += stat._deduped_bytes;
+  _deduped_young       += stat._deduped_young;
+  _deduped_young_bytes += stat._deduped_young_bytes;
+  _deduped_old         += stat._deduped_old;
+  _deduped_old_bytes   += stat._deduped_old_bytes;
+  _idle                += stat._idle;
+  _exec                += stat._exec;
+  _block               += stat._block;
+  _idle_elapsed        += stat._idle_elapsed;
+  _exec_elapsed        += stat._exec_elapsed;
+  _block_elapsed       += stat._block_elapsed;
+}
+
+void G1StringDedupStat::print_summary(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
+  double total_deduped_bytes_percent = 0.0;
+
+  if (total_stat._new_bytes > 0) {
+    // Avoid division by zero
+    total_deduped_bytes_percent = (double)total_stat._deduped_bytes / (double)total_stat._new_bytes * 100.0;
+  }
+
+  st->date_stamp(PrintGCDateStamps);
+  st->stamp(PrintGCTimeStamps);
+  st->print_cr(
+    "[GC concurrent-string-deduplication, "
+    G1_STRDEDUP_BYTES_FORMAT_NS"->"G1_STRDEDUP_BYTES_FORMAT_NS"("G1_STRDEDUP_BYTES_FORMAT_NS"), avg "
+    G1_STRDEDUP_PERCENT_FORMAT_NS", "G1_STRDEDUP_TIME_FORMAT"]",
+    G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes),
+    G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes - last_stat._deduped_bytes),
+    G1_STRDEDUP_BYTES_PARAM(last_stat._deduped_bytes),
+    total_deduped_bytes_percent,
+    last_stat._exec_elapsed);
+}
+
+void G1StringDedupStat::print_statistics(outputStream* st, const G1StringDedupStat& stat, bool total) {
+  double young_percent               = 0.0;
+  double old_percent                 = 0.0;
+  double skipped_percent             = 0.0;
+  double hashed_percent              = 0.0;
+  double known_percent               = 0.0;
+  double new_percent                 = 0.0;
+  double deduped_percent             = 0.0;
+  double deduped_bytes_percent       = 0.0;
+  double deduped_young_percent       = 0.0;
+  double deduped_young_bytes_percent = 0.0;
+  double deduped_old_percent         = 0.0;
+  double deduped_old_bytes_percent   = 0.0;
+
+  if (stat._inspected > 0) {
+    // Avoid division by zero
+    skipped_percent = (double)stat._skipped / (double)stat._inspected * 100.0;
+    hashed_percent  = (double)stat._hashed / (double)stat._inspected * 100.0;
+    known_percent   = (double)stat._known / (double)stat._inspected * 100.0;
+    new_percent     = (double)stat._new / (double)stat._inspected * 100.0;
+  }
+
+  if (stat._new > 0) {
+    // Avoid division by zero
+    deduped_percent = (double)stat._deduped / (double)stat._new * 100.0;
+  }
+
+  if (stat._deduped > 0) {
+    // Avoid division by zero
+    deduped_young_percent = (double)stat._deduped_young / (double)stat._deduped * 100.0;
+    deduped_old_percent   = (double)stat._deduped_old / (double)stat._deduped * 100.0;
+  }
+
+  if (stat._new_bytes > 0) {
+    // Avoid division by zero
+    deduped_bytes_percent = (double)stat._deduped_bytes / (double)stat._new_bytes * 100.0;
+  }
+
+  if (stat._deduped_bytes > 0) {
+    // Avoid division by zero
+    deduped_young_bytes_percent = (double)stat._deduped_young_bytes / (double)stat._deduped_bytes * 100.0;
+    deduped_old_bytes_percent   = (double)stat._deduped_old_bytes / (double)stat._deduped_bytes * 100.0;
+  }
+
+  if (total) {
+    st->print_cr(
+      "   [Total Exec: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Idle: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]",
+      stat._exec, stat._exec_elapsed, stat._idle, stat._idle_elapsed, stat._block, stat._block_elapsed);
+  } else {
+    st->print_cr(
+      "   [Last Exec: "G1_STRDEDUP_TIME_FORMAT", Idle: "G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]",
+      stat._exec_elapsed, stat._idle_elapsed, stat._block, stat._block_elapsed);
+  }
+  st->print_cr(
+    "      [Inspected:    "G1_STRDEDUP_OBJECTS_FORMAT"]\n"
+    "         [Skipped:   "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
+    "         [Hashed:    "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
+    "         [Known:     "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
+    "         [New:       "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"]\n"
+    "      [Deduplicated: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
+    "         [Young:     "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
+    "         [Old:       "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]",
+    stat._inspected,
+    stat._skipped, skipped_percent,
+    stat._hashed, hashed_percent,
+    stat._known, known_percent,
+    stat._new, new_percent, G1_STRDEDUP_BYTES_PARAM(stat._new_bytes),
+    stat._deduped, deduped_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_bytes), deduped_bytes_percent,
+    stat._deduped_young, deduped_young_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_young_bytes), deduped_young_bytes_percent,
+    stat._deduped_old, deduped_old_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_old_bytes), deduped_old_bytes_percent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupStat.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/os.hpp"
+
+// Macros for GC log output formating
+#define G1_STRDEDUP_OBJECTS_FORMAT         UINTX_FORMAT_W(12)
+#define G1_STRDEDUP_TIME_FORMAT            "%1.7lf secs"
+#define G1_STRDEDUP_PERCENT_FORMAT         "%5.1lf%%"
+#define G1_STRDEDUP_PERCENT_FORMAT_NS      "%.1lf%%"
+#define G1_STRDEDUP_BYTES_FORMAT           "%8.1lf%s"
+#define G1_STRDEDUP_BYTES_FORMAT_NS        "%.1lf%s"
+#define G1_STRDEDUP_BYTES_PARAM(bytes)     byte_size_in_proper_unit((double)(bytes)), proper_unit_for_byte_size((bytes))
+
+//
+// Statistics gathered by the deduplication thread.
+//
+class G1StringDedupStat : public StackObj {
+private:
+  // Counters
+  uintx  _inspected;
+  uintx  _skipped;
+  uintx  _hashed;
+  uintx  _known;
+  uintx  _new;
+  uintx  _new_bytes;
+  uintx  _deduped;
+  uintx  _deduped_bytes;
+  uintx  _deduped_young;
+  uintx  _deduped_young_bytes;
+  uintx  _deduped_old;
+  uintx  _deduped_old_bytes;
+  uintx  _idle;
+  uintx  _exec;
+  uintx  _block;
+
+  // Time spent by the deduplication thread in different phases
+  double _start;
+  double _idle_elapsed;
+  double _exec_elapsed;
+  double _block_elapsed;
+
+public:
+  G1StringDedupStat();
+
+  void inc_inspected() {
+    _inspected++;
+  }
+
+  void inc_skipped() {
+    _skipped++;
+  }
+
+  void inc_hashed() {
+    _hashed++;
+  }
+
+  void inc_known() {
+    _known++;
+  }
+
+  void inc_new(uintx bytes) {
+    _new++;
+    _new_bytes += bytes;
+  }
+
+  void inc_deduped_young(uintx bytes) {
+    _deduped++;
+    _deduped_bytes += bytes;
+    _deduped_young++;
+    _deduped_young_bytes += bytes;
+  }
+
+  void inc_deduped_old(uintx bytes) {
+    _deduped++;
+    _deduped_bytes += bytes;
+    _deduped_old++;
+    _deduped_old_bytes += bytes;
+  }
+
+  void mark_idle() {
+    _start = os::elapsedTime();
+    _idle++;
+  }
+
+  void mark_exec() {
+    double now = os::elapsedTime();
+    _idle_elapsed = now - _start;
+    _start = now;
+    _exec++;
+  }
+
+  void mark_block() {
+    double now = os::elapsedTime();
+    _exec_elapsed += now - _start;
+    _start = now;
+    _block++;
+  }
+
+  void mark_unblock() {
+    double now = os::elapsedTime();
+    _block_elapsed += now - _start;
+    _start = now;
+  }
+
+  void mark_done() {
+    double now = os::elapsedTime();
+    _exec_elapsed += now - _start;
+  }
+
+  void add(const G1StringDedupStat& stat);
+
+  static void print_summary(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
+  static void print_statistics(outputStream* st, const G1StringDedupStat& stat, bool total);
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 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 "classfile/altHashing.hpp"
+#include "classfile/javaClasses.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#include "gc_implementation/g1/g1StringDedupTable.hpp"
+#include "memory/gcLocker.hpp"
+#include "memory/padded.inline.hpp"
+#include "oops/typeArrayOop.hpp"
+#include "runtime/mutexLocker.hpp"
+
+//
+// Freelist in the deduplication table entry cache. Links table
+// entries together using their _next fields.
+//
+class G1StringDedupEntryFreeList : public CHeapObj<mtGC> {
+private:
+  G1StringDedupEntry* _list;
+  size_t              _length;
+
+public:
+  G1StringDedupEntryFreeList() :
+    _list(NULL),
+    _length(0) {
+  }
+
+  void add(G1StringDedupEntry* entry) {
+    entry->set_next(_list);
+    _list = entry;
+    _length++;
+  }
+
+  G1StringDedupEntry* remove() {
+    G1StringDedupEntry* entry = _list;
+    if (entry != NULL) {
+      _list = entry->next();
+      _length--;
+    }
+    return entry;
+  }
+
+  size_t length() {
+    return _length;
+  }
+};
+
+//
+// Cache of deduplication table entries. This cache provides fast allocation and
+// reuse of table entries to lower the pressure on the underlying allocator.
+// But more importantly, it provides fast/deferred freeing of table entries. This
+// is important because freeing of table entries is done during stop-the-world
+// phases and it is not uncommon for large number of entries to be freed at once.
+// Tables entries that are freed during these phases are placed onto a freelist in
+// the cache. The deduplication thread, which executes in a concurrent phase, will
+// later reuse or free the underlying memory for these entries.
+//
+// The cache allows for single-threaded allocations and multi-threaded frees.
+// Allocations are synchronized by StringDedupTable_lock as part of a table
+// modification.
+//
+class G1StringDedupEntryCache : public CHeapObj<mtGC> {
+private:
+  // One freelist per GC worker to allow lock less freeing of
+  // entries while doing a parallel scan of the table. Using
+  // PaddedEnd to avoid false sharing.
+  PaddedEnd<G1StringDedupEntryFreeList>* _lists;
+  size_t                                 _nlists;
+
+public:
+  G1StringDedupEntryCache();
+  ~G1StringDedupEntryCache();
+
+  // Get a table entry from the cache freelist, or allocate a new
+  // entry if the cache is empty.
+  G1StringDedupEntry* alloc();
+
+  // Insert a table entry into the cache freelist.
+  void free(G1StringDedupEntry* entry, uint worker_id);
+
+  // Returns current number of entries in the cache.
+  size_t size();
+
+  // If the cache has grown above the given max size, trim it down
+  // and deallocate the memory occupied by trimmed of entries.
+  void trim(size_t max_size);
+};
+
+G1StringDedupEntryCache::G1StringDedupEntryCache() {
+  _nlists = MAX2(ParallelGCThreads, (size_t)1);
+  _lists = PaddedArray<G1StringDedupEntryFreeList, mtGC>::create_unfreeable((uint)_nlists);
+}
+
+G1StringDedupEntryCache::~G1StringDedupEntryCache() {
+  ShouldNotReachHere();
+}
+
+G1StringDedupEntry* G1StringDedupEntryCache::alloc() {
+  for (size_t i = 0; i < _nlists; i++) {
+    G1StringDedupEntry* entry = _lists[i].remove();
+    if (entry != NULL) {
+      return entry;
+    }
+  }
+  return new G1StringDedupEntry();
+}
+
+void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) {
+  assert(entry->obj() != NULL, "Double free");
+  assert(worker_id < _nlists, "Invalid worker id");
+  entry->set_obj(NULL);
+  entry->set_hash(0);
+  _lists[worker_id].add(entry);
+}
+
+size_t G1StringDedupEntryCache::size() {
+  size_t size = 0;
+  for (size_t i = 0; i < _nlists; i++) {
+    size += _lists[i].length();
+  }
+  return size;
+}
+
+void G1StringDedupEntryCache::trim(size_t max_size) {
+  size_t cache_size = 0;
+  for (size_t i = 0; i < _nlists; i++) {
+    G1StringDedupEntryFreeList* list = &_lists[i];
+    cache_size += list->length();
+    while (cache_size > max_size) {
+      G1StringDedupEntry* entry = list->remove();
+      assert(entry != NULL, "Should not be null");
+      cache_size--;
+      delete entry;
+    }
+  }
+}
+
+G1StringDedupTable*      G1StringDedupTable::_table = NULL;
+G1StringDedupEntryCache* G1StringDedupTable::_entry_cache = NULL;
+
+const size_t             G1StringDedupTable::_min_size = (1 << 10);   // 1024
+const size_t             G1StringDedupTable::_max_size = (1 << 24);   // 16777216
+const double             G1StringDedupTable::_grow_load_factor = 2.0; // Grow table at 200% load
+const double             G1StringDedupTable::_shrink_load_factor = _grow_load_factor / 3.0; // Shrink table at 67% load
+const double             G1StringDedupTable::_max_cache_factor = 0.1; // Cache a maximum of 10% of the table size
+const uintx              G1StringDedupTable::_rehash_multiple = 60;   // Hash bucket has 60 times more collisions than expected
+const uintx              G1StringDedupTable::_rehash_threshold = (uintx)(_rehash_multiple * _grow_load_factor);
+
+uintx                    G1StringDedupTable::_entries_added = 0;
+uintx                    G1StringDedupTable::_entries_removed = 0;
+uintx                    G1StringDedupTable::_resize_count = 0;
+uintx                    G1StringDedupTable::_rehash_count = 0;
+
+G1StringDedupTable::G1StringDedupTable(size_t size, jint hash_seed) :
+  _size(size),
+  _entries(0),
+  _grow_threshold((uintx)(size * _grow_load_factor)),
+  _shrink_threshold((uintx)(size * _shrink_load_factor)),
+  _rehash_needed(false),
+  _hash_seed(hash_seed) {
+  assert(is_power_of_2(size), "Table size must be a power of 2");
+  _buckets = NEW_C_HEAP_ARRAY(G1StringDedupEntry*, _size, mtGC);
+  memset(_buckets, 0, _size * sizeof(G1StringDedupEntry*));
+}
+
+G1StringDedupTable::~G1StringDedupTable() {
+  FREE_C_HEAP_ARRAY(G1StringDedupEntry*, _buckets, mtGC);
+}
+
+void G1StringDedupTable::create() {
+  assert(_table == NULL, "One string deduplication table allowed");
+  _entry_cache = new G1StringDedupEntryCache();
+  _table = new G1StringDedupTable(_min_size);
+}
+
+void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) {
+  G1StringDedupEntry* entry = _entry_cache->alloc();
+  entry->set_obj(value);
+  entry->set_hash(hash);
+  entry->set_next(*list);
+  *list = entry;
+  _entries++;
+}
+
+void G1StringDedupTable::remove(G1StringDedupEntry** pentry, uint worker_id) {
+  G1StringDedupEntry* entry = *pentry;
+  *pentry = entry->next();
+  _entry_cache->free(entry, worker_id);
+}
+
+void G1StringDedupTable::transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest) {
+  G1StringDedupEntry* entry = *pentry;
+  *pentry = entry->next();
+  unsigned int hash = entry->hash();
+  size_t index = dest->hash_to_index(hash);
+  G1StringDedupEntry** list = dest->bucket(index);
+  entry->set_next(*list);
+  *list = entry;
+}
+
+bool G1StringDedupTable::equals(typeArrayOop value1, typeArrayOop value2) {
+  return (value1 == value2 ||
+          (value1->length() == value2->length() &&
+           (!memcmp(value1->base(T_CHAR),
+                    value2->base(T_CHAR),
+                    value1->length() * sizeof(jchar)))));
+}
+
+typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash,
+                                        G1StringDedupEntry** list, uintx &count) {
+  for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) {
+    if (entry->hash() == hash) {
+      typeArrayOop existing_value = entry->obj();
+      if (equals(value, existing_value)) {
+        // Match found
+        return existing_value;
+      }
+    }
+    count++;
+  }
+
+  // Not found
+  return NULL;
+}
+
+typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigned int hash) {
+  size_t index = hash_to_index(hash);
+  G1StringDedupEntry** list = bucket(index);
+  uintx count = 0;
+
+  // Lookup in list
+  typeArrayOop existing_value = lookup(value, hash, list, count);
+
+  // Check if rehash is needed
+  if (count > _rehash_threshold) {
+    _rehash_needed = true;
+  }
+
+  if (existing_value == NULL) {
+    // Not found, add new entry
+    add(value, hash, list);
+
+    // Update statistics
+    _entries_added++;
+  }
+
+  return existing_value;
+}
+
+unsigned int G1StringDedupTable::hash_code(typeArrayOop value) {
+  unsigned int hash;
+  int length = value->length();
+  const jchar* data = (jchar*)value->base(T_CHAR);
+
+  if (use_java_hash()) {
+    hash = java_lang_String::hash_code(data, length);
+  } else {
+    hash = AltHashing::murmur3_32(_table->_hash_seed, data, length);
+  }
+
+  return hash;
+}
+
+void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) {
+  assert(java_lang_String::is_instance(java_string), "Must be a string");
+  No_Safepoint_Verifier nsv;
+
+  stat.inc_inspected();
+
+  typeArrayOop value = java_lang_String::value(java_string);
+  if (value == NULL) {
+    // String has no value
+    stat.inc_skipped();
+    return;
+  }
+
+  unsigned int hash = 0;
+
+  if (use_java_hash()) {
+    // Get hash code from cache
+    hash = java_lang_String::hash(java_string);
+  }
+
+  if (hash == 0) {
+    // Compute hash
+    hash = hash_code(value);
+    stat.inc_hashed();
+  }
+
+  if (use_java_hash() && hash != 0) {
+    // Store hash code in cache
+    java_lang_String::set_hash(java_string, hash);
+  }
+
+  typeArrayOop existing_value = lookup_or_add(value, hash);
+  if (existing_value == value) {
+    // Same value, already known
+    stat.inc_known();
+    return;
+  }
+
+  // Get size of value array
+  uintx size_in_bytes = value->size() * HeapWordSize;
+  stat.inc_new(size_in_bytes);
+
+  if (existing_value != NULL) {
+    // Enqueue the reference to make sure it is kept alive. Concurrent mark might
+    // otherwise declare it dead if there are no other strong references to this object.
+    G1SATBCardTableModRefBS::enqueue(existing_value);
+
+    // Existing value found, deduplicate string
+    java_lang_String::set_value(java_string, existing_value);
+
+    if (G1CollectedHeap::heap()->is_in_young(value)) {
+      stat.inc_deduped_young(size_in_bytes);
+    } else {
+      stat.inc_deduped_old(size_in_bytes);
+    }
+  }
+}
+
+G1StringDedupTable* G1StringDedupTable::prepare_resize() {
+  size_t size = _table->_size;
+
+  // Check if the hashtable needs to be resized
+  if (_table->_entries > _table->_grow_threshold) {
+    // Grow table, double the size
+    size *= 2;
+    if (size > _max_size) {
+      // Too big, don't resize
+      return NULL;
+    }
+  } else if (_table->_entries < _table->_shrink_threshold) {
+    // Shrink table, half the size
+    size /= 2;
+    if (size < _min_size) {
+      // Too small, don't resize
+      return NULL;
+    }
+  } else if (StringDeduplicationResizeALot) {
+    // Force grow
+    size *= 2;
+    if (size > _max_size) {
+      // Too big, force shrink instead
+      size /= 4;
+    }
+  } else {
+    // Resize not needed
+    return NULL;
+  }
+
+  // Update statistics
+  _resize_count++;
+
+  // Allocate the new table. The new table will be populated by workers
+  // calling unlink_or_oops_do() and finally installed by finish_resize().
+  return new G1StringDedupTable(size, _table->_hash_seed);
+}
+
+void G1StringDedupTable::finish_resize(G1StringDedupTable* resized_table) {
+  assert(resized_table != NULL, "Invalid table");
+
+  resized_table->_entries = _table->_entries;
+
+  // Free old table
+  delete _table;
+
+  // Install new table
+  _table = resized_table;
+}
+
+void G1StringDedupTable::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, uint worker_id) {
+  // The table is divided into partitions to allow lock-less parallel processing by
+  // multiple worker threads. A worker thread first claims a partition, which ensures
+  // exclusive access to that part of the table, then continues to process it. To allow
+  // shrinking of the table in parallel we also need to make sure that the same worker
+  // thread processes all partitions where entries will hash to the same destination
+  // partition. Since the table size is always a power of two and we always shrink by
+  // dividing the table in half, we know that for a given partition there is only one
+  // other partition whoes entries will hash to the same destination partition. That
+  // other partition is always the sibling partition in the second half of the table.
+  // For example, if the table is divided into 8 partitions, the sibling of partition 0
+  // is partition 4, the sibling of partition 1 is partition 5, etc.
+  size_t table_half = _table->_size / 2;
+
+  // Let each partition be one page worth of buckets
+  size_t partition_size = MIN2(table_half, os::vm_page_size() / sizeof(G1StringDedupEntry*));
+  assert(table_half % partition_size == 0, "Invalid partition size");
+
+  // Number of entries removed during the scan
+  uintx removed = 0;
+
+  for (;;) {
+    // Grab next partition to scan
+    size_t partition_begin = cl->claim_table_partition(partition_size);
+    size_t partition_end = partition_begin + partition_size;
+    if (partition_begin >= table_half) {
+      // End of table
+      break;
+    }
+
+    // Scan the partition followed by the sibling partition in the second half of the table
+    removed += unlink_or_oops_do(cl, partition_begin, partition_end, worker_id);
+    removed += unlink_or_oops_do(cl, table_half + partition_begin, table_half + partition_end, worker_id);
+  }
+
+  // Delayed update avoid contention on the table lock
+  if (removed > 0) {
+    MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
+    _table->_entries -= removed;
+    _entries_removed += removed;
+  }
+}
+
+uintx G1StringDedupTable::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl,
+                                            size_t partition_begin,
+                                            size_t partition_end,
+                                            uint worker_id) {
+  uintx removed = 0;
+  for (size_t bucket = partition_begin; bucket < partition_end; bucket++) {
+    G1StringDedupEntry** entry = _table->bucket(bucket);
+    while (*entry != NULL) {
+      oop* p = (oop*)(*entry)->obj_addr();
+      if (cl->is_alive(*p)) {
+        cl->keep_alive(p);
+        if (cl->is_resizing()) {
+          // We are resizing the table, transfer entry to the new table
+          _table->transfer(entry, cl->resized_table());
+        } else {
+          if (cl->is_rehashing()) {
+            // We are rehashing the table, rehash the entry but keep it
+            // in the table. We can't transfer entries into the new table
+            // at this point since we don't have exclusive access to all
+            // destination partitions. finish_rehash() will do a single
+            // threaded transfer of all entries.
+            typeArrayOop value = (typeArrayOop)*p;
+            unsigned int hash = hash_code(value);
+            (*entry)->set_hash(hash);
+          }
+
+          // Move to next entry
+          entry = (*entry)->next_addr();
+        }
+      } else {
+        // Not alive, remove entry from table
+        _table->remove(entry, worker_id);
+        removed++;
+      }
+    }
+  }
+
+  return removed;
+}
+
+G1StringDedupTable* G1StringDedupTable::prepare_rehash() {
+  if (!_table->_rehash_needed && !StringDeduplicationRehashALot) {
+    // Rehash not needed
+    return NULL;
+  }
+
+  // Update statistics
+  _rehash_count++;
+
+  // Compute new hash seed
+  _table->_hash_seed = AltHashing::compute_seed();
+
+  // Allocate the new table, same size and hash seed
+  return new G1StringDedupTable(_table->_size, _table->_hash_seed);
+}
+
+void G1StringDedupTable::finish_rehash(G1StringDedupTable* rehashed_table) {
+  assert(rehashed_table != NULL, "Invalid table");
+
+  // Move all newly rehashed entries into the correct buckets in the new table
+  for (size_t bucket = 0; bucket < _table->_size; bucket++) {
+    G1StringDedupEntry** entry = _table->bucket(bucket);
+    while (*entry != NULL) {
+      _table->transfer(entry, rehashed_table);
+    }
+  }
+
+  rehashed_table->_entries = _table->_entries;
+
+  // Free old table
+  delete _table;
+
+  // Install new table
+  _table = rehashed_table;
+}
+
+void G1StringDedupTable::verify() {
+  for (size_t bucket = 0; bucket < _table->_size; bucket++) {
+    // Verify entries
+    G1StringDedupEntry** entry = _table->bucket(bucket);
+    while (*entry != NULL) {
+      typeArrayOop value = (*entry)->obj();
+      guarantee(value != NULL, "Object must not be NULL");
+      guarantee(Universe::heap()->is_in_reserved(value), "Object must be on the heap");
+      guarantee(!value->is_forwarded(), "Object must not be forwarded");
+      guarantee(value->is_typeArray(), "Object must be a typeArrayOop");
+      unsigned int hash = hash_code(value);
+      guarantee((*entry)->hash() == hash, "Table entry has inorrect hash");
+      guarantee(_table->hash_to_index(hash) == bucket, "Table entry has incorrect index");
+      entry = (*entry)->next_addr();
+    }
+
+    // Verify that we do not have entries with identical oops or identical arrays.
+    // We only need to compare entries in the same bucket. If the same oop or an
+    // identical array has been inserted more than once into different/incorrect
+    // buckets the verification step above will catch that.
+    G1StringDedupEntry** entry1 = _table->bucket(bucket);
+    while (*entry1 != NULL) {
+      typeArrayOop value1 = (*entry1)->obj();
+      G1StringDedupEntry** entry2 = (*entry1)->next_addr();
+      while (*entry2 != NULL) {
+        typeArrayOop value2 = (*entry2)->obj();
+        guarantee(!equals(value1, value2), "Table entries must not have identical arrays");
+        entry2 = (*entry2)->next_addr();
+      }
+      entry1 = (*entry1)->next_addr();
+    }
+  }
+}
+
+void G1StringDedupTable::trim_entry_cache() {
+  MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
+  size_t max_cache_size = (size_t)(_table->_size * _max_cache_factor);
+  _entry_cache->trim(max_cache_size);
+}
+
+void G1StringDedupTable::print_statistics(outputStream* st) {
+  st->print_cr(
+    "   [Table]\n"
+    "      [Memory Usage: "G1_STRDEDUP_BYTES_FORMAT_NS"]\n"
+    "      [Size: "SIZE_FORMAT", Min: "SIZE_FORMAT", Max: "SIZE_FORMAT"]\n"
+    "      [Entries: "UINTX_FORMAT", Load: "G1_STRDEDUP_PERCENT_FORMAT_NS", Cached: " UINTX_FORMAT ", Added: "UINTX_FORMAT", Removed: "UINTX_FORMAT"]\n"
+    "      [Resize Count: "UINTX_FORMAT", Shrink Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS"), Grow Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS")]\n"
+    "      [Rehash Count: "UINTX_FORMAT", Rehash Threshold: "UINTX_FORMAT", Hash Seed: 0x%x]\n"
+    "      [Age Threshold: "UINTX_FORMAT"]",
+    G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)),
+    _table->_size, _min_size, _max_size,
+    _table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed,
+    _resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0,
+    _rehash_count, _rehash_threshold, _table->_hash_seed,
+    StringDeduplicationAgeThreshold);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
+
+#include "gc_implementation/g1/g1StringDedupStat.hpp"
+#include "runtime/mutexLocker.hpp"
+
+class G1StringDedupEntryCache;
+
+//
+// Table entry in the deduplication hashtable. Points weakly to the
+// character array. Can be chained in a linked list in case of hash
+// collisions or when placed in a freelist in the entry cache.
+//
+class G1StringDedupEntry : public CHeapObj<mtGC> {
+private:
+  G1StringDedupEntry* _next;
+  unsigned int      _hash;
+  typeArrayOop      _obj;
+
+public:
+  G1StringDedupEntry() :
+    _next(NULL),
+    _hash(0),
+    _obj(NULL) {
+  }
+
+  G1StringDedupEntry* next() {
+    return _next;
+  }
+
+  G1StringDedupEntry** next_addr() {
+    return &_next;
+  }
+
+  void set_next(G1StringDedupEntry* next) {
+    _next = next;
+  }
+
+  unsigned int hash() {
+    return _hash;
+  }
+
+  void set_hash(unsigned int hash) {
+    _hash = hash;
+  }
+
+  typeArrayOop obj() {
+    return _obj;
+  }
+
+  typeArrayOop* obj_addr() {
+    return &_obj;
+  }
+
+  void set_obj(typeArrayOop obj) {
+    _obj = obj;
+  }
+};
+
+//
+// The deduplication hashtable keeps track of all unique character arrays used
+// by String objects. Each table entry weakly points to an character array, allowing
+// otherwise unreachable character arrays to be declared dead and pruned from the
+// table.
+//
+// The table is dynamically resized to accommodate the current number of table entries.
+// The table has hash buckets with chains for hash collision. If the average chain
+// length goes above or below given thresholds the table grows or shrinks accordingly.
+//
+// The table is also dynamically rehashed (using a new hash seed) if it becomes severely
+// unbalanced, i.e., a hash chain is significantly longer than average.
+//
+// All access to the table is protected by the StringDedupTable_lock, except under
+// safepoints in which case GC workers are allowed to access a table partitions they
+// have claimed without first acquiring the lock. Note however, that this applies only
+// the table partition (i.e. a range of elements in _buckets), not other parts of the
+// table such as the _entries field, statistics counters, etc.
+//
+class G1StringDedupTable : public CHeapObj<mtGC> {
+private:
+  // The currently active hashtable instance. Only modified when
+  // the table is resizes or rehashed.
+  static G1StringDedupTable*      _table;
+
+  // Cache for reuse and fast alloc/free of table entries.
+  static G1StringDedupEntryCache* _entry_cache;
+
+  G1StringDedupEntry**            _buckets;
+  size_t                          _size;
+  uintx                           _entries;
+  uintx                           _shrink_threshold;
+  uintx                           _grow_threshold;
+  bool                            _rehash_needed;
+
+  // The hash seed also dictates which hash function to use. A
+  // zero hash seed means we will use the Java compatible hash
+  // function (which doesn't use a seed), and a non-zero hash
+  // seed means we use the murmur3 hash function.
+  jint                            _hash_seed;
+
+  // Constants governing table resize/rehash/cache.
+  static const size_t             _min_size;
+  static const size_t             _max_size;
+  static const double             _grow_load_factor;
+  static const double             _shrink_load_factor;
+  static const uintx              _rehash_multiple;
+  static const uintx              _rehash_threshold;
+  static const double             _max_cache_factor;
+
+  // Table statistics, only used for logging.
+  static uintx                    _entries_added;
+  static uintx                    _entries_removed;
+  static uintx                    _resize_count;
+  static uintx                    _rehash_count;
+
+  G1StringDedupTable(size_t size, jint hash_seed = 0);
+  ~G1StringDedupTable();
+
+  // Returns the hash bucket at the given index.
+  G1StringDedupEntry** bucket(size_t index) {
+    return _buckets + index;
+  }
+
+  // Returns the hash bucket index for the given hash code.
+  size_t hash_to_index(unsigned int hash) {
+    return (size_t)hash & (_size - 1);
+  }
+
+  // Adds a new table entry to the given hash bucket.
+  void add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list);
+
+  // Removes the given table entry from the table.
+  void remove(G1StringDedupEntry** pentry, uint worker_id);
+
+  // Transfers a table entry from the current table to the destination table.
+  void transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest);
+
+  // Returns an existing character array in the given hash bucket, or NULL
+  // if no matching character array exists.
+  typeArrayOop lookup(typeArrayOop value, unsigned int hash,
+                      G1StringDedupEntry** list, uintx &count);
+
+  // Returns an existing character array in the table, or inserts a new
+  // table entry if no matching character array exists.
+  typeArrayOop lookup_or_add_inner(typeArrayOop value, unsigned int hash);
+
+  // Thread safe lookup or add of table entry
+  static typeArrayOop lookup_or_add(typeArrayOop value, unsigned int hash) {
+    // Protect the table from concurrent access. Also note that this lock
+    // acts as a fence for _table, which could have been replaced by a new
+    // instance if the table was resized or rehashed.
+    MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
+    return _table->lookup_or_add_inner(value, hash);
+  }
+
+  // Returns true if the hashtable is currently using a Java compatible
+  // hash function.
+  static bool use_java_hash() {
+    return _table->_hash_seed == 0;
+  }
+
+  static bool equals(typeArrayOop value1, typeArrayOop value2);
+
+  // Computes the hash code for the given character array, using the
+  // currently active hash function and hash seed.
+  static unsigned int hash_code(typeArrayOop value);
+
+  static uintx unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl,
+                                 size_t partition_begin,
+                                 size_t partition_end,
+                                 uint worker_id);
+
+public:
+  static void create();
+
+  // Deduplicates the given String object, or adds its backing
+  // character array to the deduplication hashtable.
+  static void deduplicate(oop java_string, G1StringDedupStat& stat);
+
+  // If a table resize is needed, returns a newly allocated empty
+  // hashtable of the proper size.
+  static G1StringDedupTable* prepare_resize();
+
+  // Installs a newly resized table as the currently active table
+  // and deletes the previously active table.
+  static void finish_resize(G1StringDedupTable* resized_table);
+
+  // If a table rehash is needed, returns a newly allocated empty
+  // hashtable and updates the hash seed.
+  static G1StringDedupTable* prepare_rehash();
+
+  // Transfers rehashed entries from the currently active table into
+  // the new table. Installs the new table as the currently active table
+  // and deletes the previously active table.
+  static void finish_rehash(G1StringDedupTable* rehashed_table);
+
+  // If the table entry cache has grown too large, trim it down according to policy
+  static void trim_entry_cache();
+
+  static void unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, uint worker_id);
+
+  static void print_statistics(outputStream* st);
+  static void verify();
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 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 "gc_implementation/g1/g1Log.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
+#include "gc_implementation/g1/g1StringDedupTable.hpp"
+#include "gc_implementation/g1/g1StringDedupThread.hpp"
+#include "gc_implementation/g1/g1StringDedupQueue.hpp"
+
+G1StringDedupThread* G1StringDedupThread::_thread = NULL;
+
+G1StringDedupThread::G1StringDedupThread() :
+  ConcurrentGCThread() {
+  set_name("String Deduplication Thread");
+  create_and_start();
+}
+
+G1StringDedupThread::~G1StringDedupThread() {
+  ShouldNotReachHere();
+}
+
+void G1StringDedupThread::create() {
+  assert(G1StringDedup::is_enabled(), "String deduplication not enabled");
+  assert(_thread == NULL, "One string deduplication thread allowed");
+  _thread = new G1StringDedupThread();
+}
+
+G1StringDedupThread* G1StringDedupThread::thread() {
+  assert(G1StringDedup::is_enabled(), "String deduplication not enabled");
+  assert(_thread != NULL, "String deduplication thread not created");
+  return _thread;
+}
+
+void G1StringDedupThread::print_on(outputStream* st) const {
+  st->print("\"%s\" ", name());
+  Thread::print_on(st);
+  st->cr();
+}
+
+void G1StringDedupThread::run() {
+  G1StringDedupStat total_stat;
+
+  initialize_in_thread();
+  wait_for_universe_init();
+
+  // Main loop
+  for (;;) {
+    G1StringDedupStat stat;
+
+    stat.mark_idle();
+
+    // Wait for the queue to become non-empty
+    G1StringDedupQueue::wait();
+
+    // Include this thread in safepoints
+    stsJoin();
+
+    stat.mark_exec();
+
+    // Process the queue
+    for (;;) {
+      oop java_string = G1StringDedupQueue::pop();
+      if (java_string == NULL) {
+        break;
+      }
+
+      G1StringDedupTable::deduplicate(java_string, stat);
+
+      // Safepoint this thread if needed
+      if (stsShouldYield()) {
+        stat.mark_block();
+        stsYield(NULL);
+        stat.mark_unblock();
+      }
+    }
+
+    G1StringDedupTable::trim_entry_cache();
+
+    stat.mark_done();
+
+    // Print statistics
+    total_stat.add(stat);
+    print(gclog_or_tty, stat, total_stat);
+
+    // Exclude this thread from safepoints
+    stsLeave();
+  }
+
+  ShouldNotReachHere();
+}
+
+void G1StringDedupThread::print(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
+  if (G1Log::fine() || PrintStringDeduplicationStatistics) {
+    G1StringDedupStat::print_summary(st, last_stat, total_stat);
+    if (PrintStringDeduplicationStatistics) {
+      G1StringDedupStat::print_statistics(st, last_stat, false);
+      G1StringDedupStat::print_statistics(st, total_stat, true);
+      G1StringDedupTable::print_statistics(st);
+      G1StringDedupQueue::print_statistics(st);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
+
+#include "gc_implementation/g1/g1StringDedupStat.hpp"
+#include "gc_implementation/shared/concurrentGCThread.hpp"
+
+//
+// The deduplication thread is where the actual deduplication occurs. It waits for
+// deduplication candidates to appear on the deduplication queue, removes them from
+// the queue and tries to deduplicate them. It uses the deduplication hashtable to
+// find identical, already existing, character arrays on the heap. The thread runs
+// concurrently with the Java application but participates in safepoints to allow
+// the GC to adjust and unlink oops from the deduplication queue and table.
+//
+class G1StringDedupThread: public ConcurrentGCThread {
+private:
+  static G1StringDedupThread* _thread;
+
+  G1StringDedupThread();
+  ~G1StringDedupThread();
+
+  void print(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
+
+public:
+  static void create();
+  static G1StringDedupThread* thread();
+
+  virtual void run();
+  virtual void print_on(outputStream* st) const;
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -285,6 +285,10 @@
   product(uintx, G1MixedGCCountTarget, 8,                                   \
           "The target number of mixed GCs after a marking cycle.")          \
                                                                             \
+  experimental(uintx, G1CodeRootsChunkCacheKeepPercent, 10,                 \
+          "The amount of code root chunks that should be kept at most "     \
+          "as percentage of already allocated.")                            \
+                                                                            \
   experimental(uintx, G1OldCSetRegionThresholdPercent, 10,                  \
           "An upper bound for the number of old CSet regions expressed "    \
           "as a percentage of the heap size.")                              \
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -43,8 +43,6 @@
 class G1ParScanClosure;
 class G1ParPushHeapRSClosure;
 
-typedef G1ParCopyClosure<G1BarrierEvac, false> G1ParScanHeapEvacClosure;
-
 class FilterIntoCSClosure;
 class FilterOutOfRegionClosure;
 class G1CMOopClosure;
@@ -61,7 +59,6 @@
 #endif
 
 #define FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) \
-      f(G1ParScanHeapEvacClosure,_nv)                   \
       f(G1ParScanClosure,_nv)                           \
       f(G1ParPushHeapRSClosure,_nv)                     \
       f(FilterIntoCSClosure,_nv)                        \
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -205,7 +205,7 @@
   init_top_at_mark_start();
 }
 
-void HeapRegion::hr_clear(bool par, bool clear_space) {
+void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) {
   assert(_humongous_type == NotHumongous,
          "we should have already filtered out humongous regions");
   assert(_humongous_start_region == NULL,
@@ -223,7 +223,11 @@
   if (!par) {
     // If this is parallel, this will be done later.
     HeapRegionRemSet* hrrs = rem_set();
-    hrrs->clear();
+    if (locked) {
+      hrrs->clear_locked();
+    } else {
+      hrrs->clear();
+    }
     _claimed = InitialClaimValue;
   }
   zero_marked_bytes();
@@ -352,7 +356,7 @@
     _claimed(InitialClaimValue), _evacuation_failed(false),
     _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
     _young_type(NotYoung), _next_young_region(NULL),
-    _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false),
+    _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), _pending_removal(false),
 #ifdef ASSERT
     _containing_set(NULL),
 #endif // ASSERT
@@ -468,9 +472,6 @@
     } else if (!g1h->is_obj_dead(obj)) {
       cl->do_object(obj);
     }
-    if (cl->abort()) return cur;
-    // The check above must occur before the operation below, since an
-    // abort might invalidate the "size" operation.
     cur += obj->size();
   }
   return NULL;
@@ -710,14 +711,14 @@
   }
 
   HeapRegionRemSet* hrrs = rem_set();
-  int strong_code_roots_length = hrrs->strong_code_roots_list_length();
+  size_t strong_code_roots_length = hrrs->strong_code_roots_list_length();
 
   // if this region is empty then there should be no entries
   // on its strong code root list
   if (is_empty()) {
     if (strong_code_roots_length > 0) {
       gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is empty "
-                             "but has "INT32_FORMAT" code root entries",
+                             "but has "SIZE_FORMAT" code root entries",
                              bottom(), end(), strong_code_roots_length);
       *failures = true;
     }
@@ -727,7 +728,7 @@
   if (continuesHumongous()) {
     if (strong_code_roots_length > 0) {
       gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous "
-                             "region but has "INT32_FORMAT" code root entries",
+                             "region but has "SIZE_FORMAT" code root entries",
                              HR_FORMAT_PARAMS(this), strong_code_roots_length);
       *failures = true;
     }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -271,6 +271,7 @@
 
   // Fields used by the HeapRegionSetBase class and subclasses.
   HeapRegion* _next;
+  HeapRegion* _prev;
 #ifdef ASSERT
   HeapRegionSetBase* _containing_set;
 #endif // ASSERT
@@ -531,11 +532,13 @@
 
   // Methods used by the HeapRegionSetBase class and subclasses.
 
-  // Getter and setter for the next field used to link regions into
+  // Getter and setter for the next and prev fields used to link regions into
   // linked lists.
   HeapRegion* next()              { return _next; }
+  HeapRegion* prev()              { return _prev; }
 
   void set_next(HeapRegion* next) { _next = next; }
+  void set_prev(HeapRegion* prev) { _prev = prev; }
 
   // Every region added to a set is tagged with a reference to that
   // set. This is used for doing consistency checking to make sure that
@@ -596,7 +599,7 @@
   void save_marks();
 
   // Reset HR stuff to default values.
-  void hr_clear(bool par, bool clear_space);
+  void hr_clear(bool par, bool clear_space, bool locked = false);
   void par_clear();
 
   // Get the start of the unmarked area in this region.
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -29,6 +29,7 @@
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
 #include "memory/allocation.hpp"
+#include "memory/padded.inline.hpp"
 #include "memory/space.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "utilities/bitMap.inline.hpp"
@@ -259,10 +260,9 @@
 size_t OtherRegionsTable::_fine_eviction_stride = 0;
 size_t OtherRegionsTable::_fine_eviction_sample_size = 0;
 
-OtherRegionsTable::OtherRegionsTable(HeapRegion* hr) :
+OtherRegionsTable::OtherRegionsTable(HeapRegion* hr, Mutex* m) :
   _g1h(G1CollectedHeap::heap()),
-  _m(Mutex::leaf, "An OtherRegionsTable lock", true),
-  _hr(hr),
+  _hr(hr), _m(m),
   _coarse_map(G1CollectedHeap::heap()->max_regions(),
               false /* in-resource-area */),
   _fine_grain_regions(NULL),
@@ -358,46 +358,66 @@
          "just checking");
 }
 
-int**  OtherRegionsTable::_from_card_cache = NULL;
-size_t OtherRegionsTable::_from_card_cache_max_regions = 0;
-size_t OtherRegionsTable::_from_card_cache_mem_size = 0;
+int**  FromCardCache::_cache = NULL;
+uint   FromCardCache::_max_regions = 0;
+size_t FromCardCache::_static_mem_size = 0;
 
-void OtherRegionsTable::init_from_card_cache(size_t max_regions) {
-  _from_card_cache_max_regions = max_regions;
+void FromCardCache::initialize(uint n_par_rs, uint max_num_regions) {
+  guarantee(_cache == NULL, "Should not call this multiple times");
 
-  int n_par_rs = HeapRegionRemSet::num_par_rem_sets();
-  _from_card_cache = NEW_C_HEAP_ARRAY(int*, n_par_rs, mtGC);
-  for (int i = 0; i < n_par_rs; i++) {
-    _from_card_cache[i] = NEW_C_HEAP_ARRAY(int, max_regions, mtGC);
-    for (size_t j = 0; j < max_regions; j++) {
-      _from_card_cache[i][j] = -1;  // An invalid value.
+  _max_regions = max_num_regions;
+  _cache = Padded2DArray<int, mtGC>::create_unfreeable(n_par_rs,
+                                                       _max_regions,
+                                                       &_static_mem_size);
+
+  for (uint i = 0; i < n_par_rs; i++) {
+    for (uint j = 0; j < _max_regions; j++) {
+      set(i, j, InvalidCard);
     }
   }
-  _from_card_cache_mem_size = n_par_rs * max_regions * sizeof(int);
 }
 
-void OtherRegionsTable::shrink_from_card_cache(size_t new_n_regs) {
-  for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
-    assert(new_n_regs <= _from_card_cache_max_regions, "Must be within max.");
-    for (size_t j = new_n_regs; j < _from_card_cache_max_regions; j++) {
-      _from_card_cache[i][j] = -1;  // An invalid value.
+void FromCardCache::shrink(uint new_num_regions) {
+  for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
+    assert(new_num_regions <= _max_regions, "Must be within max.");
+    for (uint j = new_num_regions; j < _max_regions; j++) {
+      set(i, j, InvalidCard);
     }
   }
 }
 
 #ifndef PRODUCT
-void OtherRegionsTable::print_from_card_cache() {
-  for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
-    for (size_t j = 0; j < _from_card_cache_max_regions; j++) {
-      gclog_or_tty->print_cr("_from_card_cache[%d][%d] = %d.",
-                    i, j, _from_card_cache[i][j]);
+void FromCardCache::print(outputStream* out) {
+  for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
+    for (uint j = 0; j < _max_regions; j++) {
+      out->print_cr("_from_card_cache["UINT32_FORMAT"]["UINT32_FORMAT"] = "INT32_FORMAT".",
+                    i, j, at(i, j));
     }
   }
 }
 #endif
 
+void FromCardCache::clear(uint region_idx) {
+  uint num_par_remsets = HeapRegionRemSet::num_par_rem_sets();
+  for (uint i = 0; i < num_par_remsets; i++) {
+    set(i, region_idx, InvalidCard);
+  }
+}
+
+void OtherRegionsTable::init_from_card_cache(uint max_regions) {
+  FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions);
+}
+
+void OtherRegionsTable::shrink_from_card_cache(uint new_num_regions) {
+  FromCardCache::shrink(new_num_regions);
+}
+
+void OtherRegionsTable::print_from_card_cache() {
+  FromCardCache::print();
+}
+
 void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) {
-  size_t cur_hrs_ind = (size_t) hr()->hrs_index();
+  uint cur_hrs_ind = hr()->hrs_index();
 
   if (G1TraceHeapRegionRememberedSet) {
     gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
@@ -410,19 +430,17 @@
   int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift);
 
   if (G1TraceHeapRegionRememberedSet) {
-    gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)",
+    gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = "INT32_FORMAT")",
                   hr()->bottom(), from_card,
-                  _from_card_cache[tid][cur_hrs_ind]);
+                  FromCardCache::at((uint)tid, cur_hrs_ind));
   }
 
-  if (from_card == _from_card_cache[tid][cur_hrs_ind]) {
+  if (FromCardCache::contains_or_replace((uint)tid, cur_hrs_ind, from_card)) {
     if (G1TraceHeapRegionRememberedSet) {
       gclog_or_tty->print_cr("  from-card cache hit.");
     }
     assert(contains_reference(from), "We just added it!");
     return;
-  } else {
-    _from_card_cache[tid][cur_hrs_ind] = from_card;
   }
 
   // Note that this may be a continued H region.
@@ -442,7 +460,7 @@
   size_t ind = from_hrs_ind & _mod_max_fine_entries_mask;
   PerRegionTable* prt = find_region_table(ind, from_hr);
   if (prt == NULL) {
-    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+    MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
     // Confirm that it's really not there...
     prt = find_region_table(ind, from_hr);
     if (prt == NULL) {
@@ -544,7 +562,7 @@
 jint OtherRegionsTable::_n_coarsenings = 0;
 
 PerRegionTable* OtherRegionsTable::delete_region_table() {
-  assert(_m.owned_by_self(), "Precondition");
+  assert(_m->owned_by_self(), "Precondition");
   assert(_n_fine_entries == _max_fine_entries, "Precondition");
   PerRegionTable* max = NULL;
   jint max_occ = 0;
@@ -676,8 +694,6 @@
 
 
 size_t OtherRegionsTable::occupied() const {
-  // Cast away const in this case.
-  MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
   size_t sum = occ_fine();
   sum += occ_sparse();
   sum += occ_coarse();
@@ -707,8 +723,6 @@
 }
 
 size_t OtherRegionsTable::mem_size() const {
-  // Cast away const in this case.
-  MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
   size_t sum = 0;
   // all PRTs are of the same size so it is sufficient to query only one of them.
   if (_first_all_fine_prts != NULL) {
@@ -724,7 +738,7 @@
 }
 
 size_t OtherRegionsTable::static_mem_size() {
-  return _from_card_cache_mem_size;
+  return FromCardCache::static_mem_size();
 }
 
 size_t OtherRegionsTable::fl_mem_size() {
@@ -732,14 +746,10 @@
 }
 
 void OtherRegionsTable::clear_fcc() {
-  size_t hrs_idx = hr()->hrs_index();
-  for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
-    _from_card_cache[i][hrs_idx] = -1;
-  }
+  FromCardCache::clear(hr()->hrs_index());
 }
 
 void OtherRegionsTable::clear() {
-  MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
   // if there are no entries, skip this step
   if (_first_all_fine_prts != NULL) {
     guarantee(_first_all_fine_prts != NULL && _last_all_fine_prts != NULL, "just checking");
@@ -759,7 +769,7 @@
 }
 
 void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
-  MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   size_t hrs_ind = (size_t) from_hr->hrs_index();
   size_t ind = hrs_ind & _mod_max_fine_entries_mask;
   if (del_single_region_table(ind, from_hr)) {
@@ -768,15 +778,15 @@
     _coarse_map.par_at_put(hrs_ind, 0);
   }
   // Check to see if any of the fcc entries come from here.
-  size_t hr_ind = (size_t) hr()->hrs_index();
-  for (int tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
-    int fcc_ent = _from_card_cache[tid][hr_ind];
-    if (fcc_ent != -1) {
+  uint hr_ind = hr()->hrs_index();
+  for (uint tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
+    int fcc_ent = FromCardCache::at(tid, hr_ind);
+    if (fcc_ent != FromCardCache::InvalidCard) {
       HeapWord* card_addr = (HeapWord*)
         (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift);
       if (hr()->is_in_reserved(card_addr)) {
         // Clear the from card cache.
-        _from_card_cache[tid][hr_ind] = -1;
+        FromCardCache::set(tid, hr_ind, FromCardCache::InvalidCard);
       }
     }
   }
@@ -805,7 +815,7 @@
 
 bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
   // Cast away const in this case.
-  MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
+  MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag);
   return contains_reference_locked(from);
 }
 
@@ -832,8 +842,6 @@
            "Must be in range.");
     return _sparse_table.contains_card(hr_ind, card_index);
   }
-
-
 }
 
 void
@@ -844,13 +852,15 @@
 // Determines how many threads can add records to an rset in parallel.
 // This can be done by either mutator threads together with the
 // concurrent refinement threads or GC threads.
-int HeapRegionRemSet::num_par_rem_sets() {
-  return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
+uint HeapRegionRemSet::num_par_rem_sets() {
+  return (uint)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
 }
 
 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
                                    HeapRegion* hr)
-  : _bosa(bosa), _strong_code_roots_list(NULL), _other_regions(hr) {
+  : _bosa(bosa),
+    _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #"UINT32_FORMAT, hr->hrs_index()), true),
+    _code_roots(), _other_regions(hr, &_m) {
   reset_for_par_iteration();
 }
 
@@ -883,7 +893,7 @@
 }
 
 #ifndef PRODUCT
-void HeapRegionRemSet::print() const {
+void HeapRegionRemSet::print() {
   HeapRegionRemSetIterator iter(this);
   size_t card_index;
   while (iter.has_next(card_index)) {
@@ -909,14 +919,14 @@
 }
 
 void HeapRegionRemSet::clear() {
-  if (_strong_code_roots_list != NULL) {
-    delete _strong_code_roots_list;
-  }
-  _strong_code_roots_list = new (ResourceObj::C_HEAP, mtGC)
-                                GrowableArray<nmethod*>(10, 0, NULL, true);
+  MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+  clear_locked();
+}
 
+void HeapRegionRemSet::clear_locked() {
+  _code_roots.clear();
   _other_regions.clear();
-  assert(occupied() == 0, "Should be clear.");
+  assert(occupied_locked() == 0, "Should be clear.");
   reset_for_par_iteration();
 }
 
@@ -932,27 +942,18 @@
   _other_regions.scrub(ctbs, region_bm, card_bm);
 }
 
-
 // Code roots support
 
 void HeapRegionRemSet::add_strong_code_root(nmethod* nm) {
   assert(nm != NULL, "sanity");
-  // Search for the code blob from the RHS to avoid
-  // duplicate entries as much as possible
-  if (_strong_code_roots_list->find_from_end(nm) < 0) {
-    // Code blob isn't already in the list
-    _strong_code_roots_list->push(nm);
-  }
+  _code_roots.add(nm);
 }
 
 void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) {
   assert(nm != NULL, "sanity");
-  int idx = _strong_code_roots_list->find(nm);
-  if (idx >= 0) {
-    _strong_code_roots_list->remove_at(idx);
-  }
+  _code_roots.remove(nm);
   // Check that there were no duplicates
-  guarantee(_strong_code_roots_list->find(nm) < 0, "duplicate entry found");
+  guarantee(!_code_roots.contains(nm), "duplicate entry found");
 }
 
 class NMethodMigrationOopClosure : public OopClosure {
@@ -1014,8 +1015,8 @@
   GrowableArray<nmethod*> to_be_retained(10);
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  while (_strong_code_roots_list->is_nonempty()) {
-    nmethod *nm = _strong_code_roots_list->pop();
+  while (!_code_roots.is_empty()) {
+    nmethod *nm = _code_roots.pop();
     if (nm != NULL) {
       NMethodMigrationOopClosure oop_cl(g1h, hr(), nm);
       nm->oops_do(&oop_cl);
@@ -1038,20 +1039,16 @@
 }
 
 void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
-  for (int i = 0; i < _strong_code_roots_list->length(); i += 1) {
-    nmethod* nm = _strong_code_roots_list->at(i);
-    blk->do_code_blob(nm);
-  }
+  _code_roots.nmethods_do(blk);
 }
 
 size_t HeapRegionRemSet::strong_code_roots_mem_size() {
-  return sizeof(GrowableArray<nmethod*>) +
-         _strong_code_roots_list->max_length() * sizeof(nmethod*);
+  return _code_roots.mem_size();
 }
 
 //-------------------- Iteration --------------------
 
-HeapRegionRemSetIterator:: HeapRegionRemSetIterator(const HeapRegionRemSet* hrrs) :
+HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) :
   _hrrs(hrrs),
   _g1h(G1CollectedHeap::heap()),
   _coarse_map(&hrrs->_other_regions._coarse_map),
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP
 
+#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
 #include "gc_implementation/g1/sparsePRT.hpp"
 
 // Remembered set for a heap region.  Represent a set of "cards" that
@@ -44,6 +45,54 @@
 class HRRSCleanupTask : public SparsePRTCleanupTask {
 };
 
+// The FromCardCache remembers the most recently processed card on the heap on
+// a per-region and per-thread basis.
+class FromCardCache : public AllStatic {
+ private:
+  // Array of card indices. Indexed by thread X and heap region to minimize
+  // thread contention.
+  static int** _cache;
+  static uint _max_regions;
+  static size_t _static_mem_size;
+
+ public:
+  enum {
+    InvalidCard = -1 // Card value of an invalid card, i.e. a card index not otherwise used.
+  };
+
+  static void clear(uint region_idx);
+
+  // Returns true if the given card is in the cache at the given location, or
+  // replaces the card at that location and returns false.
+  static bool contains_or_replace(uint worker_id, uint region_idx, int card) {
+    int card_in_cache = at(worker_id, region_idx);
+    if (card_in_cache == card) {
+      return true;
+    } else {
+      set(worker_id, region_idx, card);
+      return false;
+    }
+  }
+
+  static int at(uint worker_id, uint region_idx) {
+    return _cache[worker_id][region_idx];
+  }
+
+  static void set(uint worker_id, uint region_idx, int val) {
+    _cache[worker_id][region_idx] = val;
+  }
+
+  static void initialize(uint n_par_rs, uint max_num_regions);
+
+  static void shrink(uint new_num_regions);
+
+  static void print(outputStream* out = gclog_or_tty) PRODUCT_RETURN;
+
+  static size_t static_mem_size() {
+    return _static_mem_size;
+  }
+};
+
 // The "_coarse_map" is a bitmap with one bit for each region, where set
 // bits indicate that the corresponding region may contain some pointer
 // into the owning region.
@@ -72,7 +121,7 @@
   friend class HeapRegionRemSetIterator;
 
   G1CollectedHeap* _g1h;
-  Mutex            _m;
+  Mutex*           _m;
   HeapRegion*      _hr;
 
   // These are protected by "_m".
@@ -118,18 +167,13 @@
   // false.
   bool del_single_region_table(size_t ind, HeapRegion* hr);
 
-  // Indexed by thread X heap region, to minimize thread contention.
-  static int** _from_card_cache;
-  static size_t _from_card_cache_max_regions;
-  static size_t _from_card_cache_mem_size;
-
   // link/add the given fine grain remembered set into the "all" list
   void link_to_all(PerRegionTable * prt);
   // unlink/remove the given fine grain remembered set into the "all" list
   void unlink_from_all(PerRegionTable * prt);
 
 public:
-  OtherRegionsTable(HeapRegion* hr);
+  OtherRegionsTable(HeapRegion* hr, Mutex* m);
 
   HeapRegion* hr() const { return _hr; }
 
@@ -141,7 +185,6 @@
   // objects.
   void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
 
-  // Not const because it takes a lock.
   size_t occupied() const;
   size_t occ_fine() const;
   size_t occ_coarse() const;
@@ -170,11 +213,11 @@
 
   // Declare the heap size (in # of regions) to the OtherRegionsTable.
   // (Uses it to initialize from_card_cache).
-  static void init_from_card_cache(size_t max_regions);
+  static void init_from_card_cache(uint max_regions);
 
   // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
   // Make sure any entries for higher regions are invalid.
-  static void shrink_from_card_cache(size_t new_n_regs);
+  static void shrink_from_card_cache(uint new_num_regions);
 
   static void print_from_card_cache();
 };
@@ -192,15 +235,17 @@
   G1BlockOffsetSharedArray* _bosa;
   G1BlockOffsetSharedArray* bosa() const { return _bosa; }
 
-  // A list of code blobs (nmethods) whose code contains pointers into
+  // A set of code blobs (nmethods) whose code contains pointers into
   // the region that owns this RSet.
-  GrowableArray<nmethod*>* _strong_code_roots_list;
+  G1CodeRootSet _code_roots;
+
+  Mutex _m;
 
   OtherRegionsTable _other_regions;
 
   enum ParIterState { Unclaimed, Claimed, Complete };
   volatile ParIterState _iter_state;
-  volatile jlong _iter_claimed;
+  volatile size_t _iter_claimed;
 
   // Unused unless G1RecordHRRSOops is true.
 
@@ -218,17 +263,20 @@
   static void print_event(outputStream* str, Event evnt);
 
 public:
-  HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
-                   HeapRegion* hr);
+  HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr);
 
-  static int num_par_rem_sets();
+  static uint num_par_rem_sets();
   static void setup_remset_size();
 
   HeapRegion* hr() const {
     return _other_regions.hr();
   }
 
-  size_t occupied() const {
+  size_t occupied() {
+    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+    return occupied_locked();
+  }
+  size_t occupied_locked() {
     return _other_regions.occupied();
   }
   size_t occ_fine() const {
@@ -260,6 +308,7 @@
   // The region is being reclaimed; clear its remset, and any mention of
   // entries for this region in other remsets.
   void clear();
+  void clear_locked();
 
   // Attempt to claim the region.  Returns true iff this call caused an
   // atomic transition from Unclaimed to Claimed.
@@ -270,16 +319,12 @@
   bool iter_is_complete();
 
   // Support for claiming blocks of cards during iteration
-  size_t iter_claimed() const { return (size_t)_iter_claimed; }
+  size_t iter_claimed() const { return _iter_claimed; }
   // Claim the next block of cards
   size_t iter_claimed_next(size_t step) {
-    size_t current, next;
-    do {
-      current = iter_claimed();
-      next = current + step;
-    } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current);
-    return current;
+    return Atomic::add(step, &_iter_claimed) - step;
   }
+
   void reset_for_par_iteration();
 
   bool verify_ready_for_par_iteration() {
@@ -289,6 +334,7 @@
   // The actual # of bytes this hr_remset takes up.
   // Note also includes the strong code root set.
   size_t mem_size() {
+    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
     return _other_regions.mem_size()
       // This correction is necessary because the above includes the second
       // part.
@@ -299,13 +345,13 @@
   // Returns the memory occupancy of all static data structures associated
   // with remembered sets.
   static size_t static_mem_size() {
-    return OtherRegionsTable::static_mem_size();
+    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
   }
 
   // Returns the memory occupancy of all free_list data structures associated
   // with remembered sets.
   static size_t fl_mem_size() {
-    return OtherRegionsTable::fl_mem_size();
+    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size();
   }
 
   bool contains_reference(OopOrNarrowOopStar from) const {
@@ -328,21 +374,21 @@
   void strong_code_roots_do(CodeBlobClosure* blk) const;
 
   // Returns the number of elements in the strong code roots list
-  int strong_code_roots_list_length() {
-    return _strong_code_roots_list->length();
+  size_t strong_code_roots_list_length() {
+    return _code_roots.length();
   }
 
   // Returns true if the strong code roots contains the given
   // nmethod.
   bool strong_code_roots_list_contains(nmethod* nm) {
-    return _strong_code_roots_list->contains(nm);
+    return _code_roots.contains(nm);
   }
 
   // Returns the amount of memory, in bytes, currently
   // consumed by the strong code roots.
   size_t strong_code_roots_mem_size();
 
-  void print() const;
+  void print() PRODUCT_RETURN;
 
   // Called during a stop-world phase to perform any deferred cleanups.
   static void cleanup();
@@ -350,12 +396,13 @@
   // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
   // (Uses it to initialize from_card_cache).
   static void init_heap(uint max_regions) {
-    OtherRegionsTable::init_from_card_cache((size_t) max_regions);
+    G1CodeRootSet::initialize();
+    OtherRegionsTable::init_from_card_cache(max_regions);
   }
 
   // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
   static void shrink_heap(uint new_n_regs) {
-    OtherRegionsTable::shrink_from_card_cache((size_t) new_n_regs);
+    OtherRegionsTable::shrink_from_card_cache(new_n_regs);
   }
 
 #ifndef PRODUCT
@@ -384,7 +431,7 @@
 class HeapRegionRemSetIterator : public StackObj {
 
   // The region RSet over which we're iterating.
-  const HeapRegionRemSet* _hrrs;
+  HeapRegionRemSet* _hrrs;
 
   // Local caching of HRRS fields.
   const BitMap*             _coarse_map;
@@ -441,7 +488,7 @@
 public:
   // We require an iterator to be initialized before use, so the
   // constructor does little.
-  HeapRegionRemSetIterator(const HeapRegionRemSet* hrrs);
+  HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
 
   // If there remains one or more cards to be yielded, returns true and
   // sets "card_index" to one of those cards (which is then considered
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
-#include "gc_implementation/g1/heapRegionSets.hpp"
+#include "gc_implementation/g1/heapRegionSet.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "memory/allocation.hpp"
 
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,171 +23,60 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
 
-uint HeapRegionSetBase::_unrealistically_long_length = 0;
-HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone;
-
-//////////////////// HeapRegionSetBase ////////////////////
-
-void HeapRegionSetBase::set_unrealistically_long_length(uint len) {
-  guarantee(_unrealistically_long_length == 0, "should only be set once");
-  _unrealistically_long_length = len;
-}
+uint FreeRegionList::_unrealistically_long_length = 0;
 
 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
-  msg->append("[%s] %s ln: %u rn: %u cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
-              name(), message, length(), region_num(),
-              total_capacity_bytes(), total_used_bytes());
+  msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
+              name(), message, length(), total_capacity_bytes());
   fill_in_ext_msg_extra(msg);
 }
 
-bool HeapRegionSetBase::verify_region(HeapRegion* hr,
-                                  HeapRegionSetBase* expected_containing_set) {
-  const char* error_message = NULL;
-
-  if (!regions_humongous()) {
-    if (hr->isHumongous()) {
-      error_message = "the region should not be humongous";
-    }
-  } else {
-    if (!hr->isHumongous() || !hr->startsHumongous()) {
-      error_message = "the region should be 'starts humongous'";
-    }
-  }
-
-  if (!regions_empty()) {
-    if (hr->is_empty()) {
-      error_message = "the region should not be empty";
-    }
-  } else {
-    if (!hr->is_empty()) {
-      error_message = "the region should be empty";
-    }
-  }
-
-#ifdef ASSERT
-  // The _containing_set field is only available when ASSERT is defined.
-  if (hr->containing_set() != expected_containing_set) {
-    error_message = "inconsistent containing set found";
-  }
-#endif // ASSERT
-
-  const char* extra_error_message = verify_region_extra(hr);
-  if (extra_error_message != NULL) {
-    error_message = extra_error_message;
-  }
-
-  if (error_message != NULL) {
-    outputStream* out = tty;
-    out->cr();
-    out->print_cr("## [%s] %s", name(), error_message);
-    out->print_cr("## Offending Region: "PTR_FORMAT, hr);
-    out->print_cr("   "HR_FORMAT, HR_FORMAT_PARAMS(hr));
-#ifdef ASSERT
-    out->print_cr("   containing set: "PTR_FORMAT, hr->containing_set());
-#endif // ASSERT
-    out->print_cr("## Offending Region Set: "PTR_FORMAT, this);
-    print_on(out);
-    return false;
-  } else {
-    return true;
-  }
+#ifndef PRODUCT
+void HeapRegionSetBase::verify_region(HeapRegion* hr) {
+  assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index()));
+  assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions
+  assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name()));
+  assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name()));
+  assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index()));
 }
+#endif
 
 void HeapRegionSetBase::verify() {
   // It's important that we also observe the MT safety protocol even
   // for the verification calls. If we do verification without the
   // appropriate locks and the set changes underneath our feet
   // verification might fail and send us on a wild goose chase.
-  hrs_assert_mt_safety_ok(this);
-
-  guarantee(( is_empty() && length() == 0 && region_num() == 0 &&
-              total_used_bytes() == 0 && total_capacity_bytes() == 0) ||
-            (!is_empty() && length() >= 0 && region_num() >= 0 &&
-              total_used_bytes() >= 0 && total_capacity_bytes() >= 0),
-            hrs_ext_msg(this, "invariant"));
+  check_mt_safety();
 
-  guarantee((!regions_humongous() && region_num() == length()) ||
-            ( regions_humongous() && region_num() >= length()),
-            hrs_ext_msg(this, "invariant"));
-
-  guarantee(!regions_empty() || total_used_bytes() == 0,
-            hrs_ext_msg(this, "invariant"));
-
-  guarantee(total_used_bytes() <= total_capacity_bytes(),
+  guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) ||
+            (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0),
             hrs_ext_msg(this, "invariant"));
 }
 
 void HeapRegionSetBase::verify_start() {
   // See comment in verify() about MT safety and verification.
-  hrs_assert_mt_safety_ok(this);
+  check_mt_safety();
   assert(!_verify_in_progress,
          hrs_ext_msg(this, "verification should not be in progress"));
 
   // Do the basic verification first before we do the checks over the regions.
   HeapRegionSetBase::verify();
 
-  _calc_length               = 0;
-  _calc_region_num           = 0;
-  _calc_total_capacity_bytes = 0;
-  _calc_total_used_bytes     = 0;
   _verify_in_progress        = true;
 }
 
-void HeapRegionSetBase::verify_next_region(HeapRegion* hr) {
-  // See comment in verify() about MT safety and verification.
-  hrs_assert_mt_safety_ok(this);
-  assert(_verify_in_progress,
-         hrs_ext_msg(this, "verification should be in progress"));
-
-  guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification"));
-
-  _calc_length               += 1;
-  _calc_region_num           += hr->region_num();
-  _calc_total_capacity_bytes += hr->capacity();
-  _calc_total_used_bytes     += hr->used();
-}
-
 void HeapRegionSetBase::verify_end() {
   // See comment in verify() about MT safety and verification.
-  hrs_assert_mt_safety_ok(this);
+  check_mt_safety();
   assert(_verify_in_progress,
          hrs_ext_msg(this, "verification should be in progress"));
 
-  guarantee(length() == _calc_length,
-            hrs_err_msg("[%s] length: %u should be == calc length: %u",
-                        name(), length(), _calc_length));
-
-  guarantee(region_num() == _calc_region_num,
-            hrs_err_msg("[%s] region num: %u should be == calc region num: %u",
-                        name(), region_num(), _calc_region_num));
-
-  guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
-            hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == "
-                        "calc capacity bytes: "SIZE_FORMAT,
-                        name(),
-                        total_capacity_bytes(), _calc_total_capacity_bytes));
-
-  guarantee(total_used_bytes() == _calc_total_used_bytes,
-            hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == "
-                        "calc used bytes: "SIZE_FORMAT,
-                        name(), total_used_bytes(), _calc_total_used_bytes));
-
   _verify_in_progress = false;
 }
 
-void HeapRegionSetBase::clear_phase() {
-  assert(_phase != HRSPhaseNone, "pre-condition");
-  _phase = HRSPhaseNone;
-}
-
-void HeapRegionSetBase::set_phase(HRSPhase phase) {
-  assert(_phase == HRSPhaseNone, "pre-condition");
-  assert(phase != HRSPhaseNone, "pre-condition");
-  _phase = phase;
-}
-
 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
   out->cr();
   out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
@@ -196,76 +85,38 @@
   out->print_cr("    empty             : %s", BOOL_TO_STR(regions_empty()));
   out->print_cr("  Attributes");
   out->print_cr("    length            : %14u", length());
-  out->print_cr("    region num        : %14u", region_num());
   out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
                 total_capacity_bytes());
-  out->print_cr("    total used        : "SIZE_FORMAT_W(14)" bytes",
-                total_used_bytes());
-}
-
-void HeapRegionSetBase::clear() {
-  _length           = 0;
-  _region_num       = 0;
-  _total_used_bytes = 0;
 }
 
-HeapRegionSetBase::HeapRegionSetBase(const char* name)
+HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker)
   : _name(name), _verify_in_progress(false),
-    _calc_length(0), _calc_region_num(0),
-    _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { }
-
-//////////////////// HeapRegionSet ////////////////////
-
-void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
-  hrs_assert_mt_safety_ok(this);
-  hrs_assert_mt_safety_ok(proxy_set);
-  hrs_assert_sets_match(this, proxy_set);
-
-  verify_optional();
-  proxy_set->verify_optional();
-
-  if (proxy_set->is_empty()) return;
+    _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker),
+    _count()
+{ }
 
-  assert(proxy_set->length() <= _length,
-         hrs_err_msg("[%s] proxy set length: %u should be <= length: %u",
-                     name(), proxy_set->length(), _length));
-  _length -= proxy_set->length();
-
-  assert(proxy_set->region_num() <= _region_num,
-         hrs_err_msg("[%s] proxy set region num: %u should be <= region num: %u",
-                     name(), proxy_set->region_num(), _region_num));
-  _region_num -= proxy_set->region_num();
-
-  assert(proxy_set->total_used_bytes() <= _total_used_bytes,
-         hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" "
-                     "should be <= used bytes: "SIZE_FORMAT,
-                     name(), proxy_set->total_used_bytes(),
-                     _total_used_bytes));
-  _total_used_bytes -= proxy_set->total_used_bytes();
-
-  proxy_set->clear();
-
-  verify_optional();
-  proxy_set->verify_optional();
+void FreeRegionList::set_unrealistically_long_length(uint len) {
+  guarantee(_unrealistically_long_length == 0, "should only be set once");
+  _unrealistically_long_length = len;
 }
 
-//////////////////// HeapRegionLinkedList ////////////////////
-
-void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
+void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
   msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
 }
 
-void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) {
-  hrs_assert_mt_safety_ok(this);
-  hrs_assert_mt_safety_ok(from_list);
+void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) {
+  check_mt_safety();
+  from_list->check_mt_safety();
 
   verify_optional();
   from_list->verify_optional();
 
-  if (from_list->is_empty()) return;
+  if (from_list->is_empty()) {
+    return;
+  }
 
 #ifdef ASSERT
-  HeapRegionLinkedListIterator iter(from_list);
+  FreeRegionListIterator iter(from_list);
   while (iter.more_available()) {
     HeapRegion* hr = iter.get_next();
     // In set_containing_set() we check that we either set the value
@@ -276,35 +127,75 @@
   }
 #endif // ASSERT
 
-  if (_head != NULL) {
-    assert(length() >  0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
-    from_list->_tail->set_next(_head);
-  } else {
+  if (_head == NULL) {
     assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
+    _head = from_list->_head;
     _tail = from_list->_tail;
+  } else {
+    assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
+    if (as_head) {
+      from_list->_tail->set_next(_head);
+      _head->set_prev(from_list->_tail);
+      _head = from_list->_head;
+    } else {
+      _tail->set_next(from_list->_head);
+      from_list->_head->set_prev(_tail);
+      _tail = from_list->_tail;
+    }
   }
-  _head = from_list->_head;
 
-  _length           += from_list->length();
-  _region_num       += from_list->region_num();
-  _total_used_bytes += from_list->total_used_bytes();
+  _count.increment(from_list->length(), from_list->total_capacity_bytes());
   from_list->clear();
 
   verify_optional();
   from_list->verify_optional();
 }
 
-void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
-  hrs_assert_mt_safety_ok(this);
-  hrs_assert_mt_safety_ok(from_list);
+void FreeRegionList::add_as_head(FreeRegionList* from_list) {
+  add_as_head_or_tail(from_list, true /* as_head */);
+}
+
+void FreeRegionList::add_as_tail(FreeRegionList* from_list) {
+  add_as_head_or_tail(from_list, false /* as_head */);
+}
+
+void FreeRegionList::remove_all() {
+  check_mt_safety();
+  verify_optional();
+
+  HeapRegion* curr = _head;
+  while (curr != NULL) {
+    verify_region(curr);
+
+    HeapRegion* next = curr->next();
+    curr->set_next(NULL);
+    curr->set_prev(NULL);
+    curr->set_containing_set(NULL);
+    curr = next;
+  }
+  clear();
+
+  verify_optional();
+}
+
+void FreeRegionList::add_ordered(FreeRegionList* from_list) {
+  check_mt_safety();
+  from_list->check_mt_safety();
 
   verify_optional();
   from_list->verify_optional();
 
-  if (from_list->is_empty()) return;
+  if (from_list->is_empty()) {
+    return;
+  }
 
-#ifdef ASSERT
-  HeapRegionLinkedListIterator iter(from_list);
+  if (is_empty()) {
+    add_as_head(from_list);
+    return;
+  }
+
+  #ifdef ASSERT
+  FreeRegionListIterator iter(from_list);
   while (iter.more_available()) {
     HeapRegion* hr = iter.get_next();
     // In set_containing_set() we check that we either set the value
@@ -313,46 +204,50 @@
     hr->set_containing_set(NULL);
     hr->set_containing_set(this);
   }
-#endif // ASSERT
+  #endif // ASSERT
+
+  HeapRegion* curr_to = _head;
+  HeapRegion* curr_from = from_list->_head;
+
+  while (curr_from != NULL) {
+    while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) {
+      curr_to = curr_to->next();
+    }
+
+    if (curr_to == NULL) {
+      // The rest of the from list should be added as tail
+      _tail->set_next(curr_from);
+      curr_from->set_prev(_tail);
+      curr_from = NULL;
+    } else {
+      HeapRegion* next_from = curr_from->next();
 
-  if (_tail != NULL) {
-    assert(length() >  0 && _head != NULL, hrs_ext_msg(this, "invariant"));
-    _tail->set_next(from_list->_head);
-  } else {
-    assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant"));
-    _head = from_list->_head;
+      curr_from->set_next(curr_to);
+      curr_from->set_prev(curr_to->prev());
+      if (curr_to->prev() == NULL) {
+        _head = curr_from;
+      } else {
+        curr_to->prev()->set_next(curr_from);
+      }
+      curr_to->set_prev(curr_from);
+
+      curr_from = next_from;
+    }
   }
-  _tail = from_list->_tail;
 
-  _length           += from_list->length();
-  _region_num       += from_list->region_num();
-  _total_used_bytes += from_list->total_used_bytes();
+  if (_tail->hrs_index() < from_list->_tail->hrs_index()) {
+    _tail = from_list->_tail;
+  }
+
+  _count.increment(from_list->length(), from_list->total_capacity_bytes());
   from_list->clear();
 
   verify_optional();
   from_list->verify_optional();
 }
 
-void HeapRegionLinkedList::remove_all() {
-  hrs_assert_mt_safety_ok(this);
-  verify_optional();
-
-  HeapRegion* curr = _head;
-  while (curr != NULL) {
-    hrs_assert_region_ok(this, curr, this);
-
-    HeapRegion* next = curr->next();
-    curr->set_next(NULL);
-    curr->set_containing_set(NULL);
-    curr = next;
-  }
-  clear();
-
-  verify_optional();
-}
-
-void HeapRegionLinkedList::remove_all_pending(uint target_count) {
-  hrs_assert_mt_safety_ok(this);
+void FreeRegionList::remove_all_pending(uint target_count) {
+  check_mt_safety();
   assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
   assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
 
@@ -360,11 +255,11 @@
   DEBUG_ONLY(uint old_length = length();)
 
   HeapRegion* curr = _head;
-  HeapRegion* prev = NULL;
   uint count = 0;
   while (curr != NULL) {
-    hrs_assert_region_ok(this, curr, this);
+    verify_region(curr);
     HeapRegion* next = curr->next();
+    HeapRegion* prev = curr->prev();
 
     if (curr->pending_removal()) {
       assert(count < target_count,
@@ -384,10 +279,15 @@
         _tail = prev;
       } else {
         assert(_tail != curr, hrs_ext_msg(this, "invariant"));
+        next->set_prev(prev);
+      }
+      if (_last = curr) {
+        _last = NULL;
       }
 
       curr->set_next(NULL);
-      remove_internal(curr);
+      curr->set_prev(NULL);
+      remove(curr);
       curr->set_pending_removal(false);
 
       count += 1;
@@ -397,8 +297,6 @@
       // carry on iterating to make sure there are not more regions
       // tagged with pending removal.
       DEBUG_ONLY(if (count == target_count) break;)
-    } else {
-      prev = curr;
     }
     curr = next;
   }
@@ -414,46 +312,27 @@
   verify_optional();
 }
 
-void HeapRegionLinkedList::verify() {
+void FreeRegionList::verify() {
   // See comment in HeapRegionSetBase::verify() about MT safety and
   // verification.
-  hrs_assert_mt_safety_ok(this);
+  check_mt_safety();
 
   // This will also do the basic verification too.
   verify_start();
 
-  HeapRegion* curr  = _head;
-  HeapRegion* prev1 = NULL;
-  HeapRegion* prev0 = NULL;
-  uint        count = 0;
-  while (curr != NULL) {
-    verify_next_region(curr);
-
-    count += 1;
-    guarantee(count < _unrealistically_long_length,
-              hrs_err_msg("[%s] the calculated length: %u "
-                          "seems very long, is there maybe a cycle? "
-                          "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
-                          "prev1: "PTR_FORMAT" length: %u",
-                          name(), count, curr, prev0, prev1, length()));
-
-    prev1 = prev0;
-    prev0 = curr;
-    curr  = curr->next();
-  }
-
-  guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition"));
+  verify_list();
 
   verify_end();
 }
 
-void HeapRegionLinkedList::clear() {
-  HeapRegionSetBase::clear();
+void FreeRegionList::clear() {
+  _count = HeapRegionSetCount();
   _head = NULL;
   _tail = NULL;
+  _last = NULL;
 }
 
-void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) {
+void FreeRegionList::print_on(outputStream* out, bool print_contents) {
   HeapRegionSetBase::print_on(out, print_contents);
   out->print_cr("  Linking");
   out->print_cr("    head              : "PTR_FORMAT, _head);
@@ -461,10 +340,124 @@
 
   if (print_contents) {
     out->print_cr("  Contents");
-    HeapRegionLinkedListIterator iter(this);
+    FreeRegionListIterator iter(this);
     while (iter.more_available()) {
       HeapRegion* hr = iter.get_next();
       hr->print_on(out);
     }
   }
 }
+
+void FreeRegionList::verify_list() {
+  HeapRegion* curr = head();
+  HeapRegion* prev1 = NULL;
+  HeapRegion* prev0 = NULL;
+  uint count = 0;
+  size_t capacity = 0;
+  uint last_index = 0;
+
+  guarantee(_head == NULL || _head->prev() == NULL, "_head should not have a prev");
+  while (curr != NULL) {
+    verify_region(curr);
+
+    count++;
+    guarantee(count < _unrealistically_long_length,
+        hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u", name(), count, curr, prev0, prev1, length()));
+
+    if (curr->next() != NULL) {
+      guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up");
+    }
+    guarantee(curr->hrs_index() == 0 || curr->hrs_index() > last_index, "List should be sorted");
+    last_index = curr->hrs_index();
+
+    capacity += curr->capacity();
+
+    prev1 = prev0;
+    prev0 = curr;
+    curr = curr->next();
+  }
+
+  guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index()));
+  guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
+  guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count));
+  guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
+      name(), total_capacity_bytes(), capacity));
+}
+
+// Note on the check_mt_safety() methods below:
+//
+// Verification of the "master" heap region sets / lists that are
+// maintained by G1CollectedHeap is always done during a STW pause and
+// by the VM thread at the start / end of the pause. The standard
+// verification methods all assert check_mt_safety(). This is
+// important as it ensures that verification is done without
+// concurrent updates taking place at the same time. It follows, that,
+// for the "master" heap region sets / lists, the check_mt_safety()
+// method should include the VM thread / STW case.
+
+void MasterFreeRegionListMtSafeChecker::check() {
+  // Master Free List MT safety protocol:
+  // (a) If we're at a safepoint, operations on the master free list
+  // should be invoked by either the VM thread (which will serialize
+  // them) or by the GC workers while holding the
+  // FreeList_lock.
+  // (b) If we're not at a safepoint, operations on the master free
+  // list should be invoked while holding the Heap_lock.
+
+  if (SafepointSynchronize::is_at_safepoint()) {
+    guarantee(Thread::current()->is_VM_thread() ||
+              FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
+  } else {
+    guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
+  }
+}
+
+void SecondaryFreeRegionListMtSafeChecker::check() {
+  // Secondary Free List MT safety protocol:
+  // Operations on the secondary free list should always be invoked
+  // while holding the SecondaryFreeList_lock.
+
+  guarantee(SecondaryFreeList_lock->owned_by_self(), "secondary free list MT safety protocol");
+}
+
+void OldRegionSetMtSafeChecker::check() {
+  // Master Old Set MT safety protocol:
+  // (a) If we're at a safepoint, operations on the master old set
+  // should be invoked:
+  // - by the VM thread (which will serialize them), or
+  // - by the GC workers while holding the FreeList_lock, if we're
+  //   at a safepoint for an evacuation pause (this lock is taken
+  //   anyway when an GC alloc region is retired so that a new one
+  //   is allocated from the free list), or
+  // - by the GC workers while holding the OldSets_lock, if we're at a
+  //   safepoint for a cleanup pause.
+  // (b) If we're not at a safepoint, operations on the master old set
+  // should be invoked while holding the Heap_lock.
+
+  if (SafepointSynchronize::is_at_safepoint()) {
+    guarantee(Thread::current()->is_VM_thread()
+        || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
+        "master old set MT safety protocol at a safepoint");
+  } else {
+    guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
+  }
+}
+
+void HumongousRegionSetMtSafeChecker::check() {
+  // Humongous Set MT safety protocol:
+  // (a) If we're at a safepoint, operations on the master humongous
+  // set should be invoked by either the VM thread (which will
+  // serialize them) or by the GC workers while holding the
+  // OldSets_lock.
+  // (b) If we're not at a safepoint, operations on the master
+  // humongous set should be invoked while holding the Heap_lock.
+
+  if (SafepointSynchronize::is_at_safepoint()) {
+    guarantee(Thread::current()->is_VM_thread() ||
+              OldSets_lock->owned_by_self(),
+              "master humongous set MT safety protocol at a safepoint");
+  } else {
+    guarantee(Heap_lock->owned_by_self(),
+              "master humongous set MT safety protocol outside a safepoint");
+  }
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -38,135 +38,108 @@
 #define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
 #endif // HEAP_REGION_SET_FORCE_VERIFY
 
-//////////////////// HeapRegionSetBase ////////////////////
+class hrs_ext_msg;
+
+class HRSMtSafeChecker : public CHeapObj<mtGC> {
+public:
+  virtual void check() = 0;
+};
+
+class MasterFreeRegionListMtSafeChecker    : public HRSMtSafeChecker { public: void check(); };
+class SecondaryFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
+class HumongousRegionSetMtSafeChecker      : public HRSMtSafeChecker { public: void check(); };
+class OldRegionSetMtSafeChecker            : public HRSMtSafeChecker { public: void check(); };
+
+class HeapRegionSetCount VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+  uint   _length;
+  size_t _capacity;
+
+public:
+  HeapRegionSetCount() : _length(0), _capacity(0) { }
+
+  const uint   length()   const { return _length;   }
+  const size_t capacity() const { return _capacity; }
+
+  void increment(uint length_to_add, size_t capacity_to_add) {
+    _length += length_to_add;
+    _capacity += capacity_to_add;
+  }
+
+  void decrement(const uint length_to_remove, const size_t capacity_to_remove) {
+    _length -= length_to_remove;
+    _capacity -= capacity_to_remove;
+  }
+};
 
 // Base class for all the classes that represent heap region sets. It
 // contains the basic attributes that each set needs to maintain
 // (e.g., length, region num, used bytes sum) plus any shared
 // functionality (e.g., verification).
 
-class hrs_ext_msg;
-
-typedef enum {
-  HRSPhaseNone,
-  HRSPhaseEvacuation,
-  HRSPhaseCleanup,
-  HRSPhaseFullGC
-} HRSPhase;
-
-class HRSPhaseSetter;
-
 class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
-  friend class hrs_ext_msg;
-  friend class HRSPhaseSetter;
   friend class VMStructs;
+private:
+  bool _is_humongous;
+  bool _is_empty;
+  HRSMtSafeChecker* _mt_safety_checker;
 
 protected:
-  static uint _unrealistically_long_length;
-
   // The number of regions added to the set. If the set contains
   // only humongous regions, this reflects only 'starts humongous'
   // regions and does not include 'continues humongous' ones.
-  uint _length;
-
-  // The total number of regions represented by the set. If the set
-  // does not contain humongous regions, this should be the same as
-  // _length. If the set contains only humongous regions, this will
-  // include the 'continues humongous' regions.
-  uint _region_num;
-
-  // We don't keep track of the total capacity explicitly, we instead
-  // recalculate it based on _region_num and the heap region size.
-
-  // The sum of used bytes in the all the regions in the set.
-  size_t _total_used_bytes;
+  HeapRegionSetCount _count;
 
   const char* _name;
 
-  bool        _verify_in_progress;
-  uint        _calc_length;
-  uint        _calc_region_num;
-  size_t      _calc_total_capacity_bytes;
-  size_t      _calc_total_used_bytes;
-
-  // This is here so that it can be used in the subclasses to assert
-  // something different depending on which phase the GC is in. This
-  // can be particularly helpful in the check_mt_safety() methods.
-  static HRSPhase _phase;
-
-  // Only used by HRSPhaseSetter.
-  static void clear_phase();
-  static void set_phase(HRSPhase phase);
+  bool _verify_in_progress;
 
   // verify_region() is used to ensure that the contents of a region
-  // added to / removed from a set are consistent. Different sets
-  // make different assumptions about the regions added to them. So
-  // each set can override verify_region_extra(), which is called
-  // from verify_region(), and do any extra verification it needs to
-  // perform in that.
-  virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; }
-  bool verify_region(HeapRegion* hr,
-                     HeapRegionSetBase* expected_containing_set);
+  // added to / removed from a set are consistent.
+  void verify_region(HeapRegion* hr) PRODUCT_RETURN;
 
   // Indicates whether all regions in the set should be humongous or
   // not. Only used during verification.
-  virtual bool regions_humongous() = 0;
+  bool regions_humongous() { return _is_humongous; }
 
   // Indicates whether all regions in the set should be empty or
   // not. Only used during verification.
-  virtual bool regions_empty() = 0;
+  bool regions_empty() { return _is_empty; }
+
+  void check_mt_safety() {
+    if (_mt_safety_checker != NULL) {
+      _mt_safety_checker->check();
+    }
+  }
+
+  virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { }
+
+  HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker);
+
+public:
+  const char* name() { return _name; }
 
-  // Subclasses can optionally override this to do MT safety protocol
-  // checks. It is called in an assert from all methods that perform
-  // updates on the set (and subclasses should also call it too).
-  virtual bool check_mt_safety() { return true; }
+  uint length() { return _count.length(); }
+
+  bool is_empty() { return _count.length() == 0; }
+
+  size_t total_capacity_bytes() {
+    return _count.capacity();
+  }
+
+  // It updates the fields of the set to reflect hr being added to
+  // the set and tags the region appropriately.
+  inline void add(HeapRegion* hr);
+
+  // It updates the fields of the set to reflect hr being removed
+  // from the set and tags the region appropriately.
+  inline void remove(HeapRegion* hr);
 
   // fill_in_ext_msg() writes the the values of the set's attributes
   // in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra()
   // allows subclasses to append further information.
-  virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { }
   void fill_in_ext_msg(hrs_ext_msg* msg, const char* message);
 
-  // It updates the fields of the set to reflect hr being added to
-  // the set.
-  inline void update_for_addition(HeapRegion* hr);
-
-  // It updates the fields of the set to reflect hr being added to
-  // the set and tags the region appropriately.
-  inline void add_internal(HeapRegion* hr);
-
-  // It updates the fields of the set to reflect hr being removed
-  // from the set.
-  inline void update_for_removal(HeapRegion* hr);
-
-  // It updates the fields of the set to reflect hr being removed
-  // from the set and tags the region appropriately.
-  inline void remove_internal(HeapRegion* hr);
-
-  // It clears all the fields of the sets. Note: it will not iterate
-  // over the set and remove regions from it. It assumes that the
-  // caller has already done so. It will literally just clear the fields.
-  virtual void clear();
-
-  HeapRegionSetBase(const char* name);
-
-public:
-  static void set_unrealistically_long_length(uint len);
-
-  const char* name() { return _name; }
-
-  uint length() { return _length; }
-
-  bool is_empty() { return _length == 0; }
-
-  uint region_num() { return _region_num; }
-
-  size_t total_capacity_bytes() {
-    return (size_t) region_num() << HeapRegion::LogOfHRGrainBytes;
-  }
-
-  size_t total_used_bytes() { return _total_used_bytes; }
-
   virtual void verify();
   void verify_start();
   void verify_next_region(HeapRegion* hr);
@@ -187,7 +160,6 @@
 // assert/guarantee-specific message it also prints out the values of
 // the fields of the associated set. This can be very helpful in
 // diagnosing failures.
-
 class hrs_ext_msg : public hrs_err_msg {
 public:
   hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("") {
@@ -195,32 +167,6 @@
   }
 };
 
-class HRSPhaseSetter {
-public:
-  HRSPhaseSetter(HRSPhase phase) {
-    HeapRegionSetBase::set_phase(phase);
-  }
-  ~HRSPhaseSetter() {
-    HeapRegionSetBase::clear_phase();
-  }
-};
-
-// These two macros are provided for convenience, to keep the uses of
-// these two asserts a bit more concise.
-
-#define hrs_assert_mt_safety_ok(_set_)                                        \
-  do {                                                                        \
-    assert((_set_)->check_mt_safety(), hrs_ext_msg((_set_), "MT safety"));    \
-  } while (0)
-
-#define hrs_assert_region_ok(_set_, _hr_, _expected_)                         \
-  do {                                                                        \
-    assert((_set_)->verify_region((_hr_), (_expected_)),                      \
-           hrs_ext_msg((_set_), "region verification"));                      \
-  } while (0)
-
-//////////////////// HeapRegionSet ////////////////////
-
 #define hrs_assert_sets_match(_set1_, _set2_)                                 \
   do {                                                                        \
     assert(((_set1_)->regions_humongous() ==                                  \
@@ -236,63 +182,41 @@
 // the same interface (namely, the HeapRegionSetBase API).
 
 class HeapRegionSet : public HeapRegionSetBase {
-protected:
-  virtual const char* verify_region_extra(HeapRegion* hr) {
-    if (hr->next() != NULL) {
-      return "next() should always be NULL as we do not link the regions";
-    }
-
-    return HeapRegionSetBase::verify_region_extra(hr);
-  }
-
-  HeapRegionSet(const char* name) : HeapRegionSetBase(name) {
-    clear();
-  }
-
 public:
-  // It adds hr to the set. The region should not be a member of
-  // another set.
-  inline void add(HeapRegion* hr);
+  HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
+    HeapRegionSetBase(name, humongous, false /* empty */, mt_safety_checker) { }
 
-  // It removes hr from the set. The region should be a member of
-  // this set.
-  inline void remove(HeapRegion* hr);
-
-  // It removes a region from the set. Instead of updating the fields
-  // of the set to reflect this removal, it accumulates the updates
-  // in proxy_set. The idea is that proxy_set is thread-local to
-  // avoid multiple threads updating the fields of the set
-  // concurrently and having to synchronize. The method
-  // update_from_proxy() will update the fields of the set from the
-  // proxy_set.
-  inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set);
-
-  // After multiple calls to remove_with_proxy() the updates to the
-  // fields of the set are accumulated in proxy_set. This call
-  // updates the fields of the set from proxy_set.
-  void update_from_proxy(HeapRegionSet* proxy_set);
+  void bulk_remove(const HeapRegionSetCount& removed) {
+    _count.decrement(removed.length(), removed.capacity());
+  }
 };
 
-//////////////////// HeapRegionLinkedList ////////////////////
-
-// A set that links all the regions added to it in a singly-linked
+// A set that links all the regions added to it in a doubly-linked
 // list. We should try to avoid doing operations that iterate over
 // such lists in performance critical paths. Typically we should
-// add / remove one region at a time or concatenate two lists. All
-// those operations are done in constant time.
+// add / remove one region at a time or concatenate two lists. There are
+// two ways to treat your lists, ordered and un-ordered. All un-ordered
+// operations are done in constant time. To keep a list ordered only use
+// add_ordered() to add elements to the list. If a list is not ordered
+// from start, there is no way to sort it later.
 
-class HeapRegionLinkedListIterator;
+class FreeRegionListIterator;
 
-class HeapRegionLinkedList : public HeapRegionSetBase {
-  friend class HeapRegionLinkedListIterator;
+class FreeRegionList : public HeapRegionSetBase {
+  friend class FreeRegionListIterator;
 
 private:
   HeapRegion* _head;
   HeapRegion* _tail;
 
-  // These are provided for use by the friend classes.
-  HeapRegion* head() { return _head; }
-  HeapRegion* tail() { return _tail; }
+  // _last is used to keep track of where we added an element the last
+  // time in ordered lists. It helps to improve performance when adding
+  // several ordered items in a row.
+  HeapRegion* _last;
+
+  static uint _unrealistically_long_length;
+
+  void add_as_head_or_tail(FreeRegionList* from_list, bool as_head);
 
 protected:
   virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg);
@@ -300,11 +224,24 @@
   // See the comment for HeapRegionSetBase::clear()
   virtual void clear();
 
-  HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) {
+public:
+  FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL):
+    HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) {
     clear();
   }
 
-public:
+  void verify_list();
+
+  HeapRegion* head() { return _head; }
+  HeapRegion* tail() { return _tail; }
+
+  static void set_unrealistically_long_length(uint len);
+
+  // Add hr to the list. The region should not be a member of another set.
+  // Assumes that the list is ordered and will preserve that order. The order
+  // is determined by hrs_index.
+  inline void add_ordered(HeapRegion* hr);
+
   // It adds hr to the list as the new head. The region should not be
   // a member of another set.
   inline void add_as_head(HeapRegion* hr);
@@ -320,15 +257,29 @@
   // Convenience method.
   inline HeapRegion* remove_head_or_null();
 
+  // Removes and returns the last element (_tail) of the list. It assumes
+  // that the list isn't empty so that it can return a non-NULL value.
+  inline HeapRegion* remove_tail();
+
+  // Convenience method
+  inline HeapRegion* remove_tail_or_null();
+
+  // Removes from head or tail based on the given argument.
+  inline HeapRegion* remove_region(bool from_head);
+
+  // Merge two ordered lists. The result is also ordered. The order is
+  // determined by hrs_index.
+  void add_ordered(FreeRegionList* from_list);
+
   // It moves the regions from from_list to this list and empties
   // from_list. The new regions will appear in the same order as they
   // were in from_list and be linked in the beginning of this list.
-  void add_as_head(HeapRegionLinkedList* from_list);
+  void add_as_head(FreeRegionList* from_list);
 
   // It moves the regions from from_list to this list and empties
   // from_list. The new regions will appear in the same order as they
   // were in from_list and be linked in the end of this list.
-  void add_as_tail(HeapRegionLinkedList* from_list);
+  void add_as_tail(FreeRegionList* from_list);
 
   // It empties the list by removing all regions from it.
   void remove_all();
@@ -346,15 +297,13 @@
   virtual void print_on(outputStream* out, bool print_contents = false);
 };
 
-//////////////////// HeapRegionLinkedListIterator ////////////////////
-
 // Iterator class that provides a convenient way to iterate over the
 // regions of a HeapRegionLinkedList instance.
 
-class HeapRegionLinkedListIterator : public StackObj {
+class FreeRegionListIterator : public StackObj {
 private:
-  HeapRegionLinkedList* _list;
-  HeapRegion*           _curr;
+  FreeRegionList* _list;
+  HeapRegion*     _curr;
 
 public:
   bool more_available() {
@@ -369,13 +318,12 @@
     // do the "cycle" check.
 
     HeapRegion* hr = _curr;
-    assert(_list->verify_region(hr, _list), "region verification");
+    _list->verify_region(hr);
     _curr = hr->next();
     return hr;
   }
 
-  HeapRegionLinkedListIterator(HeapRegionLinkedList* list)
-    : _curr(NULL), _list(list) {
+  FreeRegionListIterator(FreeRegionList* list) : _curr(NULL), _list(list) {
     _curr = list->head();
   }
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -27,116 +27,110 @@
 
 #include "gc_implementation/g1/heapRegionSet.hpp"
 
-//////////////////// HeapRegionSetBase ////////////////////
-
-inline void HeapRegionSetBase::update_for_addition(HeapRegion* hr) {
-  // Assumes the caller has already verified the region.
-
-  _length           += 1;
-  _region_num       += hr->region_num();
-  _total_used_bytes += hr->used();
-}
-
-inline void HeapRegionSetBase::add_internal(HeapRegion* hr) {
-  hrs_assert_region_ok(this, hr, NULL);
+inline void HeapRegionSetBase::add(HeapRegion* hr) {
+  check_mt_safety();
+  assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u"));
   assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked"));
 
-  update_for_addition(hr);
+  _count.increment(1u, hr->capacity());
   hr->set_containing_set(this);
+  verify_region(hr);
 }
 
-inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) {
-  // Assumes the caller has already verified the region.
-  assert(_length > 0, hrs_ext_msg(this, "pre-condition"));
-  _length -= 1;
-
-  uint region_num_diff = hr->region_num();
-  assert(region_num_diff <= _region_num,
-         hrs_err_msg("[%s] region's region num: %u "
-                     "should be <= region num: %u",
-                     name(), region_num_diff, _region_num));
-  _region_num -= region_num_diff;
-
-  size_t used_bytes = hr->used();
-  assert(used_bytes <= _total_used_bytes,
-         hrs_err_msg("[%s] region's used bytes: "SIZE_FORMAT" "
-                     "should be <= used bytes: "SIZE_FORMAT,
-                     name(), used_bytes, _total_used_bytes));
-  _total_used_bytes -= used_bytes;
-}
-
-inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) {
-  hrs_assert_region_ok(this, hr, this);
+inline void HeapRegionSetBase::remove(HeapRegion* hr) {
+  check_mt_safety();
+  verify_region(hr);
   assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked"));
 
   hr->set_containing_set(NULL);
-  update_for_removal(hr);
-}
-
-//////////////////// HeapRegionSet ////////////////////
-
-inline void HeapRegionSet::add(HeapRegion* hr) {
-  hrs_assert_mt_safety_ok(this);
-  // add_internal() will verify the region.
-  add_internal(hr);
-}
-
-inline void HeapRegionSet::remove(HeapRegion* hr) {
-  hrs_assert_mt_safety_ok(this);
-  // remove_internal() will verify the region.
-  remove_internal(hr);
+  assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition"));
+  _count.decrement(1u, hr->capacity());
 }
 
-inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr,
-                                             HeapRegionSet* proxy_set) {
-  // No need to fo the MT safety check here given that this method
-  // does not update the contents of the set but instead accumulates
-  // the changes in proxy_set which is assumed to be thread-local.
-  hrs_assert_sets_match(this, proxy_set);
-  hrs_assert_region_ok(this, hr, this);
-
-  hr->set_containing_set(NULL);
-  proxy_set->update_for_addition(hr);
-}
-
-//////////////////// HeapRegionLinkedList ////////////////////
-
-inline void HeapRegionLinkedList::add_as_head(HeapRegion* hr) {
-  hrs_assert_mt_safety_ok(this);
+inline void FreeRegionList::add_ordered(HeapRegion* hr) {
+  check_mt_safety();
   assert((length() == 0 && _head == NULL && _tail == NULL) ||
          (length() >  0 && _head != NULL && _tail != NULL),
          hrs_ext_msg(this, "invariant"));
-  // add_internal() will verify the region.
-  add_internal(hr);
+  // add() will verify the region and check mt safety.
+  add(hr);
+
+  // Now link the region
+  if (_head != NULL) {
+    HeapRegion* curr;
+
+    if (_last != NULL && _last->hrs_index() < hr->hrs_index()) {
+      curr = _last;
+    } else {
+      curr = _head;
+    }
+
+    // Find first entry with a Region Index larger than entry to insert.
+    while (curr != NULL && curr->hrs_index() < hr->hrs_index()) {
+      curr = curr->next();
+    }
+
+    hr->set_next(curr);
+
+    if (curr == NULL) {
+      // Adding at the end
+      hr->set_prev(_tail);
+      _tail->set_next(hr);
+      _tail = hr;
+    } else if (curr->prev() == NULL) {
+      // Adding at the beginning
+      hr->set_prev(NULL);
+      _head = hr;
+      curr->set_prev(hr);
+    } else {
+      hr->set_prev(curr->prev());
+      hr->prev()->set_next(hr);
+      curr->set_prev(hr);
+    }
+  } else {
+    // The list was empty
+    _tail = hr;
+    _head = hr;
+  }
+  _last = hr;
+}
+
+inline void FreeRegionList::add_as_head(HeapRegion* hr) {
+  assert((length() == 0 && _head == NULL && _tail == NULL) ||
+         (length() >  0 && _head != NULL && _tail != NULL),
+         hrs_ext_msg(this, "invariant"));
+  // add() will verify the region and check mt safety.
+  add(hr);
 
   // Now link the region.
   if (_head != NULL) {
     hr->set_next(_head);
+    _head->set_prev(hr);
   } else {
     _tail = hr;
   }
   _head = hr;
 }
 
-inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) {
-  hrs_assert_mt_safety_ok(this);
+inline void FreeRegionList::add_as_tail(HeapRegion* hr) {
+  check_mt_safety();
   assert((length() == 0 && _head == NULL && _tail == NULL) ||
          (length() >  0 && _head != NULL && _tail != NULL),
          hrs_ext_msg(this, "invariant"));
-  // add_internal() will verify the region.
-  add_internal(hr);
+  // add() will verify the region and check mt safety.
+  add(hr);
 
   // Now link the region.
   if (_tail != NULL) {
     _tail->set_next(hr);
+    hr->set_prev(_tail);
   } else {
     _head = hr;
   }
   _tail = hr;
 }
 
-inline HeapRegion* HeapRegionLinkedList::remove_head() {
-  hrs_assert_mt_safety_ok(this);
+inline HeapRegion* FreeRegionList::remove_head() {
   assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty"));
   assert(length() > 0 && _head != NULL && _tail != NULL,
          hrs_ext_msg(this, "invariant"));
@@ -146,17 +140,22 @@
   _head = hr->next();
   if (_head == NULL) {
     _tail = NULL;
+  } else {
+    _head->set_prev(NULL);
   }
   hr->set_next(NULL);
 
-  // remove_internal() will verify the region.
-  remove_internal(hr);
+  if (_last == hr) {
+    _last = NULL;
+  }
+
+  // remove() will verify the region and check mt safety.
+  remove(hr);
   return hr;
 }
 
-inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() {
-  hrs_assert_mt_safety_ok(this);
-
+inline HeapRegion* FreeRegionList::remove_head_or_null() {
+  check_mt_safety();
   if (!is_empty()) {
     return remove_head();
   } else {
@@ -164,4 +163,47 @@
   }
 }
 
+inline HeapRegion* FreeRegionList::remove_tail() {
+  assert(!is_empty(), hrs_ext_msg(this, "The list should not be empty"));
+  assert(length() > 0 && _head != NULL && _tail != NULL,
+         hrs_ext_msg(this, "invariant"));
+
+  // We need to unlink it first
+  HeapRegion* hr = _tail;
+
+  _tail = hr->prev();
+  if (_tail == NULL) {
+    _head = NULL;
+  } else {
+    _tail->set_next(NULL);
+  }
+  hr->set_prev(NULL);
+
+  if (_last == hr) {
+    _last = NULL;
+  }
+
+  // remove() will verify the region and check mt safety.
+  remove(hr);
+  return hr;
+}
+
+inline HeapRegion* FreeRegionList::remove_tail_or_null() {
+  check_mt_safety();
+
+  if (!is_empty()) {
+    return remove_tail();
+  } else {
+    return NULL;
+  }
+}
+
+inline HeapRegion* FreeRegionList::remove_region(bool from_head) {
+  if (from_head) {
+    return remove_head_or_null();
+  } else {
+    return remove_tail_or_null();
+  }
+}
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 "gc_implementation/g1/heapRegionRemSet.hpp"
-#include "gc_implementation/g1/heapRegionSets.hpp"
-
-// Note on the check_mt_safety() methods below:
-//
-// Verification of the "master" heap region sets / lists that are
-// maintained by G1CollectedHeap is always done during a STW pause and
-// by the VM thread at the start / end of the pause. The standard
-// verification methods all assert check_mt_safety(). This is
-// important as it ensures that verification is done without
-// concurrent updates taking place at the same time. It follows, that,
-// for the "master" heap region sets / lists, the check_mt_safety()
-// method should include the VM thread / STW case.
-
-//////////////////// FreeRegionList ////////////////////
-
-const char* FreeRegionList::verify_region_extra(HeapRegion* hr) {
-  if (hr->is_young()) {
-    return "the region should not be young";
-  }
-  // The superclass will check that the region is empty and
-  // not humongous.
-  return HeapRegionLinkedList::verify_region_extra(hr);
-}
-
-//////////////////// MasterFreeRegionList ////////////////////
-
-const char* MasterFreeRegionList::verify_region_extra(HeapRegion* hr) {
-  // We should reset the RSet for parallel iteration before we add it
-  // to the master free list so that it is ready when the region is
-  // re-allocated.
-  if (!hr->rem_set()->verify_ready_for_par_iteration()) {
-    return "the region's RSet should be ready for parallel iteration";
-  }
-  return FreeRegionList::verify_region_extra(hr);
-}
-
-bool MasterFreeRegionList::check_mt_safety() {
-  // Master Free List MT safety protocol:
-  // (a) If we're at a safepoint, operations on the master free list
-  // should be invoked by either the VM thread (which will serialize
-  // them) or by the GC workers while holding the
-  // FreeList_lock.
-  // (b) If we're not at a safepoint, operations on the master free
-  // list should be invoked while holding the Heap_lock.
-
-  if (SafepointSynchronize::is_at_safepoint()) {
-    guarantee(Thread::current()->is_VM_thread() ||
-              FreeList_lock->owned_by_self(),
-              hrs_ext_msg(this, "master free list MT safety protocol "
-                                "at a safepoint"));
-  } else {
-    guarantee(Heap_lock->owned_by_self(),
-              hrs_ext_msg(this, "master free list MT safety protocol "
-                                "outside a safepoint"));
-  }
-
-  return FreeRegionList::check_mt_safety();
-}
-
-//////////////////// SecondaryFreeRegionList ////////////////////
-
-bool SecondaryFreeRegionList::check_mt_safety() {
-  // Secondary Free List MT safety protocol:
-  // Operations on the secondary free list should always be invoked
-  // while holding the SecondaryFreeList_lock.
-
-  guarantee(SecondaryFreeList_lock->owned_by_self(),
-            hrs_ext_msg(this, "secondary free list MT safety protocol"));
-
-  return FreeRegionList::check_mt_safety();
-}
-
-//////////////////// OldRegionSet ////////////////////
-
-const char* OldRegionSet::verify_region_extra(HeapRegion* hr) {
-  if (hr->is_young()) {
-    return "the region should not be young";
-  }
-  // The superclass will check that the region is not empty and not
-  // humongous.
-  return HeapRegionSet::verify_region_extra(hr);
-}
-
-//////////////////// MasterOldRegionSet ////////////////////
-
-bool MasterOldRegionSet::check_mt_safety() {
-  // Master Old Set MT safety protocol:
-  // (a) If we're at a safepoint, operations on the master old set
-  // should be invoked:
-  // - by the VM thread (which will serialize them), or
-  // - by the GC workers while holding the FreeList_lock, if we're
-  //   at a safepoint for an evacuation pause (this lock is taken
-  //   anyway when an GC alloc region is retired so that a new one
-  //   is allocated from the free list), or
-  // - by the GC workers while holding the OldSets_lock, if we're at a
-  //   safepoint for a cleanup pause.
-  // (b) If we're not at a safepoint, operations on the master old set
-  // should be invoked while holding the Heap_lock.
-
-  if (SafepointSynchronize::is_at_safepoint()) {
-    guarantee(Thread::current()->is_VM_thread() ||
-              _phase == HRSPhaseEvacuation && FreeList_lock->owned_by_self() ||
-              _phase == HRSPhaseCleanup && OldSets_lock->owned_by_self(),
-              hrs_ext_msg(this, "master old set MT safety protocol "
-                                "at a safepoint"));
-  } else {
-    guarantee(Heap_lock->owned_by_self(),
-              hrs_ext_msg(this, "master old set MT safety protocol "
-                                "outside a safepoint"));
-  }
-
-  return OldRegionSet::check_mt_safety();
-}
-
-//////////////////// HumongousRegionSet ////////////////////
-
-const char* HumongousRegionSet::verify_region_extra(HeapRegion* hr) {
-  if (hr->is_young()) {
-    return "the region should not be young";
-  }
-  // The superclass will check that the region is not empty and
-  // humongous.
-  return HeapRegionSet::verify_region_extra(hr);
-}
-
-//////////////////// MasterHumongousRegionSet ////////////////////
-
-bool MasterHumongousRegionSet::check_mt_safety() {
-  // Master Humongous Set MT safety protocol:
-  // (a) If we're at a safepoint, operations on the master humongous
-  // set should be invoked by either the VM thread (which will
-  // serialize them) or by the GC workers while holding the
-  // OldSets_lock.
-  // (b) If we're not at a safepoint, operations on the master
-  // humongous set should be invoked while holding the Heap_lock.
-
-  if (SafepointSynchronize::is_at_safepoint()) {
-    guarantee(Thread::current()->is_VM_thread() ||
-              OldSets_lock->owned_by_self(),
-              hrs_ext_msg(this, "master humongous set MT safety protocol "
-                                "at a safepoint"));
-  } else {
-    guarantee(Heap_lock->owned_by_self(),
-              hrs_ext_msg(this, "master humongous set MT safety protocol "
-                                "outside a safepoint"));
-  }
-
-  return HumongousRegionSet::check_mt_safety();
-}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
-
-#include "gc_implementation/g1/heapRegionSet.inline.hpp"
-
-//////////////////// FreeRegionList ////////////////////
-
-class FreeRegionList : public HeapRegionLinkedList {
-protected:
-  virtual const char* verify_region_extra(HeapRegion* hr);
-
-  virtual bool regions_humongous() { return false; }
-  virtual bool regions_empty()     { return true;  }
-
-public:
-  FreeRegionList(const char* name) : HeapRegionLinkedList(name) { }
-};
-
-//////////////////// MasterFreeRegionList ////////////////////
-
-class MasterFreeRegionList : public FreeRegionList {
-protected:
-  virtual const char* verify_region_extra(HeapRegion* hr);
-  virtual bool check_mt_safety();
-
-public:
-  MasterFreeRegionList(const char* name) : FreeRegionList(name) { }
-};
-
-//////////////////// SecondaryFreeRegionList ////////////////////
-
-class SecondaryFreeRegionList : public FreeRegionList {
-protected:
-  virtual bool check_mt_safety();
-
-public:
-  SecondaryFreeRegionList(const char* name) : FreeRegionList(name) { }
-};
-
-//////////////////// OldRegionSet ////////////////////
-
-class OldRegionSet : public HeapRegionSet {
-protected:
-  virtual const char* verify_region_extra(HeapRegion* hr);
-
-  virtual bool regions_humongous() { return false; }
-  virtual bool regions_empty()     { return false; }
-
-public:
-  OldRegionSet(const char* name) : HeapRegionSet(name) { }
-};
-
-//////////////////// MasterOldRegionSet ////////////////////
-
-class MasterOldRegionSet : public OldRegionSet {
-private:
-protected:
-  virtual bool check_mt_safety();
-
-public:
-  MasterOldRegionSet(const char* name) : OldRegionSet(name) { }
-};
-
-//////////////////// HumongousRegionSet ////////////////////
-
-class HumongousRegionSet : public HeapRegionSet {
-protected:
-  virtual const char* verify_region_extra(HeapRegion* hr);
-
-  virtual bool regions_humongous() { return true;  }
-  virtual bool regions_empty()     { return false; }
-
-public:
-  HumongousRegionSet(const char* name) : HeapRegionSet(name) { }
-};
-
-//////////////////// MasterHumongousRegionSet ////////////////////
-
-class MasterHumongousRegionSet : public HumongousRegionSet {
-protected:
-  virtual bool check_mt_safety();
-
-public:
-  MasterHumongousRegionSet(const char* name) : HumongousRegionSet(name) { }
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
 
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "memory/allocation.hpp"
 #include "memory/cardTableModRefBS.hpp"
--- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -57,9 +57,10 @@
   nonstatic_field(G1MonitoringSupport, _old_committed,      size_t)           \
   nonstatic_field(G1MonitoringSupport, _old_used,           size_t)           \
                                                                               \
-  nonstatic_field(HeapRegionSetBase,   _length,             uint)             \
-  nonstatic_field(HeapRegionSetBase,   _region_num,         uint)             \
-  nonstatic_field(HeapRegionSetBase,   _total_used_bytes,   size_t)           \
+  nonstatic_field(HeapRegionSetBase,   _count,          HeapRegionSetCount)   \
+                                                                              \
+  nonstatic_field(HeapRegionSetCount,  _length,         uint)                 \
+  nonstatic_field(HeapRegionSetCount,  _capacity,       size_t)               \
 
 
 #define VM_TYPES_G1(declare_type, declare_toplevel_type)                      \
@@ -71,6 +72,7 @@
   declare_type(HeapRegion, ContiguousSpace)                                   \
   declare_toplevel_type(HeapRegionSeq)                                        \
   declare_toplevel_type(HeapRegionSetBase)                                    \
+  declare_toplevel_type(HeapRegionSetCount)                                   \
   declare_toplevel_type(G1MonitoringSupport)                                  \
                                                                               \
   declare_toplevel_type(G1CollectedHeap*)                                     \
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -665,8 +665,10 @@
 
 void ParallelScavengeHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) {
   const PSHeapSummary& heap_summary = create_ps_heap_summary();
+  gc_tracer->report_gc_heap_summary(when, heap_summary);
+
   const MetaspaceSummary& metaspace_summary = create_metaspace_summary();
-  gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary);
+  gc_tracer->report_metaspace_summary(when, metaspace_summary);
 }
 
 ParallelScavengeHeap* ParallelScavengeHeap::heap() {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -550,7 +550,8 @@
 
        if (PrintTenuringDistribution) {
          gclog_or_tty->cr();
-         gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)",
+         gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold "
+                                UINTX_FORMAT " (max threshold " UINTX_FORMAT ")",
                                 size_policy->calculated_survivor_size_in_bytes(),
                                 _tenuring_threshold, MaxTenuringThreshold);
        }
@@ -829,10 +830,10 @@
 void PSScavenge::initialize() {
   // Arguments must have been parsed
 
-  if (AlwaysTenure) {
-    _tenuring_threshold = 0;
-  } else if (NeverTenure) {
-    _tenuring_threshold = markOopDesc::max_age + 1;
+  if (AlwaysTenure || NeverTenure) {
+    assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1,
+        err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold));
+    _tenuring_threshold = MaxTenuringThreshold;
   } else {
     // We want to smooth out our startup times for the AdaptiveSizePolicy
     _tenuring_threshold = (UseAdaptiveSizePolicy) ? InitialTenuringThreshold :
--- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -80,28 +80,37 @@
 
 uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
   size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
-  size_t total = 0;
-  uint age = 1;
-  assert(sizes[0] == 0, "no objects with age zero should be recorded");
-  while (age < table_size) {
-    total += sizes[age];
-    // check if including objects of age 'age' made us pass the desired
-    // size, if so 'age' is the new threshold
-    if (total > desired_survivor_size) break;
-    age++;
+  uint result;
+
+  if (AlwaysTenure || NeverTenure) {
+    assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1,
+        err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold));
+    result = MaxTenuringThreshold;
+  } else {
+    size_t total = 0;
+    uint age = 1;
+    assert(sizes[0] == 0, "no objects with age zero should be recorded");
+    while (age < table_size) {
+      total += sizes[age];
+      // check if including objects of age 'age' made us pass the desired
+      // size, if so 'age' is the new threshold
+      if (total > desired_survivor_size) break;
+      age++;
+    }
+    result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
   }
-  uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
 
   if (PrintTenuringDistribution || UsePerfData) {
 
     if (PrintTenuringDistribution) {
       gclog_or_tty->cr();
-      gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)",
+      gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold "
+        UINTX_FORMAT " (max threshold " UINTX_FORMAT ")",
         desired_survivor_size*oopSize, result, MaxTenuringThreshold);
     }
 
-    total = 0;
-    age = 1;
+    size_t total = 0;
+    uint age = 1;
     while (age < table_size) {
       total += sizes[age];
       if (sizes[age] > 0) {
--- a/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP
 
 #include "memory/allocation.hpp"
+#include "memory/metaspaceChunkFreeListSummary.hpp"
 
 class VirtualSpaceSummary : public StackObj {
   HeapWord* _start;
@@ -125,18 +126,49 @@
 };
 
 class MetaspaceSummary : public StackObj {
+  size_t _capacity_until_GC;
   MetaspaceSizes _meta_space;
   MetaspaceSizes _data_space;
   MetaspaceSizes _class_space;
+  MetaspaceChunkFreeListSummary _metaspace_chunk_free_list_summary;
+  MetaspaceChunkFreeListSummary _class_chunk_free_list_summary;
 
  public:
-  MetaspaceSummary() : _meta_space(), _data_space(), _class_space() {}
-  MetaspaceSummary(const MetaspaceSizes& meta_space, const MetaspaceSizes& data_space, const MetaspaceSizes& class_space) :
-       _meta_space(meta_space), _data_space(data_space), _class_space(class_space) { }
+  MetaspaceSummary() :
+    _capacity_until_GC(0),
+    _meta_space(),
+    _data_space(),
+    _class_space(),
+    _metaspace_chunk_free_list_summary(),
+    _class_chunk_free_list_summary()
+  {}
+  MetaspaceSummary(size_t capacity_until_GC,
+                   const MetaspaceSizes& meta_space,
+                   const MetaspaceSizes& data_space,
+                   const MetaspaceSizes& class_space,
+                   const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary,
+                   const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary) :
+    _capacity_until_GC(capacity_until_GC),
+    _meta_space(meta_space),
+    _data_space(data_space),
+    _class_space(class_space),
+    _metaspace_chunk_free_list_summary(metaspace_chunk_free_list_summary),
+    _class_chunk_free_list_summary(class_chunk_free_list_summary)
+  {}
 
+  size_t capacity_until_GC() const { return _capacity_until_GC; }
   const MetaspaceSizes& meta_space() const { return _meta_space; }
   const MetaspaceSizes& data_space() const { return _data_space; }
   const MetaspaceSizes& class_space() const { return _class_space; }
+
+  const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary() const {
+    return _metaspace_chunk_free_list_summary;
+  }
+
+  const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary() const {
+    return _class_chunk_free_list_summary;
+  }
+
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -139,11 +139,21 @@
 }
 #endif // INCLUDE_SERVICES
 
-void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const {
+void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const {
   assert_set_gc_id();
 
   send_gc_heap_summary_event(when, heap_summary);
-  send_meta_space_summary_event(when, meta_space_summary);
+}
+
+void GCTracer::report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& summary) const {
+  assert_set_gc_id();
+
+  send_meta_space_summary_event(when, summary);
+
+  send_metaspace_chunk_free_list_summary(when, Metaspace::NonClassType, summary.metaspace_chunk_free_list_summary());
+  if (UseCompressedClassPointers) {
+    send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary());
+  }
 }
 
 void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,6 +30,7 @@
 #include "gc_implementation/shared/gcWhen.hpp"
 #include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "memory/allocation.hpp"
+#include "memory/metaspace.hpp"
 #include "memory/referenceType.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1YCTypes.hpp"
@@ -41,6 +42,7 @@
 
 class EvacuationInfo;
 class GCHeapSummary;
+class MetaspaceChunkFreeListSummary;
 class MetaspaceSummary;
 class PSHeapSummary;
 class ReferenceProcessorStats;
@@ -124,7 +126,8 @@
  public:
   void report_gc_start(GCCause::Cause cause, const Ticks& timestamp);
   void report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions);
-  void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const;
+  void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const;
+  void report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& metaspace_summary) const;
   void report_gc_reference_stats(const ReferenceProcessorStats& rp) const;
   void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN;
   bool has_reported_gc_start() const;
@@ -138,6 +141,7 @@
   void send_garbage_collection_event() const;
   void send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const;
   void send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const;
+  void send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype, const MetaspaceChunkFreeListSummary& summary) const;
   void send_reference_stats_event(ReferenceType type, size_t count) const;
   void send_phase_events(TimePartitions* time_partitions) const;
 };
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -64,6 +64,30 @@
   }
 }
 
+void GCTracer::send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype,
+                                                      const MetaspaceChunkFreeListSummary& summary) const {
+  EventMetaspaceChunkFreeListSummary e;
+  if (e.should_commit()) {
+    e.set_gcId(_shared_gc_info.id());
+    e.set_when(when);
+    e.set_metadataType(mdtype);
+
+    e.set_specializedChunks(summary.num_specialized_chunks());
+    e.set_specializedChunksTotalSize(summary.specialized_chunks_size_in_bytes());
+
+    e.set_smallChunks(summary.num_small_chunks());
+    e.set_smallChunksTotalSize(summary.small_chunks_size_in_bytes());
+
+    e.set_mediumChunks(summary.num_medium_chunks());
+    e.set_mediumChunksTotalSize(summary.medium_chunks_size_in_bytes());
+
+    e.set_humongousChunks(summary.num_humongous_chunks());
+    e.set_humongousChunksTotalSize(summary.humongous_chunks_size_in_bytes());
+
+    e.commit();
+  }
+}
+
 void ParallelOldTracer::send_parallel_old_event() const {
   EventGCParallelOld e(UNTIMED);
   if (e.should_commit()) {
@@ -246,6 +270,7 @@
   if (e.should_commit()) {
     e.set_gcId(_shared_gc_info.id());
     e.set_when((u1) when);
+    e.set_gcThreshold(meta_space_summary.capacity_until_GC());
     e.set_metaspace(to_trace_struct(meta_space_summary.meta_space()));
     e.set_dataSpace(to_trace_struct(meta_space_summary.data_space()));
     e.set_classSpace(to_trace_struct(meta_space_summary.class_space()));
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -30,10 +30,18 @@
 #include "utilities/stack.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #endif // INCLUDE_ALL_GCS
 
 inline void MarkSweep::mark_object(oop obj) {
+#if INCLUDE_ALL_GCS
+  if (G1StringDedup::is_enabled()) {
+    // We must enqueue the object before it is marked
+    // as we otherwise can't read the object's age.
+    G1StringDedup::enqueue_from_mark(obj);
+  }
+#endif
   // some marks may contain information we need to preserve so we store them away
   // and overwrite the mark.  We'll restore it at the end of markSweep.
   markOop mark = obj->mark();
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -89,6 +89,15 @@
   assert(((_gc_cause != GCCause::_no_gc) &&
           (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause");
 
+  // To be able to handle a GC the VM initialization needs to be completed.
+  if (!is_init_completed()) {
+    vm_exit_during_initialization(
+      err_msg("GC triggered before VM initialization completed. Try increasing "
+              "NewSize, current value " UINTX_FORMAT "%s.",
+              byte_size_in_proper_unit(NewSize),
+              proper_unit_for_byte_size(NewSize)));
+  }
+
   acquire_pending_list_lock();
   // If the GC count has changed someone beat us to the collection
   // Get the Heap_lock after the pending_list_lock.
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -97,7 +97,13 @@
       MetaspaceAux::allocated_used_bytes(Metaspace::ClassType),
       MetaspaceAux::reserved_bytes(Metaspace::ClassType));
 
-  return MetaspaceSummary(meta_space, data_space, class_space);
+  const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary =
+    MetaspaceAux::chunk_free_list_summary(Metaspace::NonClassType);
+  const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary =
+    MetaspaceAux::chunk_free_list_summary(Metaspace::ClassType);
+
+  return MetaspaceSummary(MetaspaceGC::capacity_until_GC(), meta_space, data_space, class_space,
+                          ms_chunk_free_list_summary, class_chunk_free_list_summary);
 }
 
 void CollectedHeap::print_heap_before_gc() {
@@ -128,8 +134,10 @@
 
 void CollectedHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) {
   const GCHeapSummary& heap_summary = create_heap_summary();
+  gc_tracer->report_gc_heap_summary(when, heap_summary);
+
   const MetaspaceSummary& metaspace_summary = create_metaspace_summary();
-  gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary);
+  gc_tracer->report_metaspace_summary(when, metaspace_summary);
 }
 
 void CollectedHeap::trace_heap_before_gc(GCTracer* gc_tracer) {
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -35,8 +35,6 @@
 #include "runtime/timer.hpp"
 
 
-#ifndef PRODUCT
-
 // Standard closure for BytecodeTracer: prints the current bytecode
 // and its attributes using bytecode-specific information.
 
@@ -600,4 +598,3 @@
     }
   }
 }
-#endif // PRODUCT
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -34,8 +34,7 @@
 // By specialising the BytecodeClosure, all kinds of bytecode traces can
 // be done.
 
-#ifndef PRODUCT
-// class BytecodeTracer is only used by TraceBytecodes option
+// class BytecodeTracer is used by TraceBytecodes option and PrintMethodData
 
 class BytecodeClosure;
 class BytecodeTracer: AllStatic {
@@ -60,6 +59,4 @@
   virtual void trace(methodHandle method, address bcp, outputStream* st) = 0;
 };
 
-#endif // !PRODUCT
-
 #endif // SHARE_VM_INTERPRETER_BYTECODETRACER_HPP
--- a/hotspot/src/share/vm/memory/allocation.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -446,6 +446,7 @@
   _first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size);
   _hwm = _chunk->bottom();      // Save the cached hwm, max
   _max = _chunk->top();
+  _size_in_bytes = 0;
   set_size_in_bytes(init_size);
   NOT_PRODUCT(Atomic::inc(&_instance_count);)
 }
@@ -454,6 +455,7 @@
   _first = _chunk = new (AllocFailStrategy::EXIT_OOM, Chunk::init_size) Chunk(Chunk::init_size);
   _hwm = _chunk->bottom();      // Save the cached hwm, max
   _max = _chunk->top();
+  _size_in_bytes = 0;
   set_size_in_bytes(Chunk::init_size);
   NOT_PRODUCT(Atomic::inc(&_instance_count);)
 }
--- a/hotspot/src/share/vm/memory/allocation.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -748,6 +748,12 @@
   bool _use_malloc;
   size_t _size;
   bool _free_in_destructor;
+
+  static bool should_use_malloc(size_t size) {
+    return size < ArrayAllocatorMallocLimit;
+  }
+
+  static char* allocate_inner(size_t& size, bool& use_malloc);
  public:
   ArrayAllocator(bool free_in_destructor = true) :
     _addr(NULL), _use_malloc(false), _size(0), _free_in_destructor(free_in_destructor) { }
@@ -759,6 +765,7 @@
   }
 
   E* allocate(size_t length);
+  E* reallocate(size_t new_length);
   void free();
 };
 
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -122,35 +122,57 @@
 }
 
 template <class E, MEMFLAGS F>
+char* ArrayAllocator<E, F>::allocate_inner(size_t &size, bool &use_malloc) {
+  char* addr = NULL;
+
+  if (use_malloc) {
+    addr = AllocateHeap(size, F);
+    if (addr == NULL && size >= (size_t)os::vm_allocation_granularity()) {
+      // malloc failed let's try with mmap instead
+      use_malloc = false;
+    } else {
+      return addr;
+    }
+  }
+
+  int alignment = os::vm_allocation_granularity();
+  size = align_size_up(size, alignment);
+
+  addr = os::reserve_memory(size, NULL, alignment, F);
+  if (addr == NULL) {
+    vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)");
+  }
+
+  os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)");
+  return addr;
+}
+
+template <class E, MEMFLAGS F>
 E* ArrayAllocator<E, F>::allocate(size_t length) {
   assert(_addr == NULL, "Already in use");
 
   _size = sizeof(E) * length;
-  _use_malloc = _size < ArrayAllocatorMallocLimit;
-
-  if (_use_malloc) {
-    _addr = AllocateHeap(_size, F);
-    if (_addr == NULL && _size >=  (size_t)os::vm_allocation_granularity()) {
-      // malloc failed let's try with mmap instead
-      _use_malloc = false;
-    } else {
-      return (E*)_addr;
-    }
-  }
-
-  int alignment = os::vm_allocation_granularity();
-  _size = align_size_up(_size, alignment);
-
-  _addr = os::reserve_memory(_size, NULL, alignment, F);
-  if (_addr == NULL) {
-    vm_exit_out_of_memory(_size, OOM_MMAP_ERROR, "Allocator (reserve)");
-  }
-
-  os::commit_memory_or_exit(_addr, _size, !ExecMem, "Allocator (commit)");
+  _use_malloc = should_use_malloc(_size);
+  _addr = allocate_inner(_size, _use_malloc);
 
   return (E*)_addr;
 }
 
+template <class E, MEMFLAGS F>
+E* ArrayAllocator<E, F>::reallocate(size_t new_length) {
+  size_t new_size = sizeof(E) * new_length;
+  bool use_malloc = should_use_malloc(new_size);
+  char* new_addr = allocate_inner(new_size, use_malloc);
+
+  memcpy(new_addr, _addr, MIN2(new_size, _size));
+
+  free();
+  _size = new_size;
+  _use_malloc = use_malloc;
+  _addr = new_addr;
+  return (E*)new_addr;
+}
+
 template<class E, MEMFLAGS F>
 void ArrayAllocator<E, F>::free() {
   if (_addr != NULL) {
--- a/hotspot/src/share/vm/memory/filemap.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/filemap.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -32,8 +32,8 @@
 //  header: dump of archive instance plus versioning info, datestamp, etc.
 //   [magic # = 0xF00BABA2]
 //  ... padding to align on page-boundary
-//  read-write space from CompactingPermGenGen
-//  read-only space from CompactingPermGenGen
+//  read-write space
+//  read-only space
 //  misc data (block offset table, string table, symbols, dictionary, etc.)
 //  tag(666)
 
--- a/hotspot/src/share/vm/memory/freeList.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/freeList.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -34,6 +34,7 @@
 
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
 #endif // INCLUDE_ALL_GCS
 
 // Free list.  A FreeList is used to access a linked list of chunks
@@ -332,4 +333,5 @@
 template class FreeList<Metachunk>;
 #if INCLUDE_ALL_GCS
 template class FreeList<FreeChunk>;
+template class FreeList<G1CodeRootChunk>;
 #endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/memory/gcLocker.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/gcLocker.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -28,7 +28,6 @@
 #include "memory/sharedHeap.hpp"
 
 volatile jint GC_locker::_jni_lock_count = 0;
-volatile jint GC_locker::_lock_count     = 0;
 volatile bool GC_locker::_needs_gc       = false;
 volatile bool GC_locker::_doing_gc       = false;
 
@@ -102,7 +101,7 @@
   // We check that at least one thread is in a critical region before
   // blocking because blocked threads are woken up by a thread exiting
   // a JNI critical region.
-  while ((needs_gc() && is_jni_active()) || _doing_gc) {
+  while (is_active_and_needs_gc() || _doing_gc) {
     JNICritical_lock->wait();
   }
   thread->enter_critical();
@@ -116,27 +115,20 @@
   _jni_lock_count--;
   decrement_debug_jni_lock_count();
   thread->exit_critical();
-  if (needs_gc() && !is_jni_active()) {
+  if (needs_gc() && !is_active_internal()) {
     // We're the last thread out. Cause a GC to occur.
-    // GC will also check is_active, so this check is not
-    // strictly needed. It's added here to make it clear that
-    // the GC will NOT be performed if any other caller
-    // of GC_locker::lock() still needs GC locked.
-    if (!is_active_internal()) {
-      _doing_gc = true;
-      {
-        // Must give up the lock while at a safepoint
-        MutexUnlocker munlock(JNICritical_lock);
-        if (PrintJNIGCStalls && PrintGCDetails) {
-          ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
-          gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked",
-                                 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
-        }
-        Universe::heap()->collect(GCCause::_gc_locker);
+    _doing_gc = true;
+    {
+      // Must give up the lock while at a safepoint
+      MutexUnlocker munlock(JNICritical_lock);
+      if (PrintJNIGCStalls && PrintGCDetails) {
+        ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
+        gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked",
+            gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
       }
-      _doing_gc = false;
+      Universe::heap()->collect(GCCause::_gc_locker);
     }
-
+    _doing_gc = false;
     _needs_gc = false;
     JNICritical_lock->notify_all();
   }
--- a/hotspot/src/share/vm/memory/gcLocker.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/gcLocker.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -54,8 +54,6 @@
   // safepointing and decremented during the slow path of GC_locker
   // unlocking.
   static volatile jint _jni_lock_count;  // number of jni active instances.
-
-  static volatile jint _lock_count;      // number of other active instances
   static volatile bool _needs_gc;        // heap is filling, we need a GC
                                          // note: bool is typedef'd as jint
   static volatile bool _doing_gc;        // unlock_critical() is doing a GC
@@ -66,12 +64,6 @@
   static volatile jint _debug_jni_lock_count;
 #endif
 
-  // Accessors
-  static bool is_jni_active() {
-    assert(_needs_gc, "only valid when _needs_gc is set");
-    return _jni_lock_count > 0;
-  }
-
   // At a safepoint, visit all threads and count the number of active
   // critical sections.  This is used to ensure that all active
   // critical sections are exited before a new one is started.
@@ -82,7 +74,7 @@
 
   static bool is_active_internal() {
     verify_critical_count();
-    return _lock_count > 0 || _jni_lock_count > 0;
+    return _jni_lock_count > 0;
   }
 
  public:
@@ -132,10 +124,6 @@
   // not a stable predicate.
   static void stall_until_clear();
 
-  // Non-structured GC locking: currently needed for JNI. Use with care!
-  static void lock();
-  static void unlock();
-
   // The following two methods are used for JNI critical regions.
   // If we find that we failed to perform a GC because the GC_locker
   // was active, arrange for one as soon as possible by allowing
--- a/hotspot/src/share/vm/memory/gcLocker.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/gcLocker.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,22 +27,6 @@
 
 #include "memory/gcLocker.hpp"
 
-inline void GC_locker::lock() {
-  // cast away volatile
-  Atomic::inc(&_lock_count);
-  CHECK_UNHANDLED_OOPS_ONLY(
-    if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count++; })
-  assert(Universe::heap() == NULL ||
-         !Universe::heap()->is_gc_active(), "locking failed");
-}
-
-inline void GC_locker::unlock() {
-  // cast away volatile
-  Atomic::dec(&_lock_count);
-  CHECK_UNHANDLED_OOPS_ONLY(
-    if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count--; })
-}
-
 inline void GC_locker::lock_critical(JavaThread* thread) {
   if (!thread->in_critical()) {
     if (needs_gc()) {
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -837,12 +837,6 @@
   }
 }
 
-void GenCollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  for (int i = 0; i < _n_gens; i++) {
-    _gens[i]->oop_iterate(mr, cl);
-  }
-}
-
 void GenCollectedHeap::object_iterate(ObjectClosure* cl) {
   for (int i = 0; i < _n_gens; i++) {
     _gens[i]->object_iterate(cl);
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -212,7 +212,6 @@
 
   // Iteration functions.
   void oop_iterate(ExtendedOopClosure* cl);
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void object_iterate(ObjectClosure* cl);
   void safe_object_iterate(ObjectClosure* cl);
   Space* space_containing(const void* addr) const;
--- a/hotspot/src/share/vm/memory/genOopClosures.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/genOopClosures.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -115,9 +115,6 @@
   virtual void do_oop(narrowOop* p);
   inline void do_oop_nv(oop* p);
   inline void do_oop_nv(narrowOop* p);
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_write;
-  }
 };
 
 // Closure for scanning DefNewGeneration.
@@ -137,9 +134,6 @@
   virtual void do_oop(narrowOop* p);
   inline void do_oop_nv(oop* p);
   inline void do_oop_nv(narrowOop* p);
-  Prefetch::style prefetch_style() {
-    return Prefetch::do_write;
-  }
 };
 
 class KlassScanClosure: public KlassClosure {
--- a/hotspot/src/share/vm/memory/generation.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/generation.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -295,22 +295,16 @@
 
 class GenerationOopIterateClosure : public SpaceClosure {
  public:
-  ExtendedOopClosure* cl;
-  MemRegion mr;
+  ExtendedOopClosure* _cl;
   virtual void do_space(Space* s) {
-    s->oop_iterate(mr, cl);
+    s->oop_iterate(_cl);
   }
-  GenerationOopIterateClosure(ExtendedOopClosure* _cl, MemRegion _mr) :
-    cl(_cl), mr(_mr) {}
+  GenerationOopIterateClosure(ExtendedOopClosure* cl) :
+    _cl(cl) {}
 };
 
 void Generation::oop_iterate(ExtendedOopClosure* cl) {
-  GenerationOopIterateClosure blk(cl, _reserved);
-  space_iterate(&blk);
-}
-
-void Generation::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  GenerationOopIterateClosure blk(cl, mr);
+  GenerationOopIterateClosure blk(cl);
   space_iterate(&blk);
 }
 
--- a/hotspot/src/share/vm/memory/generation.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/generation.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -543,10 +543,6 @@
   // generation, calling "cl.do_oop" on each.
   virtual void oop_iterate(ExtendedOopClosure* cl);
 
-  // Same as above, restricted to the intersection of a memory region and
-  // the generation.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
-
   // Iterate over all objects in the generation, calling "cl.do_object" on
   // each.
   virtual void object_iterate(ObjectClosure* cl);
--- a/hotspot/src/share/vm/memory/iterator.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/iterator.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,11 +27,8 @@
 
 #include "memory/allocation.hpp"
 #include "memory/memRegion.hpp"
-#include "runtime/prefetch.hpp"
 #include "utilities/top.hpp"
 
-// The following classes are C++ `closures` for iterating over objects, roots and spaces
-
 class CodeBlob;
 class nmethod;
 class ReferenceProcessor;
@@ -39,22 +36,11 @@
 class KlassClosure;
 class ClassLoaderData;
 
-// Closure provides abortability.
+// The following classes are C++ `closures` for iterating over objects, roots and spaces
 
-class Closure : public StackObj {
- protected:
-  bool _abort;
-  void set_abort() { _abort = true; }
- public:
-  Closure() : _abort(false) {}
-  // A subtype can use this mechanism to indicate to some iterator mapping
-  // functions that the iteration should cease.
-  bool abort() { return _abort; }
-  void clear_abort() { _abort = false; }
-};
+class Closure : public StackObj { };
 
 // OopClosure is used for iterating through references to Java objects.
-
 class OopClosure : public Closure {
  public:
   virtual void do_oop(oop* o) = 0;
@@ -97,11 +83,6 @@
 
   virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); }
 
-  // Controls how prefetching is done for invocations of this closure.
-  Prefetch::style prefetch_style() { // Note that this is non-virtual.
-    return Prefetch::do_none;
-  }
-
   // True iff this closure may be safely applied more than once to an oop
   // location without an intervening "major reset" (like the end of a GC).
   virtual bool idempotent() { return false; }
@@ -177,19 +158,6 @@
   ObjectToOopClosure(ExtendedOopClosure* cl) : _cl(cl) {}
 };
 
-// A version of ObjectClosure with "memory" (see _previous_address below)
-class UpwardsObjectClosure: public BoolObjectClosure {
-  HeapWord* _previous_address;
- public:
-  UpwardsObjectClosure() : _previous_address(NULL) { }
-  void set_previous(HeapWord* addr) { _previous_address = addr; }
-  HeapWord* previous()              { return _previous_address; }
-  // A return value of "true" can be used by the caller to decide
-  // if this object's end should *NOT* be recorded in
-  // _previous_address above.
-  virtual bool do_object_bm(oop obj, MemRegion mr) = 0;
-};
-
 // A version of ObjectClosure that is expected to be robust
 // in the face of possibly uninitialized objects.
 class ObjectClosureCareful : public ObjectClosure {
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -32,7 +32,9 @@
 #include "memory/gcLocker.hpp"
 #include "memory/metachunk.hpp"
 #include "memory/metaspace.hpp"
+#include "memory/metaspaceGCThresholdUpdater.hpp"
 #include "memory/metaspaceShared.hpp"
+#include "memory/metaspaceTracer.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "runtime/atomic.inline.hpp"
@@ -57,6 +59,7 @@
 MetaWord* last_allocated = 0;
 
 size_t Metaspace::_compressed_class_space_size;
+const MetaspaceTracer* Metaspace::_tracer = NULL;
 
 // Used in declarations in SpaceManager and ChunkManager
 enum ChunkIndex {
@@ -182,6 +185,48 @@
   // Remove from a list by size.  Selects list based on size of chunk.
   Metachunk* free_chunks_get(size_t chunk_word_size);
 
+#define index_bounds_check(index)                                         \
+  assert(index == SpecializedIndex ||                                     \
+         index == SmallIndex ||                                           \
+         index == MediumIndex ||                                          \
+         index == HumongousIndex, err_msg("Bad index: %d", (int) index))
+
+  size_t num_free_chunks(ChunkIndex index) const {
+    index_bounds_check(index);
+
+    if (index == HumongousIndex) {
+      return _humongous_dictionary.total_free_blocks();
+    }
+
+    ssize_t count = _free_chunks[index].count();
+    return count == -1 ? 0 : (size_t) count;
+  }
+
+  size_t size_free_chunks_in_bytes(ChunkIndex index) const {
+    index_bounds_check(index);
+
+    size_t word_size = 0;
+    if (index == HumongousIndex) {
+      word_size = _humongous_dictionary.total_size();
+    } else {
+      const size_t size_per_chunk_in_words = _free_chunks[index].size();
+      word_size = size_per_chunk_in_words * num_free_chunks(index);
+    }
+
+    return word_size * BytesPerWord;
+  }
+
+  MetaspaceChunkFreeListSummary chunk_free_list_summary() const {
+    return MetaspaceChunkFreeListSummary(num_free_chunks(SpecializedIndex),
+                                         num_free_chunks(SmallIndex),
+                                         num_free_chunks(MediumIndex),
+                                         num_free_chunks(HumongousIndex),
+                                         size_free_chunks_in_bytes(SpecializedIndex),
+                                         size_free_chunks_in_bytes(SmallIndex),
+                                         size_free_chunks_in_bytes(MediumIndex),
+                                         size_free_chunks_in_bytes(HumongousIndex));
+  }
+
   // Debug support
   void verify();
   void slow_verify() {
@@ -1436,19 +1481,21 @@
     expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment());
     // Don't expand unless it's significant
     if (expand_bytes >= MinMetaspaceExpansion) {
-      MetaspaceGC::inc_capacity_until_GC(expand_bytes);
-    }
-    if (PrintGCDetails && Verbose) {
-      size_t new_capacity_until_GC = capacity_until_GC;
-      gclog_or_tty->print_cr("    expanding:"
-                    "  minimum_desired_capacity: %6.1fKB"
-                    "  expand_bytes: %6.1fKB"
-                    "  MinMetaspaceExpansion: %6.1fKB"
-                    "  new metaspace HWM:  %6.1fKB",
-                    minimum_desired_capacity / (double) K,
-                    expand_bytes / (double) K,
-                    MinMetaspaceExpansion / (double) K,
-                    new_capacity_until_GC / (double) K);
+      size_t new_capacity_until_GC = MetaspaceGC::inc_capacity_until_GC(expand_bytes);
+      Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
+                                               new_capacity_until_GC,
+                                               MetaspaceGCThresholdUpdater::ComputeNewSize);
+      if (PrintGCDetails && Verbose) {
+        gclog_or_tty->print_cr("    expanding:"
+                      "  minimum_desired_capacity: %6.1fKB"
+                      "  expand_bytes: %6.1fKB"
+                      "  MinMetaspaceExpansion: %6.1fKB"
+                      "  new metaspace HWM:  %6.1fKB",
+                      minimum_desired_capacity / (double) K,
+                      expand_bytes / (double) K,
+                      MinMetaspaceExpansion / (double) K,
+                      new_capacity_until_GC / (double) K);
+      }
     }
     return;
   }
@@ -1528,7 +1575,10 @@
   // Don't shrink unless it's significant
   if (shrink_bytes >= MinMetaspaceExpansion &&
       ((capacity_until_GC - shrink_bytes) >= MetaspaceSize)) {
-    MetaspaceGC::dec_capacity_until_GC(shrink_bytes);
+    size_t new_capacity_until_GC = MetaspaceGC::dec_capacity_until_GC(shrink_bytes);
+    Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
+                                             new_capacity_until_GC,
+                                             MetaspaceGCThresholdUpdater::ComputeNewSize);
   }
 }
 
@@ -2629,6 +2679,19 @@
   return free_chunks_total_words() * BytesPerWord;
 }
 
+bool MetaspaceAux::has_chunk_free_list(Metaspace::MetadataType mdtype) {
+  return Metaspace::get_chunk_manager(mdtype) != NULL;
+}
+
+MetaspaceChunkFreeListSummary MetaspaceAux::chunk_free_list_summary(Metaspace::MetadataType mdtype) {
+  if (!has_chunk_free_list(mdtype)) {
+    return MetaspaceChunkFreeListSummary();
+  }
+
+  const ChunkManager* cm = Metaspace::get_chunk_manager(mdtype);
+  return cm->chunk_free_list_summary();
+}
+
 void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) {
   gclog_or_tty->print(", [Metaspace:");
   if (PrintGCDetails && Verbose) {
@@ -3132,6 +3195,7 @@
   }
 
   MetaspaceGC::initialize();
+  _tracer = new MetaspaceTracer();
 }
 
 Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype,
@@ -3220,8 +3284,12 @@
   assert(delta_bytes > 0, "Must be");
 
   size_t after_inc = MetaspaceGC::inc_capacity_until_GC(delta_bytes);
+
+  // capacity_until_GC might be updated concurrently, must calculate previous value.
   size_t before_inc = after_inc - delta_bytes;
 
+  tracer()->report_gc_threshold(before_inc, after_inc,
+                                MetaspaceGCThresholdUpdater::ExpandAndAllocate);
   if (PrintGCDetails && Verbose) {
     gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
         " to " SIZE_FORMAT, before_inc, after_inc);
@@ -3275,37 +3343,22 @@
 }
 
 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
-  if (SafepointSynchronize::is_at_safepoint()) {
-    assert(Thread::current()->is_VM_thread(), "should be the VM thread");
-    // Don't take Heap_lock
-    MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
-    if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
-      // Dark matter.  Too small for dictionary.
+  assert(!SafepointSynchronize::is_at_safepoint()
+         || Thread::current()->is_VM_thread(), "should be the VM thread");
+
+  MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
+
+  if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
+    // Dark matter.  Too small for dictionary.
 #ifdef ASSERT
-      Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
+    Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
 #endif
-      return;
-    }
-    if (is_class && using_class_space()) {
-      class_vsm()->deallocate(ptr, word_size);
-    } else {
-      vsm()->deallocate(ptr, word_size);
-    }
+    return;
+  }
+  if (is_class && using_class_space()) {
+    class_vsm()->deallocate(ptr, word_size);
   } else {
-    MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
-
-    if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
-      // Dark matter.  Too small for dictionary.
-#ifdef ASSERT
-      Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
-#endif
-      return;
-    }
-    if (is_class && using_class_space()) {
-      class_vsm()->deallocate(ptr, word_size);
-    } else {
-      vsm()->deallocate(ptr, word_size);
-    }
+    vsm()->deallocate(ptr, word_size);
   }
 }
 
@@ -3345,6 +3398,8 @@
   MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
 
   if (result == NULL) {
+    tracer()->report_metaspace_allocation_failure(loader_data, word_size, type, mdtype);
+
     // Allocation failed.
     if (is_init_completed()) {
       // Only start a GC if the bootstrapping has completed.
@@ -3356,7 +3411,7 @@
   }
 
   if (result == NULL) {
-    report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
+    report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
   }
 
   // Zero initialize.
@@ -3370,7 +3425,9 @@
   return class_vsm()->calc_chunk_size(word_size);
 }
 
-void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) {
+void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetaspaceObj::Type type, MetadataType mdtype, TRAPS) {
+  tracer()->report_metadata_oom(loader_data, word_size, type, mdtype);
+
   // If result is still null, we are out of memory.
   if (Verbose && TraceMetadataChunkAllocation) {
     gclog_or_tty->print_cr("Metaspace allocation failed for size "
@@ -3413,6 +3470,16 @@
   }
 }
 
+const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) {
+  switch (mdtype) {
+    case Metaspace::ClassType: return "Class";
+    case Metaspace::NonClassType: return "Metadata";
+    default:
+      assert(false, err_msg("Got bad mdtype: %d", (int) mdtype));
+      return NULL;
+  }
+}
+
 void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) {
   assert(DumpSharedSpaces, "sanity");
 
--- a/hotspot/src/share/vm/memory/metaspace.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -26,6 +26,7 @@
 
 #include "memory/allocation.hpp"
 #include "memory/memRegion.hpp"
+#include "memory/metaspaceChunkFreeListSummary.hpp"
 #include "runtime/virtualspace.hpp"
 #include "utilities/exceptions.hpp"
 
@@ -60,6 +61,7 @@
 class ClassLoaderData;
 class Metablock;
 class Metachunk;
+class MetaspaceTracer;
 class MetaWord;
 class Mutex;
 class outputStream;
@@ -149,6 +151,8 @@
   static ChunkManager* _chunk_manager_metadata;
   static ChunkManager* _chunk_manager_class;
 
+  static const MetaspaceTracer* _tracer;
+
  public:
   static VirtualSpaceList* space_list()       { return _space_list; }
   static VirtualSpaceList* class_space_list() { return _class_space_list; }
@@ -164,6 +168,8 @@
     return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata();
   }
 
+  static const MetaspaceTracer* tracer() { return _tracer; }
+
  private:
   // This is used by DumpSharedSpaces only, where only _vsm is used. So we will
   // maintain a single list for now.
@@ -234,7 +240,9 @@
   static void purge();
 
   static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size,
-                                   MetadataType mdtype, TRAPS);
+                                   MetaspaceObj::Type type, MetadataType mdtype, TRAPS);
+
+  static const char* metadata_type_name(Metaspace::MetadataType mdtype);
 
   void print_on(outputStream* st) const;
   // Debugging support
@@ -348,6 +356,9 @@
     return min_chunk_size_words() * BytesPerWord;
   }
 
+  static bool has_chunk_free_list(Metaspace::MetadataType mdtype);
+  static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype);
+
   // Print change in used metadata.
   static void print_metaspace_change(size_t prev_metadata_used);
   static void print_on(outputStream * out);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+
+#include "memory/allocation.hpp"
+
+class MetaspaceChunkFreeListSummary VALUE_OBJ_CLASS_SPEC {
+  size_t _num_specialized_chunks;
+  size_t _num_small_chunks;
+  size_t _num_medium_chunks;
+  size_t _num_humongous_chunks;
+
+  size_t _specialized_chunks_size_in_bytes;
+  size_t _small_chunks_size_in_bytes;
+  size_t _medium_chunks_size_in_bytes;
+  size_t _humongous_chunks_size_in_bytes;
+
+ public:
+  MetaspaceChunkFreeListSummary() :
+    _num_specialized_chunks(0),
+    _num_small_chunks(0),
+    _num_medium_chunks(0),
+    _num_humongous_chunks(0),
+    _specialized_chunks_size_in_bytes(0),
+    _small_chunks_size_in_bytes(0),
+    _medium_chunks_size_in_bytes(0),
+    _humongous_chunks_size_in_bytes(0)
+  {}
+
+  MetaspaceChunkFreeListSummary(size_t num_specialized_chunks,
+                                size_t num_small_chunks,
+                                size_t num_medium_chunks,
+                                size_t num_humongous_chunks,
+                                size_t specialized_chunks_size_in_bytes,
+                                size_t small_chunks_size_in_bytes,
+                                size_t medium_chunks_size_in_bytes,
+                                size_t humongous_chunks_size_in_bytes) :
+    _num_specialized_chunks(num_specialized_chunks),
+    _num_small_chunks(num_small_chunks),
+    _num_medium_chunks(num_medium_chunks),
+    _num_humongous_chunks(num_humongous_chunks),
+    _specialized_chunks_size_in_bytes(specialized_chunks_size_in_bytes),
+    _small_chunks_size_in_bytes(small_chunks_size_in_bytes),
+    _medium_chunks_size_in_bytes(medium_chunks_size_in_bytes),
+    _humongous_chunks_size_in_bytes(humongous_chunks_size_in_bytes)
+  {}
+
+  size_t num_specialized_chunks() const {
+    return _num_specialized_chunks;
+  }
+
+  size_t num_small_chunks() const {
+    return _num_small_chunks;
+  }
+
+  size_t num_medium_chunks() const {
+    return _num_medium_chunks;
+  }
+
+  size_t num_humongous_chunks() const {
+    return _num_humongous_chunks;
+  }
+
+  size_t specialized_chunks_size_in_bytes() const {
+    return _specialized_chunks_size_in_bytes;
+  }
+
+  size_t small_chunks_size_in_bytes() const {
+    return _small_chunks_size_in_bytes;
+  }
+
+  size_t medium_chunks_size_in_bytes() const {
+    return _medium_chunks_size_in_bytes;
+  }
+
+  size_t humongous_chunks_size_in_bytes() const {
+    return _humongous_chunks_size_in_bytes;
+  }
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+class MetaspaceGCThresholdUpdater : public AllStatic {
+ public:
+  enum Type {
+    ComputeNewSize,
+    ExpandAndAllocate,
+    Last
+  };
+
+  static const char* to_string(MetaspaceGCThresholdUpdater::Type updater) {
+    switch (updater) {
+      case ComputeNewSize:
+        return "compute_new_size";
+      case ExpandAndAllocate:
+        return "expand_and_allocate";
+      default:
+        assert(false, err_msg("Got bad updater: %d", (int) updater));
+        return NULL;
+    };
+  }
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -645,9 +645,6 @@
   TraceTime timer("Dump Shared Spaces", TraceStartupTime);
   ResourceMark rm;
 
-  // Lock out GC - is it necessary? I don't think we care.
-  No_GC_Verifier no_gc;
-
   // Preload classes to be shared.
   // Should use some os:: method rather than fopen() here. aB.
   // Construct the path to the class list (in jre/lib)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 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 "classfile/classLoaderData.hpp"
+#include "memory/metaspaceTracer.hpp"
+#include "oops/oop.inline.hpp"
+#include "trace/tracing.hpp"
+#include "trace/traceBackend.hpp"
+
+void MetaspaceTracer::report_gc_threshold(size_t old_val,
+                                          size_t new_val,
+                                          MetaspaceGCThresholdUpdater::Type updater) const {
+  EventMetaspaceGCThreshold event;
+  if (event.should_commit()) {
+    event.set_oldValue(old_val);
+    event.set_newValue(new_val);
+    event.set_updater((u1)updater);
+    event.commit();
+  }
+}
+
+void MetaspaceTracer::report_metaspace_allocation_failure(ClassLoaderData *cld,
+                                                          size_t word_size,
+                                                          MetaspaceObj::Type objtype,
+                                                          Metaspace::MetadataType mdtype) const {
+  send_allocation_failure_event<EventMetaspaceAllocationFailure>(cld, word_size, objtype, mdtype);
+}
+
+void MetaspaceTracer::report_metadata_oom(ClassLoaderData *cld,
+                                         size_t word_size,
+                                         MetaspaceObj::Type objtype,
+                                         Metaspace::MetadataType mdtype) const {
+  send_allocation_failure_event<EventMetaspaceOOM>(cld, word_size, objtype, mdtype);
+}
+
+template <typename E>
+void MetaspaceTracer::send_allocation_failure_event(ClassLoaderData *cld,
+                                                    size_t word_size,
+                                                    MetaspaceObj::Type objtype,
+                                                    Metaspace::MetadataType mdtype) const {
+  E event;
+  if (event.should_commit()) {
+    if (cld->is_anonymous()) {
+      event.set_classLoader(NULL);
+      event.set_anonymousClassLoader(true);
+    } else {
+      if (cld->is_the_null_class_loader_data()) {
+        event.set_classLoader((Klass*) NULL);
+      } else {
+        event.set_classLoader(cld->class_loader()->klass());
+      }
+      event.set_anonymousClassLoader(false);
+    }
+
+    event.set_size(word_size * BytesPerWord);
+    event.set_metadataType((u1) mdtype);
+    event.set_metaspaceObjectType((u1) objtype);
+    event.commit();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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_MEMORY_METASPACE_TRACER_HPP
+#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/metaspace.hpp"
+#include "memory/metaspaceGCThresholdUpdater.hpp"
+
+class ClassLoaderData;
+
+class MetaspaceTracer : public CHeapObj<mtTracing> {
+  template <typename E>
+  void send_allocation_failure_event(ClassLoaderData *cld,
+                                     size_t word_size,
+                                     MetaspaceObj::Type objtype,
+                                     Metaspace::MetadataType mdtype) const;
+ public:
+  void report_gc_threshold(size_t old_val,
+                           size_t new_val,
+                           MetaspaceGCThresholdUpdater::Type updater) const;
+  void report_metaspace_allocation_failure(ClassLoaderData *cld,
+                                           size_t word_size,
+                                           MetaspaceObj::Type objtype,
+                                           Metaspace::MetadataType mdtype) const;
+  void report_metadata_oom(ClassLoaderData *cld,
+                           size_t word_size,
+                           MetaspaceObj::Type objtype,
+                           Metaspace::MetadataType mdtype) const;
+
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP
--- a/hotspot/src/share/vm/memory/padded.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/padded.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -90,4 +90,23 @@
   static PaddedEnd<T>* create_unfreeable(uint length);
 };
 
+// Helper class to create an array of references to arrays of primitive types
+// Both the array of references and the data arrays are aligned to the given
+// alignment. The allocated memory is zero-filled.
+template <class T, MEMFLAGS flags, size_t alignment = DEFAULT_CACHE_LINE_SIZE>
+class Padded2DArray {
+ public:
+  // Creates an aligned padded 2D array.
+  // The memory cannot be deleted since the raw memory chunk is not returned.
+  static T** create_unfreeable(uint rows, uint columns, size_t* allocation_size = NULL);
+};
+
+// Helper class to create an array of T objects. The array as a whole will
+// start at a multiple of alignment and its size will be aligned to alignment.
+template <class T, MEMFLAGS flags, size_t alignment = DEFAULT_CACHE_LINE_SIZE>
+class PaddedPrimitiveArray {
+ public:
+  static T* create_unfreeable(size_t length);
+};
+
 #endif // SHARE_VM_MEMORY_PADDED_HPP
--- a/hotspot/src/share/vm/memory/padded.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/padded.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -47,3 +47,42 @@
 
   return aligned_padded_array;
 }
+
+template <class T, MEMFLAGS flags, size_t alignment>
+T** Padded2DArray<T, flags, alignment>::create_unfreeable(uint rows, uint columns, size_t* allocation_size) {
+  // Calculate and align the size of the first dimension's table.
+  size_t table_size = align_size_up_(rows * sizeof(T*), alignment);
+  // The size of the separate rows.
+  size_t row_size = align_size_up_(columns * sizeof(T), alignment);
+  // Total size consists of the indirection table plus the rows.
+  size_t total_size = table_size + rows * row_size + alignment;
+
+  // Allocate a chunk of memory large enough to allow alignment of the chunk.
+  void* chunk = AllocateHeap(total_size, flags);
+  // Clear the allocated memory.
+  memset(chunk, 0, total_size);
+  // Align the chunk of memory.
+  T** result = (T**)align_pointer_up(chunk, alignment);
+  void* data_start = (void*)((uintptr_t)result + table_size);
+
+  // Fill in the row table.
+  for (size_t i = 0; i < rows; i++) {
+    result[i] = (T*)((uintptr_t)data_start + i * row_size);
+  }
+
+  if (allocation_size != NULL) {
+    *allocation_size = total_size;
+  }
+
+  return result;
+}
+
+template <class T, MEMFLAGS flags, size_t alignment>
+T* PaddedPrimitiveArray<T, flags, alignment>::create_unfreeable(size_t length) {
+  // Allocate a chunk of memory large enough to allow for some alignment.
+  void* chunk = AllocateHeap(length * sizeof(T) + alignment, flags);
+
+  memset(chunk, 0, length * sizeof(T) + alignment);
+
+  return (T*)align_pointer_up(chunk, alignment);
+}
--- a/hotspot/src/share/vm/memory/sharedHeap.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -163,9 +163,6 @@
   // Iteration functions.
   void oop_iterate(ExtendedOopClosure* cl) = 0;
 
-  // Same as above, restricted to a memory region.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
-
   // Iterate over all spaces in use in the heap, in an undefined order.
   virtual void space_iterate(SpaceClosure* cl) = 0;
 
--- a/hotspot/src/share/vm/memory/space.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/space.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -42,9 +42,6 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
 
-void SpaceMemRegionOopsIterClosure::do_oop(oop* p)       { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
-void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
-
 HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
                                                 HeapWord* top_obj) {
   if (top_obj != NULL) {
@@ -305,10 +302,6 @@
   CompactibleSpace::clear(mangle_space);
 }
 
-bool ContiguousSpace::is_in(const void* p) const {
-  return _bottom <= p && p < _top;
-}
-
 bool ContiguousSpace::is_free_block(const HeapWord* p) const {
   return p >= _top;
 }
@@ -550,115 +543,11 @@
   object_iterate(&blk2);
 }
 
-HeapWord* Space::object_iterate_careful(ObjectClosureCareful* cl) {
-  guarantee(false, "NYI");
-  return bottom();
-}
-
-HeapWord* Space::object_iterate_careful_m(MemRegion mr,
-                                          ObjectClosureCareful* cl) {
-  guarantee(false, "NYI");
-  return bottom();
-}
-
-
-void Space::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) {
-  assert(!mr.is_empty(), "Should be non-empty");
-  // We use MemRegion(bottom(), end()) rather than used_region() below
-  // because the two are not necessarily equal for some kinds of
-  // spaces, in particular, certain kinds of free list spaces.
-  // We could use the more complicated but more precise:
-  // MemRegion(used_region().start(), round_to(used_region().end(), CardSize))
-  // but the slight imprecision seems acceptable in the assertion check.
-  assert(MemRegion(bottom(), end()).contains(mr),
-         "Should be within used space");
-  HeapWord* prev = cl->previous();   // max address from last time
-  if (prev >= mr.end()) { // nothing to do
-    return;
-  }
-  // This assert will not work when we go from cms space to perm
-  // space, and use same closure. Easy fix deferred for later. XXX YSR
-  // assert(prev == NULL || contains(prev), "Should be within space");
-
-  bool last_was_obj_array = false;
-  HeapWord *blk_start_addr, *region_start_addr;
-  if (prev > mr.start()) {
-    region_start_addr = prev;
-    blk_start_addr    = prev;
-    // The previous invocation may have pushed "prev" beyond the
-    // last allocated block yet there may be still be blocks
-    // in this region due to a particular coalescing policy.
-    // Relax the assertion so that the case where the unallocated
-    // block is maintained and "prev" is beyond the unallocated
-    // block does not cause the assertion to fire.
-    assert((BlockOffsetArrayUseUnallocatedBlock &&
-            (!is_in(prev))) ||
-           (blk_start_addr == block_start(region_start_addr)), "invariant");
-  } else {
-    region_start_addr = mr.start();
-    blk_start_addr    = block_start(region_start_addr);
-  }
-  HeapWord* region_end_addr = mr.end();
-  MemRegion derived_mr(region_start_addr, region_end_addr);
-  while (blk_start_addr < region_end_addr) {
-    const size_t size = block_size(blk_start_addr);
-    if (block_is_obj(blk_start_addr)) {
-      last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr);
-    } else {
-      last_was_obj_array = false;
-    }
-    blk_start_addr += size;
-  }
-  if (!last_was_obj_array) {
-    assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()),
-           "Should be within (closed) used space");
-    assert(blk_start_addr > prev, "Invariant");
-    cl->set_previous(blk_start_addr); // min address for next time
-  }
-}
-
 bool Space::obj_is_alive(const HeapWord* p) const {
   assert (block_is_obj(p), "The address should point to an object");
   return true;
 }
 
-void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) {
-  assert(!mr.is_empty(), "Should be non-empty");
-  assert(used_region().contains(mr), "Should be within used space");
-  HeapWord* prev = cl->previous();   // max address from last time
-  if (prev >= mr.end()) { // nothing to do
-    return;
-  }
-  // See comment above (in more general method above) in case you
-  // happen to use this method.
-  assert(prev == NULL || is_in_reserved(prev), "Should be within space");
-
-  bool last_was_obj_array = false;
-  HeapWord *obj_start_addr, *region_start_addr;
-  if (prev > mr.start()) {
-    region_start_addr = prev;
-    obj_start_addr    = prev;
-    assert(obj_start_addr == block_start(region_start_addr), "invariant");
-  } else {
-    region_start_addr = mr.start();
-    obj_start_addr    = block_start(region_start_addr);
-  }
-  HeapWord* region_end_addr = mr.end();
-  MemRegion derived_mr(region_start_addr, region_end_addr);
-  while (obj_start_addr < region_end_addr) {
-    oop obj = oop(obj_start_addr);
-    const size_t size = obj->size();
-    last_was_obj_array = cl->do_object_bm(obj, derived_mr);
-    obj_start_addr += size;
-  }
-  if (!last_was_obj_array) {
-    assert((bottom() <= obj_start_addr)  && (obj_start_addr <= end()),
-           "Should be within (closed) used space");
-    assert(obj_start_addr > prev, "Invariant");
-    cl->set_previous(obj_start_addr); // min address for next time
-  }
-}
-
 #if INCLUDE_ALL_GCS
 #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)         \
                                                                             \
@@ -686,43 +575,6 @@
   }
 }
 
-void ContiguousSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* blk) {
-  if (is_empty()) {
-    return;
-  }
-  MemRegion cur = MemRegion(bottom(), top());
-  mr = mr.intersection(cur);
-  if (mr.is_empty()) {
-    return;
-  }
-  if (mr.equals(cur)) {
-    oop_iterate(blk);
-    return;
-  }
-  assert(mr.end() <= top(), "just took an intersection above");
-  HeapWord* obj_addr = block_start(mr.start());
-  HeapWord* t = mr.end();
-
-  // Handle first object specially.
-  oop obj = oop(obj_addr);
-  SpaceMemRegionOopsIterClosure smr_blk(blk, mr);
-  obj_addr += obj->oop_iterate(&smr_blk);
-  while (obj_addr < t) {
-    oop obj = oop(obj_addr);
-    assert(obj->is_oop(), "expected an oop");
-    obj_addr += obj->size();
-    // If "obj_addr" is not greater than top, then the
-    // entire object "obj" is within the region.
-    if (obj_addr <= t) {
-      obj->oop_iterate(blk);
-    } else {
-      // "obj" extends beyond end of region
-      obj->oop_iterate(&smr_blk);
-      break;
-    }
-  };
-}
-
 void ContiguousSpace::object_iterate(ObjectClosure* blk) {
   if (is_empty()) return;
   WaterMark bm = bottom_mark();
--- a/hotspot/src/share/vm/memory/space.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/space.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -81,31 +81,6 @@
 class CardTableRS;
 class DirtyCardToOopClosure;
 
-// An oop closure that is circumscribed by a filtering memory region.
-class SpaceMemRegionOopsIterClosure: public ExtendedOopClosure {
- private:
-  ExtendedOopClosure* _cl;
-  MemRegion   _mr;
- protected:
-  template <class T> void do_oop_work(T* p) {
-    if (_mr.contains(p)) {
-      _cl->do_oop(p);
-    }
-  }
- public:
-  SpaceMemRegionOopsIterClosure(ExtendedOopClosure* cl, MemRegion mr):
-    _cl(cl), _mr(mr) {}
-  virtual void do_oop(oop* p);
-  virtual void do_oop(narrowOop* p);
-  virtual bool do_metadata() {
-    // _cl is of type ExtendedOopClosure instead of OopClosure, so that we can check this.
-    assert(!_cl->do_metadata(), "I've checked all call paths, this shouldn't happen.");
-    return false;
-  }
-  virtual void do_klass(Klass* k)                         { ShouldNotReachHere(); }
-  virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); }
-};
-
 // A Space describes a heap area. Class Space is an abstract
 // base class.
 //
@@ -145,6 +120,12 @@
 
   void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; }
 
+  // Returns true if this object has been allocated since a
+  // generation's "save_marks" call.
+  virtual bool obj_allocated_since_save_marks(const oop obj) const {
+    return (HeapWord*)obj >= saved_mark_word();
+  }
+
   MemRegionClosure* preconsumptionDirtyCardClosure() const {
     return _preconsumptionDirtyCardClosure;
   }
@@ -152,9 +133,9 @@
     _preconsumptionDirtyCardClosure = cl;
   }
 
-  // Returns a subregion of the space containing all the objects in
+  // Returns a subregion of the space containing only the allocated objects in
   // the space.
-  virtual MemRegion used_region() const { return MemRegion(bottom(), end()); }
+  virtual MemRegion used_region() const = 0;
 
   // Returns a region that is guaranteed to contain (at least) all objects
   // allocated at the time of the last call to "save_marks".  If the space
@@ -164,7 +145,7 @@
   // saved mark.  Otherwise, the "obj_allocated_since_save_marks" method of
   // the space must distinguish between objects in the region allocated before
   // and after the call to save marks.
-  virtual MemRegion used_region_at_save_marks() const {
+  MemRegion used_region_at_save_marks() const {
     return MemRegion(bottom(), saved_mark_word());
   }
 
@@ -197,7 +178,9 @@
   // expensive operation. To prevent performance problems
   // on account of its inadvertent use in product jvm's,
   // we restrict its use to assertion checks only.
-  virtual bool is_in(const void* p) const = 0;
+  bool is_in(const void* p) const {
+    return used_region().contains(p);
+  }
 
   // Returns true iff the given reserved memory of the space contains the
   // given address.
@@ -221,11 +204,6 @@
   // applications of the closure are not included in the iteration.
   virtual void oop_iterate(ExtendedOopClosure* cl);
 
-  // Same as above, restricted to the intersection of a memory region and
-  // the space.  Fields in objects allocated by applications of the closure
-  // are not included in the iteration.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
-
   // Iterate over all objects in the space, calling "cl.do_object" on
   // each.  Objects allocated by applications of the closure are not
   // included in the iteration.
@@ -234,24 +212,6 @@
   // objects whose internal references point to objects in the space.
   virtual void safe_object_iterate(ObjectClosure* blk) = 0;
 
-  // Iterate over all objects that intersect with mr, calling "cl->do_object"
-  // on each.  There is an exception to this: if this closure has already
-  // been invoked on an object, it may skip such objects in some cases.  This is
-  // Most likely to happen in an "upwards" (ascending address) iteration of
-  // MemRegions.
-  virtual void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
-
-  // Iterate over as many initialized objects in the space as possible,
-  // calling "cl.do_object_careful" on each. Return NULL if all objects
-  // in the space (at the start of the iteration) were iterated over.
-  // Return an address indicating the extent of the iteration in the
-  // event that the iteration had to return because of finding an
-  // uninitialized object in the space, or if the closure "cl"
-  // signaled early termination.
-  virtual HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
-  virtual HeapWord* object_iterate_careful_m(MemRegion mr,
-                                             ObjectClosureCareful* cl);
-
   // Create and return a new dirty card to oop closure. Can be
   // overridden to return the appropriate type of closure
   // depending on the type of space in which the closure will
@@ -292,10 +252,6 @@
   // Allocation (return NULL if full).  Enforces mutual exclusion internally.
   virtual HeapWord* par_allocate(size_t word_size) = 0;
 
-  // Returns true if this object has been allocated since a
-  // generation's "save_marks" call.
-  virtual bool obj_allocated_since_save_marks(const oop obj) const = 0;
-
   // Mark-sweep-compact support: all spaces can update pointers to objects
   // moving as a part of compaction.
   virtual void adjust_pointers();
@@ -427,7 +383,7 @@
 
   // Perform operations on the space needed after a compaction
   // has been performed.
-  virtual void reset_after_compaction() {}
+  virtual void reset_after_compaction() = 0;
 
   // Returns the next space (in the current generation) to be compacted in
   // the global compaction order.  Also is used to select the next
@@ -492,7 +448,7 @@
   HeapWord* _end_of_live;
 
   // Minimum size of a free block.
-  virtual size_t minimum_free_block_size() const = 0;
+  virtual size_t minimum_free_block_size() const { return 0; }
 
   // This the function is invoked when an allocation of an object covering
   // "start" to "end occurs crosses the threshold; returns the next
@@ -808,7 +764,7 @@
   HeapWord* top() const            { return _top;    }
   void set_top(HeapWord* value)    { _top = value; }
 
-  virtual void set_saved_mark()    { _saved_mark_word = top();    }
+  void set_saved_mark()            { _saved_mark_word = top();    }
   void reset_saved_mark()          { _saved_mark_word = bottom(); }
 
   WaterMark bottom_mark()     { return WaterMark(this, bottom()); }
@@ -843,36 +799,30 @@
   size_t used() const            { return byte_size(bottom(), top()); }
   size_t free() const            { return byte_size(top(),    end()); }
 
-  // Override from space.
-  bool is_in(const void* p) const;
-
   virtual bool is_free_block(const HeapWord* p) const;
 
   // In a contiguous space we have a more obvious bound on what parts
   // contain objects.
   MemRegion used_region() const { return MemRegion(bottom(), top()); }
 
-  MemRegion used_region_at_save_marks() const {
-    return MemRegion(bottom(), saved_mark_word());
-  }
-
   // Allocation (return NULL if full)
   virtual HeapWord* allocate(size_t word_size);
   virtual HeapWord* par_allocate(size_t word_size);
 
-  virtual bool obj_allocated_since_save_marks(const oop obj) const {
-    return (HeapWord*)obj >= saved_mark_word();
-  }
-
   // Iteration
   void oop_iterate(ExtendedOopClosure* cl);
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void object_iterate(ObjectClosure* blk);
   // For contiguous spaces this method will iterate safely over objects
   // in the space (i.e., between bottom and top) when at a safepoint.
   void safe_object_iterate(ObjectClosure* blk);
-  void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
-  // iterates on objects up to the safe limit
+
+  // Iterate over as many initialized objects in the space as possible,
+  // calling "cl.do_object_careful" on each. Return NULL if all objects
+  // in the space (at the start of the iteration) were iterated over.
+  // Return an address indicating the extent of the iteration in the
+  // event that the iteration had to return because of finding an
+  // uninitialized object in the space, or if the closure "cl"
+  // signaled early termination.
   HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
   HeapWord* concurrent_iteration_safe_limit() {
     assert(_concurrent_iteration_safe_limit <= top(),
@@ -903,7 +853,6 @@
     // set new iteration safe limit
     set_concurrent_iteration_safe_limit(compaction_top());
   }
-  virtual size_t minimum_free_block_size() const { return 0; }
 
   // Override.
   DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
--- a/hotspot/src/share/vm/memory/universe.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -632,7 +632,6 @@
   guarantee(sizeof(oop) % sizeof(HeapWord) == 0,
             "oop size is not not a multiple of HeapWord size");
   TraceTime timer("Genesis", TraceStartupTime);
-  GC_locker::lock();  // do not allow gc during bootstrapping
   JavaClasses::compute_hard_coded_offsets();
 
   jint status = Universe::initialize_heap();
@@ -1164,8 +1163,6 @@
 
   MemoryService::add_metaspace_memory_pools();
 
-  GC_locker::unlock();  // allow gc after bootstrapping
-
   MemoryService::set_universe_heap(Universe::_collectedHeap);
   return true;
 }
--- a/hotspot/src/share/vm/oops/constMethod.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/constMethod.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -27,68 +27,61 @@
 
 #include "oops/oop.hpp"
 
-// An ConstMethod* represents portions of a Java method which
-// do not vary.
+// An ConstMethod represents portions of a Java method which are not written to after
+// the classfile is parsed(*see below).  This part of the method can be shared across
+// processes in a read-only section with Class Data Sharing (CDS).  It's important
+// that this class doesn't have virtual functions because the vptr cannot be shared
+// with CDS.
+//   (*)RewriteByteCodes and RewriteFrequentPairs is an exception but turned off in CDS
 //
-// Memory layout (each line represents a word). Note that most
-// applications load thousands of methods, so keeping the size of this
+// Note that most applications load thousands of methods, so keeping the size of this
 // structure small has a big impact on footprint.
+
+// The actual bytecodes are inlined after the end of the ConstMethod struct.
+//
+// The line number table is compressed and inlined following the byte codes. It is
+// found as the first byte following the byte codes.  Note that accessing the line
+// number and local variable tables is not performance critical at all.
+//
+// The checked exceptions table and the local variable table are inlined after the
+// line number table, and indexed from the end of the method. We do not compress the
+// checked exceptions table since the average length is less than 2, and it is used
+// by reflection so access should be fast.  We do not bother to compress the local
+// variable table either since it is mostly absent.
+//
 //
-// |------------------------------------------------------|
-// | header                                               |
-// | klass                                                |
-// |------------------------------------------------------|
-// | fingerprint 1                                        |
-// | fingerprint 2                                        |
-// | constants                      (oop)                 |
-// | stackmap_data                  (oop)                 |
-// | constMethod_size                                     |
-// | interp_kind  | flags    | code_size                  |
-// | name index              | signature index            |
-// | method_idnum            | max_stack                  |
-// | max_locals              | size_of_parameters         |
-// |------------------------------------------------------|
-// |                                                      |
-// | byte codes                                           |
-// |                                                      |
-// |------------------------------------------------------|
-// | compressed linenumber table                          |
-// |  (see class CompressedLineNumberReadStream)          |
-// |  (note that length is unknown until decompressed)    |
-// |  (access flags bit tells whether table is present)   |
-// |  (indexed from start of ConstMethod*)                |
-// |  (elements not necessarily sorted!)                  |
-// |------------------------------------------------------|
-// | localvariable table elements + length (length last)  |
-// |  (length is u2, elements are 6-tuples of u2)         |
-// |  (see class LocalVariableTableElement)               |
-// |  (access flags bit tells whether table is present)   |
-// |  (indexed from end of ConstMethod*)                  |
-// |------------------------------------------------------|
-// | exception table + length (length last)               |
-// |  (length is u2, elements are 4-tuples of u2)         |
-// |  (see class ExceptionTableElement)                   |
-// |  (access flags bit tells whether table is present)   |
-// |  (indexed from end of ConstMethod*)                  |
-// |------------------------------------------------------|
-// | checked exceptions elements + length (length last)   |
-// |  (length is u2, elements are u2)                     |
-// |  (see class CheckedExceptionElement)                 |
-// |  (access flags bit tells whether table is present)   |
-// |  (indexed from end of ConstMethod*)                  |
-// |------------------------------------------------------|
-// | method parameters elements + length (length last)    |
-// |  (length is u2, elements are u2, u4 structures)      |
-// |  (see class MethodParametersElement)                 |
-// |  (access flags bit tells whether table is present)   |
-// |  (indexed from end of ConstMethod*)                  |
-// |------------------------------------------------------|
-// | generic signature index (u2)                         |
-// |  (indexed from start of constMethodOop)              |
-// |------------------------------------------------------|
-// | annotations arrays - method, parameter, type, default|
-// | pointer to Array<u1> if annotation is present        |
-// |------------------------------------------------------|
+//  ConstMethod embedded field layout (after declared fields):
+//    [EMBEDDED byte codes]
+//    [EMBEDDED compressed linenumber table]
+//     (see class CompressedLineNumberReadStream)
+//     (note that length is unknown until decompressed)
+//     (access flags bit tells whether table is present)
+//     (indexed from start of ConstMethod)
+//     (elements not necessarily sorted!)
+//    [EMBEDDED localvariable table elements + length (length last)]
+//     (length is u2, elements are 6-tuples of u2)
+//     (see class LocalVariableTableElement)
+//     (access flags bit tells whether table is present)
+//     (indexed from end of ConstMethod*)
+//    [EMBEDDED exception table + length (length last)]
+//     (length is u2, elements are 4-tuples of u2)
+//     (see class ExceptionTableElement)
+//     (access flags bit tells whether table is present)
+//     (indexed from end of ConstMethod*)
+//    [EMBEDDED checked exceptions elements + length (length last)]
+//     (length is u2, elements are u2)
+//     (see class CheckedExceptionElement)
+//     (access flags bit tells whether table is present)
+//     (indexed from end of ConstMethod*)
+//    [EMBEDDED method parameters elements + length (length last)]
+//     (length is u2, elements are u2, u4 structures)
+//     (see class MethodParametersElement)
+//     (access flags bit tells whether table is present)
+//     (indexed from end of ConstMethod*)
+//    [EMBEDDED generic signature index (u2)]
+//     (indexed from end of constMethodOop)
+//    [EMBEDDED annotations arrays - method, parameter, type, default]
+//      pointer to Array<u1> if annotation is present
 //
 // IMPORTANT: If anything gets added here, there need to be changes to
 // ensure that ServicabilityAgent doesn't get broken as a result!
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -180,12 +180,12 @@
   return (i < 0) ? _no_index_sentinel : i;
 }
 
-Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
+Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) {
   // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
   // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
   // tag is not updated atomicly.
 
-  CPSlot entry = this_oop->slot_at(which);
+  CPSlot entry = this_cp->slot_at(which);
   if (entry.is_resolved()) {
     assert(entry.get_klass()->is_klass(), "must be");
     // Already resolved - return entry.
@@ -204,15 +204,15 @@
 
   Symbol* name = NULL;
   Handle       loader;
-  {  MonitorLockerEx ml(this_oop->lock());
+  {  MonitorLockerEx ml(this_cp->lock());
 
-    if (this_oop->tag_at(which).is_unresolved_klass()) {
-      if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
+    if (this_cp->tag_at(which).is_unresolved_klass()) {
+      if (this_cp->tag_at(which).is_unresolved_klass_in_error()) {
         in_error = true;
       } else {
         do_resolve = true;
-        name   = this_oop->unresolved_klass_at(which);
-        loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
+        name   = this_cp->unresolved_klass_at(which);
+        loader = Handle(THREAD, this_cp->pool_holder()->class_loader());
       }
     }
   } // unlocking constantPool
@@ -221,26 +221,26 @@
   // The original attempt to resolve this constant pool entry failed so find the
   // original error and throw it again (JVMS 5.4.3).
   if (in_error) {
-    Symbol* error = SystemDictionary::find_resolution_error(this_oop, which);
+    Symbol* error = SystemDictionary::find_resolution_error(this_cp, which);
     guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
     ResourceMark rm;
     // exception text will be the class name
-    const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
+    const char* className = this_cp->unresolved_klass_at(which)->as_C_string();
     THROW_MSG_0(error, className);
   }
 
   if (do_resolve) {
-    // this_oop must be unlocked during resolve_or_fail
-    oop protection_domain = this_oop->pool_holder()->protection_domain();
+    // this_cp must be unlocked during resolve_or_fail
+    oop protection_domain = this_cp->pool_holder()->protection_domain();
     Handle h_prot (THREAD, protection_domain);
-    Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
+    Klass* kk = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
     KlassHandle k;
     if (!HAS_PENDING_EXCEPTION) {
-      k = KlassHandle(THREAD, k_oop);
+      k = KlassHandle(THREAD, kk);
       // preserve the resolved klass.
-      mirror_handle = Handle(THREAD, k_oop->java_mirror());
+      mirror_handle = Handle(THREAD, kk->java_mirror());
       // Do access check for klasses
-      verify_constant_pool_resolve(this_oop, k, THREAD);
+      verify_constant_pool_resolve(this_cp, k, THREAD);
     }
 
     // Failed to resolve class. We must record the errors so that subsequent attempts
@@ -251,12 +251,12 @@
 
       bool throw_orig_error = false;
       {
-        MonitorLockerEx ml(this_oop->lock());
+        MonitorLockerEx ml(this_cp->lock());
 
         // some other thread has beaten us and has resolved the class.
-        if (this_oop->tag_at(which).is_klass()) {
+        if (this_cp->tag_at(which).is_klass()) {
           CLEAR_PENDING_EXCEPTION;
-          entry = this_oop->resolved_klass_at(which);
+          entry = this_cp->resolved_klass_at(which);
           return entry.get_klass();
         }
 
@@ -267,12 +267,12 @@
           // and OutOfMemoryError, etc, or if the thread was hit by stop()
           // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
         }
-        else if (!this_oop->tag_at(which).is_unresolved_klass_in_error()) {
-          SystemDictionary::add_resolution_error(this_oop, which, error);
-          this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
+        else if (!this_cp->tag_at(which).is_unresolved_klass_in_error()) {
+          SystemDictionary::add_resolution_error(this_cp, which, error);
+          this_cp->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
         } else {
           // some other thread has put the class in error state.
-          error = SystemDictionary::find_resolution_error(this_oop, which);
+          error = SystemDictionary::find_resolution_error(this_cp, which);
           assert(error != NULL, "checking");
           throw_orig_error = true;
         }
@@ -281,7 +281,7 @@
       if (throw_orig_error) {
         CLEAR_PENDING_EXCEPTION;
         ResourceMark rm;
-        const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
+        const char* className = this_cp->unresolved_klass_at(which)->as_C_string();
         THROW_MSG_0(error, className);
       }
 
@@ -305,32 +305,32 @@
           }
         }
       }
-      if (k() != this_oop->pool_holder()) {
+      if (k() != this_cp->pool_holder()) {
         // only print something if the classes are different
         if (source_file != NULL) {
           tty->print("RESOLVE %s %s %s:%d\n",
-                     this_oop->pool_holder()->external_name(),
+                     this_cp->pool_holder()->external_name(),
                      InstanceKlass::cast(k())->external_name(), source_file, line_number);
         } else {
           tty->print("RESOLVE %s %s\n",
-                     this_oop->pool_holder()->external_name(),
+                     this_cp->pool_holder()->external_name(),
                      InstanceKlass::cast(k())->external_name());
         }
       }
       return k();
     } else {
-      MonitorLockerEx ml(this_oop->lock());
+      MonitorLockerEx ml(this_cp->lock());
       // Only updated constant pool - if it is resolved.
-      do_resolve = this_oop->tag_at(which).is_unresolved_klass();
+      do_resolve = this_cp->tag_at(which).is_unresolved_klass();
       if (do_resolve) {
-        ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
+        ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
         this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
-        this_oop->klass_at_put(which, k());
+        this_cp->klass_at_put(which, k());
       }
     }
   }
 
-  entry = this_oop->resolved_klass_at(which);
+  entry = this_cp->resolved_klass_at(which);
   assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
   return entry.get_klass();
 }
@@ -340,8 +340,8 @@
 // by compiler and exception handling.  Also used to avoid classloads for
 // instanceof operations. Returns NULL if the class has not been loaded or
 // if the verification of constant pool failed
-Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_oop, int which) {
-  CPSlot entry = this_oop->slot_at(which);
+Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_cp, int which) {
+  CPSlot entry = this_cp->slot_at(which);
   if (entry.is_resolved()) {
     assert(entry.get_klass()->is_klass(), "must be");
     return entry.get_klass();
@@ -349,8 +349,8 @@
     assert(entry.is_unresolved(), "must be either symbol or klass");
     Thread *thread = Thread::current();
     Symbol* name = entry.get_symbol();
-    oop loader = this_oop->pool_holder()->class_loader();
-    oop protection_domain = this_oop->pool_holder()->protection_domain();
+    oop loader = this_cp->pool_holder()->class_loader();
+    oop protection_domain = this_cp->pool_holder()->protection_domain();
     Handle h_prot (thread, protection_domain);
     Handle h_loader (thread, loader);
     Klass* k = SystemDictionary::find(name, h_loader, h_prot, thread);
@@ -360,7 +360,7 @@
       EXCEPTION_MARK;
       KlassHandle klass(THREAD, k);
       // return NULL if verification fails
-      verify_constant_pool_resolve(this_oop, klass, THREAD);
+      verify_constant_pool_resolve(this_cp, klass, THREAD);
       if (HAS_PENDING_EXCEPTION) {
         CLEAR_PENDING_EXCEPTION;
         return NULL;
@@ -373,8 +373,8 @@
 }
 
 
-Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_oop, int which) {
-  return klass_at_if_loaded(this_oop, this_oop->klass_ref_index_at(which));
+Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_cp, int which) {
+  return klass_at_if_loaded(this_cp, this_cp->klass_ref_index_at(which));
 }
 
 
@@ -486,11 +486,11 @@
 }
 
 
-void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
+void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle k, TRAPS) {
  if (k->oop_is_instance() || k->oop_is_objArray()) {
-    instanceKlassHandle holder (THREAD, this_oop->pool_holder());
-    Klass* elem_oop = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass();
-    KlassHandle element (THREAD, elem_oop);
+    instanceKlassHandle holder (THREAD, this_cp->pool_holder());
+    Klass* elem = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass();
+    KlassHandle element (THREAD, elem);
 
     // The element type could be a typeArray - we only need the access check if it is
     // an reference to another class
@@ -559,10 +559,10 @@
 }
 
 
-void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS) {
-  for (int index = 1; index < this_oop->length(); index++) { // Index 0 is unused
-    if (this_oop->tag_at(index).is_string()) {
-      this_oop->string_at(index, CHECK);
+void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS) {
+  for (int index = 1; index < this_cp->length(); index++) { // Index 0 is unused
+    if (this_cp->tag_at(index).is_string()) {
+      this_cp->string_at(index, CHECK);
     }
   }
 }
@@ -585,11 +585,11 @@
 
 // If resolution for MethodHandle or MethodType fails, save the exception
 // in the resolution error table, so that the same exception is thrown again.
-void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which,
+void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int which,
                                      int tag, TRAPS) {
   ResourceMark rm;
   Symbol* error = PENDING_EXCEPTION->klass()->name();
-  MonitorLockerEx ml(this_oop->lock());  // lock cpool to change tag.
+  MonitorLockerEx ml(this_cp->lock());  // lock cpool to change tag.
 
   int error_tag = (tag == JVM_CONSTANT_MethodHandle) ?
            JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError;
@@ -601,12 +601,12 @@
     // and OutOfMemoryError, etc, or if the thread was hit by stop()
     // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
 
-  } else if (this_oop->tag_at(which).value() != error_tag) {
-    SystemDictionary::add_resolution_error(this_oop, which, error);
-    this_oop->tag_at_put(which, error_tag);
+  } else if (this_cp->tag_at(which).value() != error_tag) {
+    SystemDictionary::add_resolution_error(this_cp, which, error);
+    this_cp->tag_at_put(which, error_tag);
   } else {
     // some other thread has put the class in error state.
-    error = SystemDictionary::find_resolution_error(this_oop, which);
+    error = SystemDictionary::find_resolution_error(this_cp, which);
     assert(error != NULL, "checking");
     CLEAR_PENDING_EXCEPTION;
     THROW_MSG(error, "");
@@ -617,7 +617,7 @@
 // Called to resolve constants in the constant pool and return an oop.
 // Some constant pool entries cache their resolved oop. This is also
 // called to create oops from constants to use in arguments for invokedynamic
-oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
+oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS) {
   oop result_oop = NULL;
   Handle throw_exception;
 
@@ -625,23 +625,23 @@
     // It is possible that this constant is one which is cached in the objects.
     // We'll do a linear search.  This should be OK because this usage is rare.
     assert(index > 0, "valid index");
-    cache_index = this_oop->cp_to_object_index(index);
+    cache_index = this_cp->cp_to_object_index(index);
   }
   assert(cache_index == _no_index_sentinel || cache_index >= 0, "");
   assert(index == _no_index_sentinel || index >= 0, "");
 
   if (cache_index >= 0) {
-    result_oop = this_oop->resolved_references()->obj_at(cache_index);
+    result_oop = this_cp->resolved_references()->obj_at(cache_index);
     if (result_oop != NULL) {
       return result_oop;
       // That was easy...
     }
-    index = this_oop->object_to_cp_index(cache_index);
+    index = this_cp->object_to_cp_index(cache_index);
   }
 
   jvalue prim_value;  // temp used only in a few cases below
 
-  int tag_value = this_oop->tag_at(index).value();
+  int tag_value = this_cp->tag_at(index).value();
 
   switch (tag_value) {
 
@@ -650,7 +650,7 @@
   case JVM_CONSTANT_Class:
     {
       assert(cache_index == _no_index_sentinel, "should not have been set");
-      Klass* resolved = klass_at_impl(this_oop, index, CHECK_NULL);
+      Klass* resolved = klass_at_impl(this_cp, index, CHECK_NULL);
       // ldc wants the java mirror.
       result_oop = resolved->java_mirror();
       break;
@@ -658,17 +658,17 @@
 
   case JVM_CONSTANT_String:
     assert(cache_index != _no_index_sentinel, "should have been set");
-    if (this_oop->is_pseudo_string_at(index)) {
-      result_oop = this_oop->pseudo_string_at(index, cache_index);
+    if (this_cp->is_pseudo_string_at(index)) {
+      result_oop = this_cp->pseudo_string_at(index, cache_index);
       break;
     }
-    result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
+    result_oop = string_at_impl(this_cp, index, cache_index, CHECK_NULL);
     break;
 
   case JVM_CONSTANT_MethodHandleInError:
   case JVM_CONSTANT_MethodTypeInError:
     {
-      Symbol* error = SystemDictionary::find_resolution_error(this_oop, index);
+      Symbol* error = SystemDictionary::find_resolution_error(this_cp, index);
       guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
       ResourceMark rm;
       THROW_MSG_0(error, "");
@@ -677,72 +677,72 @@
 
   case JVM_CONSTANT_MethodHandle:
     {
-      int ref_kind                 = this_oop->method_handle_ref_kind_at(index);
-      int callee_index             = this_oop->method_handle_klass_index_at(index);
-      Symbol*  name =      this_oop->method_handle_name_ref_at(index);
-      Symbol*  signature = this_oop->method_handle_signature_ref_at(index);
+      int ref_kind                 = this_cp->method_handle_ref_kind_at(index);
+      int callee_index             = this_cp->method_handle_klass_index_at(index);
+      Symbol*  name =      this_cp->method_handle_name_ref_at(index);
+      Symbol*  signature = this_cp->method_handle_signature_ref_at(index);
       if (PrintMiscellaneous)
         tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
-                      ref_kind, index, this_oop->method_handle_index_at(index),
+                      ref_kind, index, this_cp->method_handle_index_at(index),
                       callee_index, name->as_C_string(), signature->as_C_string());
       KlassHandle callee;
-      { Klass* k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
+      { Klass* k = klass_at_impl(this_cp, callee_index, CHECK_NULL);
         callee = KlassHandle(THREAD, k);
       }
-      KlassHandle klass(THREAD, this_oop->pool_holder());
+      KlassHandle klass(THREAD, this_cp->pool_holder());
       Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
                                                                    callee, name, signature,
                                                                    THREAD);
       result_oop = value();
       if (HAS_PENDING_EXCEPTION) {
-        save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
+        save_and_throw_exception(this_cp, index, tag_value, CHECK_NULL);
       }
       break;
     }
 
   case JVM_CONSTANT_MethodType:
     {
-      Symbol*  signature = this_oop->method_type_signature_at(index);
+      Symbol*  signature = this_cp->method_type_signature_at(index);
       if (PrintMiscellaneous)
         tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
-                      index, this_oop->method_type_index_at(index),
+                      index, this_cp->method_type_index_at(index),
                       signature->as_C_string());
-      KlassHandle klass(THREAD, this_oop->pool_holder());
+      KlassHandle klass(THREAD, this_cp->pool_holder());
       Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD);
       result_oop = value();
       if (HAS_PENDING_EXCEPTION) {
-        save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
+        save_and_throw_exception(this_cp, index, tag_value, CHECK_NULL);
       }
       break;
     }
 
   case JVM_CONSTANT_Integer:
     assert(cache_index == _no_index_sentinel, "should not have been set");
-    prim_value.i = this_oop->int_at(index);
+    prim_value.i = this_cp->int_at(index);
     result_oop = java_lang_boxing_object::create(T_INT, &prim_value, CHECK_NULL);
     break;
 
   case JVM_CONSTANT_Float:
     assert(cache_index == _no_index_sentinel, "should not have been set");
-    prim_value.f = this_oop->float_at(index);
+    prim_value.f = this_cp->float_at(index);
     result_oop = java_lang_boxing_object::create(T_FLOAT, &prim_value, CHECK_NULL);
     break;
 
   case JVM_CONSTANT_Long:
     assert(cache_index == _no_index_sentinel, "should not have been set");
-    prim_value.j = this_oop->long_at(index);
+    prim_value.j = this_cp->long_at(index);
     result_oop = java_lang_boxing_object::create(T_LONG, &prim_value, CHECK_NULL);
     break;
 
   case JVM_CONSTANT_Double:
     assert(cache_index == _no_index_sentinel, "should not have been set");
-    prim_value.d = this_oop->double_at(index);
+    prim_value.d = this_cp->double_at(index);
     result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL);
     break;
 
   default:
     DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
-                              this_oop(), index, cache_index, tag_value) );
+                              this_cp(), index, cache_index, tag_value) );
     assert(false, "unexpected constant tag");
     break;
   }
@@ -750,15 +750,15 @@
   if (cache_index >= 0) {
     // Cache the oop here also.
     Handle result_handle(THREAD, result_oop);
-    MonitorLockerEx ml(this_oop->lock());  // don't know if we really need this
-    oop result = this_oop->resolved_references()->obj_at(cache_index);
+    MonitorLockerEx ml(this_cp->lock());  // don't know if we really need this
+    oop result = this_cp->resolved_references()->obj_at(cache_index);
     // Benign race condition:  resolved_references may already be filled in while we were trying to lock.
     // The important thing here is that all threads pick up the same result.
     // It doesn't matter which racing thread wins, as long as only one
     // result is used by all threads, and all future queries.
     // That result may be either a resolved constant or a failure exception.
     if (result == NULL) {
-      this_oop->resolved_references()->obj_at_put(cache_index, result_handle());
+      this_cp->resolved_references()->obj_at_put(cache_index, result_handle());
       return result_handle();
     } else {
       // Return the winning thread's result.  This can be different than
@@ -778,8 +778,8 @@
 }
 
 
-oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_oop, int index, TRAPS) {
-  assert(this_oop->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
+oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS) {
+  assert(this_cp->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
 
   Handle bsm;
   int argc;
@@ -787,14 +787,14 @@
     // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type], plus optional arguments
     // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
     // It is accompanied by the optional arguments.
-    int bsm_index = this_oop->invoke_dynamic_bootstrap_method_ref_index_at(index);
-    oop bsm_oop = this_oop->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
+    int bsm_index = this_cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
+    oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
     if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) {
       THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle");
     }
 
     // Extract the optional static arguments.
-    argc = this_oop->invoke_dynamic_argument_count_at(index);
+    argc = this_cp->invoke_dynamic_argument_count_at(index);
     if (argc == 0)  return bsm_oop;
 
     bsm = Handle(THREAD, bsm_oop);
@@ -808,21 +808,21 @@
 
   info->obj_at_put(0, bsm());
   for (int i = 0; i < argc; i++) {
-    int arg_index = this_oop->invoke_dynamic_argument_index_at(index, i);
-    oop arg_oop = this_oop->resolve_possibly_cached_constant_at(arg_index, CHECK_NULL);
+    int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
+    oop arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK_NULL);
     info->obj_at_put(1+i, arg_oop);
   }
 
   return info();
 }
 
-oop ConstantPool::string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS) {
+oop ConstantPool::string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS) {
   // If the string has already been interned, this entry will be non-null
-  oop str = this_oop->resolved_references()->obj_at(obj_index);
+  oop str = this_cp->resolved_references()->obj_at(obj_index);
   if (str != NULL) return str;
-  Symbol* sym = this_oop->unresolved_string_at(which);
+  Symbol* sym = this_cp->unresolved_string_at(which);
   str = StringTable::intern(sym, CHECK_(NULL));
-  this_oop->string_at_put(which, obj_index, str);
+  this_cp->string_at_put(which, obj_index, str);
   assert(java_lang_String::is_instance(str), "must be string");
   return str;
 }
--- a/hotspot/src/share/vm/oops/constantPool.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -48,7 +48,7 @@
 # include "bytes_ppc.hpp"
 #endif
 
-// A constantPool is an array containing class constants as described in the
+// A ConstantPool is an array containing class constants as described in the
 // class file.
 //
 // Most of the constant pool entries are written during class parsing, which
@@ -81,9 +81,10 @@
 };
 
 class KlassSizeStats;
+
 class ConstantPool : public Metadata {
   friend class VMStructs;
-  friend class BytecodeInterpreter;  // Directly extracts an oop in the pool for fast instanceof/checkcast
+  friend class BytecodeInterpreter;  // Directly extracts a klass in the pool for fast instanceof/checkcast
   friend class Universe;             // For null constructor
  private:
   Array<u1>*           _tags;        // the tag array describing the constant pool's contents
@@ -747,13 +748,13 @@
   friend class SystemDictionary;
 
   // Used by compiler to prevent classloading.
-  static Method*          method_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static bool       has_appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static oop            appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static bool    has_method_type_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static oop         method_type_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static Klass*            klass_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static Klass*        klass_ref_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static Method*          method_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static bool       has_appendix_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static oop            appendix_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static bool    has_method_type_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static oop         method_type_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static Klass*            klass_at_if_loaded      (constantPoolHandle this_cp, int which);
+  static Klass*        klass_ref_at_if_loaded      (constantPoolHandle this_cp, int which);
 
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
   // future by other Java code. These take constant pool indices rather than
@@ -811,19 +812,19 @@
   }
 
   // Performs the LinkResolver checks
-  static void verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle klass, TRAPS);
+  static void verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle klass, TRAPS);
 
   // Implementation of methods that needs an exposed 'this' pointer, in order to
   // handle GC while executing the method
-  static Klass* klass_at_impl(constantPoolHandle this_oop, int which, TRAPS);
-  static oop string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS);
+  static Klass* klass_at_impl(constantPoolHandle this_cp, int which, TRAPS);
+  static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS);
 
   // Resolve string constants (to prevent allocation during compilation)
-  static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
+  static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS);
 
-  static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
-  static void save_and_throw_exception(constantPoolHandle this_oop, int which, int tag_value, TRAPS);
-  static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_oop, int index, TRAPS);
+  static oop resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS);
+  static void save_and_throw_exception(constantPoolHandle this_cp, int which, int tag_value, TRAPS);
+  static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS);
 
  public:
   // Merging ConstantPool* support:
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -328,7 +328,7 @@
   // the f1 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;',
   // not '(Ljava/lang/String;)Ljava/util/List;'.
   // The fact that String and List are involved is encoded in the MethodType in refs[f2].
-  // This allows us to create fewer method oops, while keeping type safety.
+  // This allows us to create fewer Methods, while keeping type safety.
   //
 
   objArrayHandle resolved_references = cpool->resolved_references();
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -102,8 +102,9 @@
 // _f1      = Method* for non-virtual calls, unused by virtual calls.
 //            for interface calls, which are essentially virtual but need a klass,
 //            contains Klass* for the corresponding interface.
-//            for invokedynamic, f1 contains a site-specific CallSite object (as an appendix)
-//            for invokehandle, f1 contains a site-specific MethodType object (as an appendix)
+//            for invokedynamic and invokehandle, f1 contains the adapter method which
+//            manages the actual call. The appendix is stored in the ConstantPool
+//            resolved_references array.
 //            (upcoming metadata changes will move the appendix to a separate array)
 // _f2      = vtable/itable index (or final Method*) for virtual calls only,
 //            unused by non-virtual.  The is_vfinal flag indicates this is a
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -432,8 +432,8 @@
     if (!InstanceKlass::cast(super)->is_initialized()) return;
 
     // call body to expose the this pointer
-    instanceKlassHandle this_oop(thread, this);
-    eager_initialize_impl(this_oop);
+    instanceKlassHandle this_k(thread, this);
+    eager_initialize_impl(this_k);
   }
 }
 
@@ -470,16 +470,16 @@
   assert(!is_not_initialized(), "class must be initialized now");
 }
 
-void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
+void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) {
   EXCEPTION_MARK;
-  oop init_lock = this_oop->init_lock();
+  oop init_lock = this_k->init_lock();
   ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
   // abort if someone beat us to the initialization
-  if (!this_oop->is_not_initialized()) return;  // note: not equivalent to is_initialized()
-
-  ClassState old_state = this_oop->init_state();
-  link_class_impl(this_oop, true, THREAD);
+  if (!this_k->is_not_initialized()) return;  // note: not equivalent to is_initialized()
+
+  ClassState old_state = this_k->init_state();
+  link_class_impl(this_k, true, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     // Abort if linking the class throws an exception.
@@ -487,16 +487,16 @@
     // Use a test to avoid redundantly resetting the state if there's
     // no change.  Set_init_state() asserts that state changes make
     // progress, whereas here we might just be spinning in place.
-    if( old_state != this_oop->_init_state )
-      this_oop->set_init_state (old_state);
+    if( old_state != this_k->_init_state )
+      this_k->set_init_state (old_state);
   } else {
     // linking successfull, mark class as initialized
-    this_oop->set_init_state (fully_initialized);
-    this_oop->fence_and_clear_init_lock();
+    this_k->set_init_state (fully_initialized);
+    this_k->fence_and_clear_init_lock();
     // trace
     if (TraceClassInitialization) {
       ResourceMark rm(THREAD);
-      tty->print_cr("[Initialized %s without side effects]", this_oop->external_name());
+      tty->print_cr("[Initialized %s without side effects]", this_k->external_name());
     }
   }
 }
@@ -508,8 +508,8 @@
 void InstanceKlass::initialize(TRAPS) {
   if (this->should_be_initialized()) {
     HandleMark hm(THREAD);
-    instanceKlassHandle this_oop(THREAD, this);
-    initialize_impl(this_oop, CHECK);
+    instanceKlassHandle this_k(THREAD, this);
+    initialize_impl(this_k, CHECK);
     // Note: at this point the class may be initialized
     //       OR it may be in the state of being initialized
     //       in case of recursive initialization!
@@ -520,11 +520,11 @@
 
 
 bool InstanceKlass::verify_code(
-    instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
+    instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
   // 1) Verify the bytecodes
   Verifier::Mode mode =
     throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
-  return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), CHECK_false);
+  return Verifier::verify(this_k, mode, this_k->should_verify_class(), CHECK_false);
 }
 
 
@@ -540,8 +540,8 @@
   assert(is_loaded(), "must be loaded");
   if (!is_linked()) {
     HandleMark hm(THREAD);
-    instanceKlassHandle this_oop(THREAD, this);
-    link_class_impl(this_oop, true, CHECK);
+    instanceKlassHandle this_k(THREAD, this);
+    link_class_impl(this_k, true, CHECK);
   }
 }
 
@@ -551,22 +551,22 @@
   assert(is_loaded(), "must be loaded");
   if (!is_linked()) {
     HandleMark hm(THREAD);
-    instanceKlassHandle this_oop(THREAD, this);
-    link_class_impl(this_oop, false, CHECK_false);
+    instanceKlassHandle this_k(THREAD, this);
+    link_class_impl(this_k, false, CHECK_false);
   }
   return is_linked();
 }
 
 bool InstanceKlass::link_class_impl(
-    instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
+    instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
   // check for error state
-  if (this_oop->is_in_error_state()) {
+  if (this_k->is_in_error_state()) {
     ResourceMark rm(THREAD);
     THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
-               this_oop->external_name(), false);
+               this_k->external_name(), false);
   }
   // return if already verified
-  if (this_oop->is_linked()) {
+  if (this_k->is_linked()) {
     return true;
   }
 
@@ -576,7 +576,7 @@
   JavaThread* jt = (JavaThread*)THREAD;
 
   // link super class before linking this class
-  instanceKlassHandle super(THREAD, this_oop->super());
+  instanceKlassHandle super(THREAD, this_k->super());
   if (super.not_null()) {
     if (super->is_interface()) {  // check if super class is an interface
       ResourceMark rm(THREAD);
@@ -584,7 +584,7 @@
         THREAD_AND_LOCATION,
         vmSymbols::java_lang_IncompatibleClassChangeError(),
         "class %s has interface %s as super class",
-        this_oop->external_name(),
+        this_k->external_name(),
         super->external_name()
       );
       return false;
@@ -594,7 +594,7 @@
   }
 
   // link all interfaces implemented by this class before linking this class
-  Array<Klass*>* interfaces = this_oop->local_interfaces();
+  Array<Klass*>* interfaces = this_k->local_interfaces();
   int num_interfaces = interfaces->length();
   for (int index = 0; index < num_interfaces; index++) {
     HandleMark hm(THREAD);
@@ -603,7 +603,7 @@
   }
 
   // in case the class is linked in the process of linking its superclasses
-  if (this_oop->is_linked()) {
+  if (this_k->is_linked()) {
     return true;
   }
 
@@ -618,14 +618,14 @@
 
   // verification & rewriting
   {
-    oop init_lock = this_oop->init_lock();
+    oop init_lock = this_k->init_lock();
     ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
     // rewritten will have been set if loader constraint error found
     // on an earlier link attempt
     // don't verify or rewrite if already rewritten
 
-    if (!this_oop->is_linked()) {
-      if (!this_oop->is_rewritten()) {
+    if (!this_k->is_linked()) {
+      if (!this_k->is_rewritten()) {
         {
           // Timer includes any side effects of class verification (resolution,
           // etc), but not recursive entry into verify_code().
@@ -635,7 +635,7 @@
                                    jt->get_thread_stat()->perf_recursion_counts_addr(),
                                    jt->get_thread_stat()->perf_timers_addr(),
                                    PerfClassTraceTime::CLASS_VERIFY);
-          bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
+          bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
           if (!verify_ok) {
             return false;
           }
@@ -644,39 +644,39 @@
         // Just in case a side-effect of verify linked this class already
         // (which can sometimes happen since the verifier loads classes
         // using custom class loaders, which are free to initialize things)
-        if (this_oop->is_linked()) {
+        if (this_k->is_linked()) {
           return true;
         }
 
         // also sets rewritten
-        this_oop->rewrite_class(CHECK_false);
+        this_k->rewrite_class(CHECK_false);
       }
 
       // relocate jsrs and link methods after they are all rewritten
-      this_oop->link_methods(CHECK_false);
+      this_k->link_methods(CHECK_false);
 
       // Initialize the vtable and interface table after
       // methods have been rewritten since rewrite may
       // fabricate new Method*s.
       // also does loader constraint checking
-      if (!this_oop()->is_shared()) {
+      if (!this_k()->is_shared()) {
         ResourceMark rm(THREAD);
-        this_oop->vtable()->initialize_vtable(true, CHECK_false);
-        this_oop->itable()->initialize_itable(true, CHECK_false);
+        this_k->vtable()->initialize_vtable(true, CHECK_false);
+        this_k->itable()->initialize_itable(true, CHECK_false);
       }
 #ifdef ASSERT
       else {
         ResourceMark rm(THREAD);
-        this_oop->vtable()->verify(tty, true);
+        this_k->vtable()->verify(tty, true);
         // In case itable verification is ever added.
-        // this_oop->itable()->verify(tty, true);
+        // this_k->itable()->verify(tty, true);
       }
 #endif
-      this_oop->set_init_state(linked);
+      this_k->set_init_state(linked);
       if (JvmtiExport::should_post_class_prepare()) {
         Thread *thread = THREAD;
         assert(thread->is_Java_thread(), "thread->is_Java_thread()");
-        JvmtiExport::post_class_prepare((JavaThread *) thread, this_oop());
+        JvmtiExport::post_class_prepare((JavaThread *) thread, this_k());
       }
     }
   }
@@ -689,13 +689,13 @@
 // verification but before the first method of the class is executed.
 void InstanceKlass::rewrite_class(TRAPS) {
   assert(is_loaded(), "must be loaded");
-  instanceKlassHandle this_oop(THREAD, this);
-  if (this_oop->is_rewritten()) {
-    assert(this_oop()->is_shared(), "rewriting an unshared class?");
+  instanceKlassHandle this_k(THREAD, this);
+  if (this_k->is_rewritten()) {
+    assert(this_k()->is_shared(), "rewriting an unshared class?");
     return;
   }
-  Rewriter::rewrite(this_oop, CHECK);
-  this_oop->set_rewritten();
+  Rewriter::rewrite(this_k, CHECK);
+  this_k->set_rewritten();
 }
 
 // Now relocate and link method entry points after class is rewritten.
@@ -729,19 +729,19 @@
 }
 
 
-void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
+void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) {
   // Make sure klass is linked (verified) before initialization
   // A class could already be verified, since it has been reflected upon.
-  this_oop->link_class(CHECK);
-
-  DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);
+  this_k->link_class(CHECK);
+
+  DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_k()), -1);
 
   bool wait = false;
 
   // refer to the JVM book page 47 for description of steps
   // Step 1
   {
-    oop init_lock = this_oop->init_lock();
+    oop init_lock = this_k->init_lock();
     ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
     Thread *self = THREAD; // it's passed the current thread
@@ -750,29 +750,29 @@
     // If we were to use wait() instead of waitInterruptibly() then
     // we might end up throwing IE from link/symbol resolution sites
     // that aren't expected to throw.  This would wreak havoc.  See 6320309.
-    while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
+    while(this_k->is_being_initialized() && !this_k->is_reentrant_initialization(self)) {
         wait = true;
       ol.waitUninterruptibly(CHECK);
     }
 
     // Step 3
-    if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
-      DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);
+    if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) {
+      DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_k()), -1,wait);
       return;
     }
 
     // Step 4
-    if (this_oop->is_initialized()) {
-      DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
+    if (this_k->is_initialized()) {
+      DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_k()), -1,wait);
       return;
     }
 
     // Step 5
-    if (this_oop->is_in_error_state()) {
-      DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);
+    if (this_k->is_in_error_state()) {
+      DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_k()), -1,wait);
       ResourceMark rm(THREAD);
       const char* desc = "Could not initialize class ";
-      const char* className = this_oop->external_name();
+      const char* className = this_k->external_name();
       size_t msglen = strlen(desc) + strlen(className) + 1;
       char* message = NEW_RESOURCE_ARRAY(char, msglen);
       if (NULL == message) {
@@ -785,13 +785,13 @@
     }
 
     // Step 6
-    this_oop->set_init_state(being_initialized);
-    this_oop->set_init_thread(self);
+    this_k->set_init_state(being_initialized);
+    this_k->set_init_thread(self);
   }
 
   // Step 7
-  Klass* super_klass = this_oop->super();
-  if (super_klass != NULL && !this_oop->is_interface() && super_klass->should_be_initialized()) {
+  Klass* super_klass = this_k->super();
+  if (super_klass != NULL && !this_k->is_interface() && super_klass->should_be_initialized()) {
     super_klass->initialize(THREAD);
 
     if (HAS_PENDING_EXCEPTION) {
@@ -799,18 +799,18 @@
       CLEAR_PENDING_EXCEPTION;
       {
         EXCEPTION_MARK;
-        this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
+        this_k->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
         CLEAR_PENDING_EXCEPTION;   // ignore any exception thrown, superclass initialization error is thrown below
       }
-      DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);
+      DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_k()), -1,wait);
       THROW_OOP(e());
     }
   }
 
-  if (this_oop->has_default_methods()) {
+  if (this_k->has_default_methods()) {
     // Step 7.5: initialize any interfaces which have default methods
-    for (int i = 0; i < this_oop->local_interfaces()->length(); ++i) {
-      Klass* iface = this_oop->local_interfaces()->at(i);
+    for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
+      Klass* iface = this_k->local_interfaces()->at(i);
       InstanceKlass* ik = InstanceKlass::cast(iface);
       if (ik->has_default_methods() && ik->should_be_initialized()) {
         ik->initialize(THREAD);
@@ -821,7 +821,7 @@
           {
             EXCEPTION_MARK;
             // Locks object, set state, and notify all waiting threads
-            this_oop->set_initialization_state_and_notify(
+            this_k->set_initialization_state_and_notify(
                 initialization_error, THREAD);
 
             // ignore any exception thrown, superclass initialization error is
@@ -829,7 +829,7 @@
             CLEAR_PENDING_EXCEPTION;
           }
           DTRACE_CLASSINIT_PROBE_WAIT(
-              super__failed, InstanceKlass::cast(this_oop()), -1, wait);
+              super__failed, InstanceKlass::cast(this_k()), -1, wait);
           THROW_OOP(e());
         }
       }
@@ -840,7 +840,7 @@
   {
     assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
     JavaThread* jt = (JavaThread*)THREAD;
-    DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);
+    DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_k()), -1,wait);
     // Timer includes any side effects of class initialization (resolution,
     // etc), but not recursive entry into call_class_initializer().
     PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
@@ -849,14 +849,14 @@
                              jt->get_thread_stat()->perf_recursion_counts_addr(),
                              jt->get_thread_stat()->perf_timers_addr(),
                              PerfClassTraceTime::CLASS_CLINIT);
-    this_oop->call_class_initializer(THREAD);
+    this_k->call_class_initializer(THREAD);
   }
 
   // Step 9
   if (!HAS_PENDING_EXCEPTION) {
-    this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
+    this_k->set_initialization_state_and_notify(fully_initialized, CHECK);
     { ResourceMark rm(THREAD);
-      debug_only(this_oop->vtable()->verify(tty, true);)
+      debug_only(this_k->vtable()->verify(tty, true);)
     }
   }
   else {
@@ -868,13 +868,13 @@
     JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
     {
       EXCEPTION_MARK;
-      this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
+      this_k->set_initialization_state_and_notify(initialization_error, THREAD);
       CLEAR_PENDING_EXCEPTION;   // ignore any exception thrown, class initialization error is thrown below
       // JVMTI has already reported the pending exception
       // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
       JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
     }
-    DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);
+    DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_k()), -1,wait);
     if (e->is_a(SystemDictionary::Error_klass())) {
       THROW_OOP(e());
     } else {
@@ -884,7 +884,7 @@
                 &args);
     }
   }
-  DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);
+  DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_k()), -1,wait);
 }
 
 
@@ -894,11 +894,11 @@
   set_initialization_state_and_notify_impl(kh, state, CHECK);
 }
 
-void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
-  oop init_lock = this_oop->init_lock();
+void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) {
+  oop init_lock = this_k->init_lock();
   ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
-  this_oop->set_init_state(state);
-  this_oop->fence_and_clear_init_lock();
+  this_k->set_init_state(state);
+  this_k->fence_and_clear_init_lock();
   ol.notify_all(CHECK);
 }
 
@@ -952,12 +952,11 @@
 
 void InstanceKlass::process_interfaces(Thread *thread) {
   // link this class into the implementors list of every interface it implements
-  Klass* this_as_klass_oop = this;
   for (int i = local_interfaces()->length() - 1; i >= 0; i--) {
     assert(local_interfaces()->at(i)->is_klass(), "must be a klass");
     InstanceKlass* interf = InstanceKlass::cast(local_interfaces()->at(i));
     assert(interf->is_interface(), "expected interface");
-    interf->add_implementor(this_as_klass_oop);
+    interf->add_implementor(this);
   }
 }
 
@@ -1083,12 +1082,12 @@
 }
 
 Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) {
-  instanceKlassHandle this_oop(THREAD, this);
-  return array_klass_impl(this_oop, or_null, n, THREAD);
+  instanceKlassHandle this_k(THREAD, this);
+  return array_klass_impl(this_k, or_null, n, THREAD);
 }
 
-Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_oop, bool or_null, int n, TRAPS) {
-  if (this_oop->array_klasses() == NULL) {
+Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_k, bool or_null, int n, TRAPS) {
+  if (this_k->array_klasses() == NULL) {
     if (or_null) return NULL;
 
     ResourceMark rm;
@@ -1099,14 +1098,14 @@
       MutexLocker ma(MultiArray_lock, THREAD);
 
       // Check if update has already taken place
-      if (this_oop->array_klasses() == NULL) {
-        Klass*    k = ObjArrayKlass::allocate_objArray_klass(this_oop->class_loader_data(), 1, this_oop, CHECK_NULL);
-        this_oop->set_array_klasses(k);
+      if (this_k->array_klasses() == NULL) {
+        Klass*    k = ObjArrayKlass::allocate_objArray_klass(this_k->class_loader_data(), 1, this_k, CHECK_NULL);
+        this_k->set_array_klasses(k);
       }
     }
   }
   // _this will always be set at this point
-  ObjArrayKlass* oak = (ObjArrayKlass*)this_oop->array_klasses();
+  ObjArrayKlass* oak = (ObjArrayKlass*)this_k->array_klasses();
   if (or_null) {
     return oak->array_klass_or_null(n);
   }
@@ -1133,20 +1132,20 @@
   return NULL;
 }
 
-void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) {
+void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAPS) {
   if (ReplayCompiles &&
       (ReplaySuppressInitializers == 1 ||
-       ReplaySuppressInitializers >= 2 && this_oop->class_loader() != NULL)) {
+       ReplaySuppressInitializers >= 2 && this_k->class_loader() != NULL)) {
     // Hide the existence of the initializer for the purpose of replaying the compile
     return;
   }
 
-  methodHandle h_method(THREAD, this_oop->class_initializer());
-  assert(!this_oop->is_initialized(), "we cannot initialize twice");
+  methodHandle h_method(THREAD, this_k->class_initializer());
+  assert(!this_k->is_initialized(), "we cannot initialize twice");
   if (TraceClassInitialization) {
     tty->print("%d Initializing ", call_class_initializer_impl_counter++);
-    this_oop->name()->print_value();
-    tty->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", (address)this_oop());
+    this_k->name()->print_value();
+    tty->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", (address)this_k());
   }
   if (h_method() != NULL) {
     JavaCallArguments args; // No arguments
@@ -1296,8 +1295,8 @@
 }
 
 
-void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
-  for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) {
+void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
+  for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) {
     if (fs.access_flags().is_static()) {
       fieldDescriptor& fd = fs.field_descriptor();
       f(&fd, CHECK);
@@ -1515,14 +1514,14 @@
 }
 
 /* jni_id_for_impl for jfieldIds only */
-JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_oop, int offset) {
+JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_k, int offset) {
   MutexLocker ml(JfieldIdCreation_lock);
   // Retry lookup after we got the lock
-  JNIid* probe = this_oop->jni_ids() == NULL ? NULL : this_oop->jni_ids()->find(offset);
+  JNIid* probe = this_k->jni_ids() == NULL ? NULL : this_k->jni_ids()->find(offset);
   if (probe == NULL) {
     // Slow case, allocate new static field identifier
-    probe = new JNIid(this_oop(), offset, this_oop->jni_ids());
-    this_oop->set_jni_ids(probe);
+    probe = new JNIid(this_k(), offset, this_k->jni_ids());
+    this_k->set_jni_ids(probe);
   }
   return probe;
 }
@@ -3161,8 +3160,8 @@
   }
 
   // Verify first subklass
-  if (subklass_oop() != NULL) {
-    guarantee(subklass_oop()->is_klass(), "should be klass");
+  if (subklass() != NULL) {
+    guarantee(subklass()->is_klass(), "should be klass");
   }
 
   // Verify siblings
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -43,35 +43,7 @@
 // An InstanceKlass is the VM level representation of a Java class.
 // It contains all information needed for at class at execution runtime.
 
-//  InstanceKlass layout:
-//    [C++ vtbl pointer           ] Klass
-//    [subtype cache              ] Klass
-//    [instance size              ] Klass
-//    [java mirror                ] Klass
-//    [super                      ] Klass
-//    [access_flags               ] Klass
-//    [name                       ] Klass
-//    [first subklass             ] Klass
-//    [next sibling               ] Klass
-//    [array klasses              ]
-//    [methods                    ]
-//    [local interfaces           ]
-//    [transitive interfaces      ]
-//    [fields                     ]
-//    [constants                  ]
-//    [class loader               ]
-//    [source file name           ]
-//    [inner classes              ]
-//    [static field size          ]
-//    [nonstatic field size       ]
-//    [static oop fields size     ]
-//    [nonstatic oop maps size    ]
-//    [has finalize method        ]
-//    [deoptimization mark bit    ]
-//    [initialization state       ]
-//    [initializing thread        ]
-//    [Java vtable length         ]
-//    [oop map cache (stack maps) ]
+//  InstanceKlass embedded field layout (after declared fields):
 //    [EMBEDDED Java vtable             ] size in words = vtable_len
 //    [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
 //      The embedded nonstatic oop-map blocks are short pairs (offset, length)
@@ -1031,16 +1003,16 @@
 
   // Static methods that are used to implement member methods where an exposed this pointer
   // is needed due to possible GCs
-  static bool link_class_impl                           (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
-  static bool verify_code                               (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
-  static void initialize_impl                           (instanceKlassHandle this_oop, TRAPS);
-  static void eager_initialize_impl                     (instanceKlassHandle this_oop);
-  static void set_initialization_state_and_notify_impl  (instanceKlassHandle this_oop, ClassState state, TRAPS);
-  static void call_class_initializer_impl               (instanceKlassHandle this_oop, TRAPS);
-  static Klass* array_klass_impl                      (instanceKlassHandle this_oop, bool or_null, int n, TRAPS);
-  static void do_local_static_fields_impl               (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS);
+  static bool link_class_impl                           (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
+  static bool verify_code                               (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
+  static void initialize_impl                           (instanceKlassHandle this_k, TRAPS);
+  static void eager_initialize_impl                     (instanceKlassHandle this_k);
+  static void set_initialization_state_and_notify_impl  (instanceKlassHandle this_k, ClassState state, TRAPS);
+  static void call_class_initializer_impl               (instanceKlassHandle this_k, TRAPS);
+  static Klass* array_klass_impl                        (instanceKlassHandle this_k, bool or_null, int n, TRAPS);
+  static void do_local_static_fields_impl               (instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS);
   /* jni_id_for_impl for jfieldID only */
-  static JNIid* jni_id_for_impl                         (instanceKlassHandle this_oop, int offset);
+  static JNIid* jni_id_for_impl                         (instanceKlassHandle this_k, int offset);
 
   // Returns the array class for the n'th dimension
   Klass* array_klass_impl(bool or_null, int n, TRAPS);
--- a/hotspot/src/share/vm/oops/klass.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -334,19 +334,11 @@
 }
 
 
-Klass* Klass::subklass() const {
-  return _subklass == NULL ? NULL : _subklass;
-}
-
 InstanceKlass* Klass::superklass() const {
   assert(super() == NULL || super()->oop_is_instance(), "must be instance klass");
   return _super == NULL ? NULL : InstanceKlass::cast(_super);
 }
 
-Klass* Klass::next_sibling() const {
-  return _next_sibling == NULL ? NULL : _next_sibling;
-}
-
 void Klass::set_subklass(Klass* s) {
   assert(s != this, "sanity check");
   _subklass = s;
@@ -365,7 +357,7 @@
   assert((!super->is_interface()    // interfaces cannot be supers
           && (super->superklass() == NULL || !is_interface())),
          "an interface can only be a subklass of Object");
-  Klass* prev_first_subklass = super->subklass_oop();
+  Klass* prev_first_subklass = super->subklass();
   if (prev_first_subklass != NULL) {
     // set our sibling to be the superklass' previous first subklass
     set_next_sibling(prev_first_subklass);
@@ -405,7 +397,7 @@
     assert(current->is_loader_alive(is_alive), "just checking, this should be live");
 
     // Find and set the first alive subklass
-    Klass* sub = current->subklass_oop();
+    Klass* sub = current->subklass();
     while (sub != NULL && !sub->is_loader_alive(is_alive)) {
 #ifndef PRODUCT
       if (TraceClassUnloading && WizardMode) {
@@ -413,7 +405,7 @@
         tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name());
       }
 #endif
-      sub = sub->next_sibling_oop();
+      sub = sub->next_sibling();
     }
     current->set_subklass(sub);
     if (sub != NULL) {
@@ -421,13 +413,13 @@
     }
 
     // Find and set the first alive sibling
-    Klass* sibling = current->next_sibling_oop();
+    Klass* sibling = current->next_sibling();
     while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
       if (TraceClassUnloading && WizardMode) {
         ResourceMark rm;
         tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name());
       }
-      sibling = sibling->next_sibling_oop();
+      sibling = sibling->next_sibling();
     }
     current->set_next_sibling(sibling);
     if (sibling != NULL) {
--- a/hotspot/src/share/vm/oops/klass.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -56,34 +56,6 @@
 // actual type.  (See oop.inline.hpp for some of the forwarding code.)
 // ALL FUNCTIONS IMPLEMENTING THIS DISPATCH ARE PREFIXED WITH "oop_"!
 
-//  Klass layout:
-//    [C++ vtbl ptr  ] (contained in Metadata)
-//    [layout_helper ]
-//    [super_check_offset   ] for fast subtype checks
-//    [name          ]
-//    [secondary_super_cache] for fast subtype checks
-//    [secondary_supers     ] array of 2ndary supertypes
-//    [primary_supers 0]
-//    [primary_supers 1]
-//    [primary_supers 2]
-//    ...
-//    [primary_supers 7]
-//    [java_mirror   ]
-//    [super         ]
-//    [subklass      ] first subclass
-//    [next_sibling  ] link to chain additional subklasses
-//    [next_link     ]
-//    [class_loader_data]
-//    [modifier_flags]
-//    [access_flags  ]
-//    [last_biased_lock_bulk_revocation_time] (64 bits)
-//    [prototype_header]
-//    [biased_lock_revocation_count]
-//    [_modified_oops]
-//    [_accumulated_modified_oops]
-//    [trace_id]
-
-
 // Forward declarations.
 template <class T> class Array;
 template <class T> class GrowableArray;
@@ -257,9 +229,9 @@
   // Use InstanceKlass::contains_field_offset to classify field offsets.
 
   // sub/superklass links
+  Klass* subklass() const              { return _subklass; }
+  Klass* next_sibling() const          { return _next_sibling; }
   InstanceKlass* superklass() const;
-  Klass* subklass() const;
-  Klass* next_sibling() const;
   void append_to_sibling_list();           // add newly created receiver to superklass' subklass list
 
   void set_next_link(Klass* k) { _next_link = k; }
@@ -281,8 +253,6 @@
   bool has_accumulated_modified_oops()   { return _accumulated_modified_oops == 1; }
 
  protected:                                // internal accessors
-  Klass* subklass_oop() const            { return _subklass; }
-  Klass* next_sibling_oop() const        { return _next_sibling; }
   void     set_subklass(Klass* s);
   void     set_next_sibling(Klass* s);
 
--- a/hotspot/src/share/vm/oops/method.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -273,7 +273,7 @@
 }
 
 address Method::bcp_from(int bci) const {
-  assert((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci");
+  assert((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()), err_msg("illegal bci: %d", bci));
   address bcp = code_base() + bci;
   assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
   return bcp;
@@ -329,14 +329,12 @@
   }
 }
 
-#ifndef PRODUCT
 void Method::print_invocation_count() {
   if (is_static()) tty->print("static ");
   if (is_final()) tty->print("final ");
   if (is_synchronized()) tty->print("synchronized ");
   if (is_native()) tty->print("native ");
-  method_holder()->name()->print_symbol_on(tty);
-  tty->print(".");
+  tty->print("%s::", method_holder()->external_name());
   name()->print_symbol_on(tty);
   signature()->print_symbol_on(tty);
 
@@ -349,12 +347,12 @@
   tty->print_cr ("  interpreter_invocation_count: %8d ", interpreter_invocation_count());
   tty->print_cr ("  invocation_counter:           %8d ", invocation_count());
   tty->print_cr ("  backedge_counter:             %8d ", backedge_count());
+#ifndef PRODUCT
   if (CountCompiledCalls) {
     tty->print_cr ("  compiled_invocation_count: %8d ", compiled_invocation_count());
   }
-
+#endif
 }
-#endif
 
 // Build a MethodData* object to hold information about this method
 // collected in the interpreter.
@@ -577,12 +575,12 @@
 }
 
 
-objArrayHandle Method::resolved_checked_exceptions_impl(Method* this_oop, TRAPS) {
-  int length = this_oop->checked_exceptions_length();
+objArrayHandle Method::resolved_checked_exceptions_impl(Method* method, TRAPS) {
+  int length = method->checked_exceptions_length();
   if (length == 0) {  // common case
     return objArrayHandle(THREAD, Universe::the_empty_class_klass_array());
   } else {
-    methodHandle h_this(THREAD, this_oop);
+    methodHandle h_this(THREAD, method);
     objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle()));
     objArrayHandle mirrors (THREAD, m_oop);
     for (int i = 0; i < length; i++) {
@@ -1443,10 +1441,6 @@
 #endif // !PRODUCT || INCLUDE_JVMTI
 
 
-//-----------------------------------------------------------------------------------
-// Non-product code
-
-#ifndef PRODUCT
 void Method::print_codes_on(outputStream* st) const {
   print_codes_on(0, code_size(), st);
 }
@@ -1460,7 +1454,6 @@
   BytecodeTracer::set_closure(BytecodeTracer::std_closure());
   while (s.next() >= 0) BytecodeTracer::trace(mh, s.bcp(), st);
 }
-#endif // not PRODUCT
 
 
 // Simple compression of line number tables. We use a regular compressed stream, except that we compress deltas
--- a/hotspot/src/share/vm/oops/method.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -40,50 +40,15 @@
 
 // A Method represents a Java method.
 //
-// Memory layout (each line represents a word). Note that most applications load thousands of methods,
-// so keeping the size of this structure small has a big impact on footprint.
-//
-// The actual bytecodes are inlined after the end of the Method struct.
-//
-// There are bits in the access_flags telling whether inlined tables are present.
-// Note that accessing the line number and local variable tables is not performance critical at all.
-// Accessing the checked exceptions table is used by reflection, so we put that last to make access
-// to it fast.
-//
-// The line number table is compressed and inlined following the byte codes. It is found as the first
-// byte following the byte codes. The checked exceptions table and the local variable table are inlined
-// after the line number table, and indexed from the end of the method. We do not compress the checked
-// exceptions table since the average length is less than 2, and do not bother to compress the local
-// variable table either since it is mostly absent.
-//
-// Note that native_function and signature_handler has to be at fixed offsets (required by the interpreter)
+// Note that most applications load thousands of methods, so keeping the size of this
+// class small has a big impact on footprint.
 //
-// |------------------------------------------------------|
-// | header                                               |
-// | klass                                                |
-// |------------------------------------------------------|
-// | ConstMethod*                   (metadata)            |
-// |------------------------------------------------------|
-// | MethodData*                    (metadata)            |
-// | MethodCounters                                       |
-// |------------------------------------------------------|
-// | access_flags                                         |
-// | vtable_index                                         |
-// |------------------------------------------------------|
-// | result_index (C++ interpreter only)                  |
-// |------------------------------------------------------|
-// | method_size             | intrinsic_id  |   flags    |
-// |------------------------------------------------------|
-// | code                           (pointer)             |
-// | i2i                            (pointer)             |
-// | adapter                        (pointer)             |
-// | from_compiled_entry            (pointer)             |
-// | from_interpreted_entry         (pointer)             |
-// |------------------------------------------------------|
-// | native_function       (present only if native)       |
-// | signature_handler     (present only if native)       |
-// |------------------------------------------------------|
-
+// Note that native_function and signature_handler have to be at fixed offsets
+// (required by the interpreter)
+//
+//  Method embedded field layout (after declared fields):
+//   [EMBEDDED native_function       (present only if native) ]
+//   [EMBEDDED signature_handler     (present only if native) ]
 
 class CheckedExceptionElement;
 class LocalVariableTableElement;
@@ -429,6 +394,9 @@
 #ifndef PRODUCT
   int  compiled_invocation_count() const         { return _compiled_invocation_count;  }
   void set_compiled_invocation_count(int count)  { _compiled_invocation_count = count; }
+#else
+  // for PrintMethodData in a product build
+  int  compiled_invocation_count() const         { return 0;  }
 #endif // not PRODUCT
 
   // Clear (non-shared space) pointers which could not be relevant
@@ -497,10 +465,8 @@
   // Interpreter oopmap support
   void mask_for(int bci, InterpreterOopMap* mask);
 
-#ifndef PRODUCT
   // operations on invocation counter
   void print_invocation_count();
-#endif
 
   // byte codes
   void    set_code(address code)      { return constMethod()->set_code(code); }
@@ -509,8 +475,8 @@
 
   // prints byte codes
   void print_codes() const            { print_codes_on(tty); }
-  void print_codes_on(outputStream* st) const                      PRODUCT_RETURN;
-  void print_codes_on(int from, int to, outputStream* st) const    PRODUCT_RETURN;
+  void print_codes_on(outputStream* st) const;
+  void print_codes_on(int from, int to, outputStream* st) const;
 
   // method parameters
   bool has_method_parameters() const
@@ -661,7 +627,7 @@
 
   // Static methods that are used to implement member methods where an exposed this pointer
   // is needed due to possible GCs
-  static objArrayHandle resolved_checked_exceptions_impl(Method* this_oop, TRAPS);
+  static objArrayHandle resolved_checked_exceptions_impl(Method* method, TRAPS);
 
   // Returns the byte code index from the byte code pointer
   int     bci_from(address bcp) const;
--- a/hotspot/src/share/vm/oops/methodData.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "compiler/compilerOracle.hpp"
 #include "interpreter/bytecode.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -114,7 +115,6 @@
   print_data_on(st, print_data_on_helper(md));
 }
 
-#ifndef PRODUCT
 void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const {
   st->print("bci: %d", bci());
   st->fill_to(tab_width_one);
@@ -137,7 +137,6 @@
 void ProfileData::tab(outputStream* st, bool first) const {
   st->fill_to(first ? tab_width_one : tab_width_two);
 }
-#endif // !PRODUCT
 
 // ==================================================================
 // BitData
@@ -146,23 +145,19 @@
 // whether a checkcast bytecode has seen a null value.
 
 
-#ifndef PRODUCT
 void BitData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "BitData", extra);
 }
-#endif // !PRODUCT
 
 // ==================================================================
 // CounterData
 //
 // A CounterData corresponds to a simple counter.
 
-#ifndef PRODUCT
 void CounterData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "CounterData", extra);
   st->print_cr("count(%u)", count());
 }
-#endif // !PRODUCT
 
 // ==================================================================
 // JumpData
@@ -187,12 +182,10 @@
   set_displacement(offset);
 }
 
-#ifndef PRODUCT
 void JumpData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "JumpData", extra);
   st->print_cr("taken(%u) displacement(%d)", taken(), displacement());
 }
-#endif // !PRODUCT
 
 int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
   // Parameter profiling include the receiver
@@ -341,7 +334,6 @@
   return MethodData::profile_arguments();
 }
 
-#ifndef PRODUCT
 void TypeEntries::print_klass(outputStream* st, intptr_t k) {
   if (is_type_none(k)) {
     st->print("none");
@@ -397,7 +389,6 @@
     _ret.print_data_on(st);
   }
 }
-#endif
 
 // ==================================================================
 // ReceiverTypeData
@@ -416,7 +407,6 @@
   }
 }
 
-#ifndef PRODUCT
 void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
   uint row;
   int entries = 0;
@@ -446,7 +436,6 @@
   print_shared(st, "VirtualCallData", extra);
   print_receiver_data_on(st);
 }
-#endif // !PRODUCT
 
 // ==================================================================
 // RetData
@@ -498,7 +487,6 @@
 }
 #endif // CC_INTERP
 
-#ifndef PRODUCT
 void RetData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "RetData", extra);
   uint row;
@@ -515,7 +503,6 @@
     }
   }
 }
-#endif // !PRODUCT
 
 // ==================================================================
 // BranchData
@@ -533,7 +520,6 @@
   set_displacement(offset);
 }
 
-#ifndef PRODUCT
 void BranchData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "BranchData", extra);
   st->print_cr("taken(%u) displacement(%d)",
@@ -541,7 +527,6 @@
   tab(st);
   st->print_cr("not taken(%u)", not_taken());
 }
-#endif
 
 // ==================================================================
 // MultiBranchData
@@ -607,7 +592,6 @@
   }
 }
 
-#ifndef PRODUCT
 void MultiBranchData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "MultiBranchData", extra);
   st->print_cr("default_count(%u) displacement(%d)",
@@ -619,9 +603,7 @@
                  count_at(i), displacement_at(i));
   }
 }
-#endif
 
-#ifndef PRODUCT
 void ArgInfoData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "ArgInfoData", extra);
   int nargs = number_of_args();
@@ -631,8 +613,6 @@
   st->cr();
 }
 
-#endif
-
 int ParametersTypeData::compute_cell_count(Method* m) {
   if (!MethodData::profile_parameters_for_method(m)) {
     return 0;
@@ -653,7 +633,6 @@
   return MethodData::profile_parameters();
 }
 
-#ifndef PRODUCT
 void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const {
   st->print("parameter types", extra);
   _parameters.print_data_on(st);
@@ -665,7 +644,6 @@
   method()->print_short_name(st);
   st->cr();
 }
-#endif
 
 // ==================================================================
 // MethodData*
@@ -800,6 +778,8 @@
   case Bytecodes::_invokeinterface:
   case Bytecodes::_if_acmpeq:
   case Bytecodes::_if_acmpne:
+  case Bytecodes::_ifnull:
+  case Bytecodes::_ifnonnull:
   case Bytecodes::_invokestatic:
 #ifdef COMPILER2
     return UseTypeSpeculation;
@@ -1153,6 +1133,21 @@
   _highest_osr_comp_level = 0;
   _would_profile = true;
 
+#if INCLUDE_RTM_OPT
+  _rtm_state = NoRTM; // No RTM lock eliding by default
+  if (UseRTMLocking &&
+      !CompilerOracle::has_option_string(_method, "NoRTMLockEliding")) {
+    if (CompilerOracle::has_option_string(_method, "UseRTMLockEliding") || !UseRTMDeopt) {
+      // Generate RTM lock eliding code without abort ratio calculation code.
+      _rtm_state = UseRTM;
+    } else if (UseRTMDeopt) {
+      // Generate RTM lock eliding code and include abort ratio calculation
+      // code if UseRTMDeopt is on.
+      _rtm_state = ProfileRTM;
+    }
+  }
+#endif
+
   // Initialize flags and trap history.
   _nof_decompiles = 0;
   _nof_overflow_recompiles = 0;
@@ -1341,8 +1336,6 @@
 
 // Printing
 
-#ifndef PRODUCT
-
 void MethodData::print_on(outputStream* st) const {
   assert(is_methodData(), "should be method data");
   st->print("method data for ");
@@ -1351,15 +1344,12 @@
   print_data_on(st);
 }
 
-#endif //PRODUCT
-
 void MethodData::print_value_on(outputStream* st) const {
   assert(is_methodData(), "should be method data");
   st->print("method data for ");
   method()->print_value_on(st);
 }
 
-#ifndef PRODUCT
 void MethodData::print_data_on(outputStream* st) const {
   ResourceMark rm;
   ProfileData* data = first_data();
@@ -1400,7 +1390,6 @@
     if (dp >= end) return;
   }
 }
-#endif
 
 #if INCLUDE_SERVICES
 // Size Statistics
--- a/hotspot/src/share/vm/oops/methodData.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -280,12 +280,10 @@
   friend class ReturnTypeEntry;
   friend class TypeStackSlotEntries;
 private:
-#ifndef PRODUCT
   enum {
     tab_width_one = 16,
     tab_width_two = 36
   };
-#endif // !PRODUCT
 
   // This is a pointer to a section of profiling data.
   DataLayout* _data;
@@ -521,10 +519,8 @@
 
   void print_data_on(outputStream* st, const MethodData* md) const;
 
-#ifndef PRODUCT
   void print_shared(outputStream* st, const char* name, const char* extra) const;
   void tab(outputStream* st, bool first = false) const;
-#endif
 };
 
 // BitData
@@ -583,9 +579,7 @@
   }
 #endif // CC_INTERP
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // CounterData
@@ -646,9 +640,7 @@
   }
 #endif // CC_INTERP
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // JumpData
@@ -733,9 +725,7 @@
   // Specific initialization.
   void post_initialize(BytecodeStream* stream, MethodData* mdo);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // Entries in a ProfileData object to record types: it can either be
@@ -808,9 +798,7 @@
     return with_status((intptr_t)k, in);
   }
 
-#ifndef PRODUCT
   static void print_klass(outputStream* st, intptr_t k);
-#endif
 
   // GC support
   static bool is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p);
@@ -919,9 +907,7 @@
   // GC support
   void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st) const;
-#endif
 };
 
 // Type entry used for return from a call. A single cell to record the
@@ -964,9 +950,7 @@
   // GC support
   void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st) const;
-#endif
 };
 
 // Entries to collect type information at a call: contains arguments
@@ -1144,9 +1128,7 @@
     }
   }
 
-#ifndef PRODUCT
   virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // ReceiverTypeData
@@ -1288,10 +1270,8 @@
   }
 #endif // CC_INTERP
 
-#ifndef PRODUCT
   void print_receiver_data_on(outputStream* st) const;
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // VirtualCallData
@@ -1332,9 +1312,7 @@
   }
 #endif // CC_INTERP
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // VirtualCallTypeData
@@ -1458,9 +1436,7 @@
     }
   }
 
-#ifndef PRODUCT
   virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // RetData
@@ -1561,9 +1537,7 @@
   // Specific initialization.
   void post_initialize(BytecodeStream* stream, MethodData* mdo);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // BranchData
@@ -1639,9 +1613,7 @@
   // Specific initialization.
   void post_initialize(BytecodeStream* stream, MethodData* mdo);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // ArrayData
@@ -1832,9 +1804,7 @@
   // Specific initialization.
   void post_initialize(BytecodeStream* stream, MethodData* mdo);
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 class ArgInfoData : public ArrayData {
@@ -1859,9 +1829,7 @@
     array_set_int_at(arg, val);
   }
 
-#ifndef PRODUCT
   void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // ParametersTypeData
@@ -1920,9 +1888,7 @@
     _parameters.clean_weak_klass_links(is_alive_closure);
   }
 
-#ifndef PRODUCT
   virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 
   static ByteSize stack_slot_offset(int i) {
     return cell_offset(stack_slot_local_offset(i));
@@ -1976,9 +1942,7 @@
     set_intptr_at(method_offset, (intptr_t)m);
   }
 
-#ifndef PRODUCT
   virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
 };
 
 // MethodData*
@@ -2052,7 +2016,7 @@
 
   // Whole-method sticky bits and flags
   enum {
-    _trap_hist_limit    = 18,   // decoupled from Deoptimization::Reason_LIMIT
+    _trap_hist_limit    = 20,   // decoupled from Deoptimization::Reason_LIMIT
     _trap_hist_mask     = max_jubyte,
     _extra_data_count   = 4     // extra DataLayout headers, for trap history
   }; // Public flag values
@@ -2083,6 +2047,12 @@
   // Counter values at the time profiling started.
   int               _invocation_counter_start;
   int               _backedge_counter_start;
+
+#if INCLUDE_RTM_OPT
+  // State of RTM code generation during compilation of the method
+  int               _rtm_state;
+#endif
+
   // Number of loops and blocks is computed when compiling the first
   // time with C1. It is used to determine if method is trivial.
   short             _num_loops;
@@ -2246,6 +2216,22 @@
   InvocationCounter* invocation_counter()     { return &_invocation_counter; }
   InvocationCounter* backedge_counter()       { return &_backedge_counter;   }
 
+#if INCLUDE_RTM_OPT
+  int rtm_state() const {
+    return _rtm_state;
+  }
+  void set_rtm_state(RTMState rstate) {
+    _rtm_state = (int)rstate;
+  }
+  void atomic_set_rtm_state(RTMState rstate) {
+    Atomic::store((int)rstate, &_rtm_state);
+  }
+
+  static int rtm_state_offset_in_bytes() {
+    return offset_of(MethodData, _rtm_state);
+  }
+#endif
+
   void set_would_profile(bool p)              { _would_profile = p;    }
   bool would_profile() const                  { return _would_profile; }
 
@@ -2435,15 +2421,11 @@
   void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; }
 
   // Printing
-#ifndef PRODUCT
   void print_on      (outputStream* st) const;
-#endif
   void print_value_on(outputStream* st) const;
 
-#ifndef PRODUCT
   // printing support for method data
   void print_data_on(outputStream* st) const;
-#endif
 
   const char* internal_name() const { return "{method data}"; }
 
--- a/hotspot/src/share/vm/opto/addnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/addnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/connode.hpp"
 #include "opto/machnode.hpp"
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -446,6 +446,9 @@
   diagnostic(bool, PrintPreciseBiasedLockingStatistics, false,              \
           "Print per-lock-site statistics of biased locking in JVM")        \
                                                                             \
+  diagnostic(bool, PrintPreciseRTMLockingStatistics, false,                 \
+          "Print per-lock-site statistics of rtm locking in JVM")           \
+                                                                            \
   notproduct(bool, PrintEliminateLocks, false,                              \
           "Print out when locks are eliminated")                            \
                                                                             \
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -33,8 +33,8 @@
 #include "opto/addnode.hpp"
 #include "opto/callGenerator.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
--- a/hotspot/src/share/vm/opto/callnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,6 +27,7 @@
 #include "compiler/oopMap.hpp"
 #include "opto/callGenerator.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/escape.hpp"
 #include "opto/locknode.hpp"
 #include "opto/machnode.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/castnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 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 "opto/addnode.hpp"
+#include "opto/castnode.hpp"
+#include "opto/connode.hpp"
+#include "opto/matcher.hpp"
+#include "opto/phaseX.hpp"
+#include "opto/subnode.hpp"
+#include "opto/type.hpp"
+
+//=============================================================================
+// If input is already higher or equal to cast type, then this is an identity.
+Node *ConstraintCastNode::Identity( PhaseTransform *phase ) {
+  return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
+}
+
+//------------------------------Value------------------------------------------
+// Take 'join' of input and cast-up type
+const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
+  if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
+  const Type* ft = phase->type(in(1))->filter_speculative(_type);
+
+#ifdef ASSERT
+  // Previous versions of this function had some special case logic,
+  // which is no longer necessary.  Make sure of the required effects.
+  switch (Opcode()) {
+    case Op_CastII:
+    {
+      const Type* t1 = phase->type(in(1));
+      if( t1 == Type::TOP )  assert(ft == Type::TOP, "special case #1");
+      const Type* rt = t1->join_speculative(_type);
+      if (rt->empty())       assert(ft == Type::TOP, "special case #2");
+      break;
+    }
+    case Op_CastPP:
+    if (phase->type(in(1)) == TypePtr::NULL_PTR &&
+        _type->isa_ptr() && _type->is_ptr()->_ptr == TypePtr::NotNull)
+    assert(ft == Type::TOP, "special case #3");
+    break;
+  }
+#endif //ASSERT
+
+  return ft;
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape){
+  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
+}
+
+//------------------------------Ideal_DU_postCCP-------------------------------
+// Throw away cast after constant propagation
+Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+  const Type *t = ccp->type(in(1));
+  ccp->hash_delete(this);
+  set_type(t);                   // Turn into ID function
+  ccp->hash_insert(this);
+  return this;
+}
+
+
+//=============================================================================
+
+//------------------------------Ideal_DU_postCCP-------------------------------
+// If not converting int->oop, throw away cast after constant propagation
+Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+  const Type *t = ccp->type(in(1));
+  if (!t->isa_oop_ptr() || ((in(1)->is_DecodeN()) && Matcher::gen_narrow_oop_implicit_null_checks())) {
+    return NULL; // do not transform raw pointers or narrow oops
+  }
+  return ConstraintCastNode::Ideal_DU_postCCP(ccp);
+}
+
+
+
+//=============================================================================
+//------------------------------Identity---------------------------------------
+// If input is already higher or equal to cast type, then this is an identity.
+Node *CheckCastPPNode::Identity( PhaseTransform *phase ) {
+  // Toned down to rescue meeting at a Phi 3 different oops all implementing
+  // the same interface.  CompileTheWorld starting at 502, kd12rc1.zip.
+  return (phase->type(in(1)) == phase->type(this)) ? in(1) : this;
+}
+
+//------------------------------Value------------------------------------------
+// Take 'join' of input and cast-up type, unless working with an Interface
+const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const {
+  if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
+
+  const Type *inn = phase->type(in(1));
+  if( inn == Type::TOP ) return Type::TOP;  // No information yet
+
+  const TypePtr *in_type   = inn->isa_ptr();
+  const TypePtr *my_type   = _type->isa_ptr();
+  const Type *result = _type;
+  if( in_type != NULL && my_type != NULL ) {
+    TypePtr::PTR   in_ptr    = in_type->ptr();
+    if( in_ptr == TypePtr::Null ) {
+      result = in_type;
+    } else if( in_ptr == TypePtr::Constant ) {
+      // Casting a constant oop to an interface?
+      // (i.e., a String to a Comparable?)
+      // Then return the interface.
+      const TypeOopPtr *jptr = my_type->isa_oopptr();
+      assert( jptr, "" );
+      result =  (jptr->klass()->is_interface() || !in_type->higher_equal(_type))
+      ? my_type->cast_to_ptr_type( TypePtr::NotNull )
+      : in_type;
+    } else {
+      result =  my_type->cast_to_ptr_type( my_type->join_ptr(in_ptr) );
+    }
+  }
+
+  // This is the code from TypePtr::xmeet() that prevents us from
+  // having 2 ways to represent the same type. We have to replicate it
+  // here because we don't go through meet/join.
+  if (result->remove_speculative() == result->speculative()) {
+    result = result->remove_speculative();
+  }
+
+  // Same as above: because we don't go through meet/join, remove the
+  // speculative type if we know we won't use it.
+  return result->cleanup_speculative();
+
+  // JOIN NOT DONE HERE BECAUSE OF INTERFACE ISSUES.
+  // FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR!
+
+  //
+  // Remove this code after overnight run indicates no performance
+  // loss from not performing JOIN at CheckCastPPNode
+  //
+  // const TypeInstPtr *in_oop = in->isa_instptr();
+  // const TypeInstPtr *my_oop = _type->isa_instptr();
+  // // If either input is an 'interface', return destination type
+  // assert (in_oop == NULL || in_oop->klass() != NULL, "");
+  // assert (my_oop == NULL || my_oop->klass() != NULL, "");
+  // if( (in_oop && in_oop->klass()->is_interface())
+  //   ||(my_oop && my_oop->klass()->is_interface()) ) {
+  //   TypePtr::PTR  in_ptr = in->isa_ptr() ? in->is_ptr()->_ptr : TypePtr::BotPTR;
+  //   // Preserve cast away nullness for interfaces
+  //   if( in_ptr == TypePtr::NotNull && my_oop && my_oop->_ptr == TypePtr::BotPTR ) {
+  //     return my_oop->cast_to_ptr_type(TypePtr::NotNull);
+  //   }
+  //   return _type;
+  // }
+  //
+  // // Neither the input nor the destination type is an interface,
+  //
+  // // history: JOIN used to cause weird corner case bugs
+  // //          return (in == TypeOopPtr::NULL_PTR) ? in : _type;
+  // // JOIN picks up NotNull in common instance-of/check-cast idioms, both oops.
+  // // JOIN does not preserve NotNull in other cases, e.g. RawPtr vs InstPtr
+  // const Type *join = in->join(_type);
+  // // Check if join preserved NotNull'ness for pointers
+  // if( join->isa_ptr() && _type->isa_ptr() ) {
+  //   TypePtr::PTR join_ptr = join->is_ptr()->_ptr;
+  //   TypePtr::PTR type_ptr = _type->is_ptr()->_ptr;
+  //   // If there isn't any NotNull'ness to preserve
+  //   // OR if join preserved NotNull'ness then return it
+  //   if( type_ptr == TypePtr::BotPTR  || type_ptr == TypePtr::Null ||
+  //       join_ptr == TypePtr::NotNull || join_ptr == TypePtr::Constant ) {
+  //     return join;
+  //   }
+  //   // ELSE return same old type as before
+  //   return _type;
+  // }
+  // // Not joining two pointers
+  // return join;
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *CheckCastPPNode::Ideal(PhaseGVN *phase, bool can_reshape){
+  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *CastX2PNode::Value( PhaseTransform *phase ) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  if (t->base() == Type_X && t->singleton()) {
+    uintptr_t bits = (uintptr_t) t->is_intptr_t()->get_con();
+    if (bits == 0)   return TypePtr::NULL_PTR;
+    return TypeRawPtr::make((address) bits);
+  }
+  return CastX2PNode::bottom_type();
+}
+
+//------------------------------Idealize---------------------------------------
+static inline bool fits_in_int(const Type* t, bool but_not_min_int = false) {
+  if (t == Type::TOP)  return false;
+  const TypeX* tl = t->is_intptr_t();
+  jint lo = min_jint;
+  jint hi = max_jint;
+  if (but_not_min_int)  ++lo;  // caller wants to negate the value w/o overflow
+  return (tl->_lo >= lo) && (tl->_hi <= hi);
+}
+
+static inline Node* addP_of_X2P(PhaseGVN *phase,
+                                Node* base,
+                                Node* dispX,
+                                bool negate = false) {
+  if (negate) {
+    dispX = new (phase->C) SubXNode(phase->MakeConX(0), phase->transform(dispX));
+  }
+  return new (phase->C) AddPNode(phase->C->top(),
+                                 phase->transform(new (phase->C) CastX2PNode(base)),
+                                 phase->transform(dispX));
+}
+
+Node *CastX2PNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  // convert CastX2P(AddX(x, y)) to AddP(CastX2P(x), y) if y fits in an int
+  int op = in(1)->Opcode();
+  Node* x;
+  Node* y;
+  switch (op) {
+    case Op_SubX:
+    x = in(1)->in(1);
+    // Avoid ideal transformations ping-pong between this and AddP for raw pointers.
+    if (phase->find_intptr_t_con(x, -1) == 0)
+    break;
+    y = in(1)->in(2);
+    if (fits_in_int(phase->type(y), true)) {
+      return addP_of_X2P(phase, x, y, true);
+    }
+    break;
+    case Op_AddX:
+    x = in(1)->in(1);
+    y = in(1)->in(2);
+    if (fits_in_int(phase->type(y))) {
+      return addP_of_X2P(phase, x, y);
+    }
+    if (fits_in_int(phase->type(x))) {
+      return addP_of_X2P(phase, y, x);
+    }
+    break;
+  }
+  return NULL;
+}
+
+//------------------------------Identity---------------------------------------
+Node *CastX2PNode::Identity( PhaseTransform *phase ) {
+  if (in(1)->Opcode() == Op_CastP2X)  return in(1)->in(1);
+  return this;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *CastP2XNode::Value( PhaseTransform *phase ) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  if (t->base() == Type::RawPtr && t->singleton()) {
+    uintptr_t bits = (uintptr_t) t->is_rawptr()->get_con();
+    return TypeX::make(bits);
+  }
+  return CastP2XNode::bottom_type();
+}
+
+Node *CastP2XNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
+}
+
+//------------------------------Identity---------------------------------------
+Node *CastP2XNode::Identity( PhaseTransform *phase ) {
+  if (in(1)->Opcode() == Op_CastX2P)  return in(1)->in(1);
+  return this;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/castnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 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_OPTO_CASTNODE_HPP
+#define SHARE_VM_OPTO_CASTNODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+
+//------------------------------ConstraintCastNode-----------------------------
+// cast to a different range
+class ConstraintCastNode: public TypeNode {
+  public:
+  ConstraintCastNode (Node *n, const Type *t ): TypeNode(t,2) {
+    init_class_id(Class_ConstraintCast);
+    init_req(1, n);
+  }
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const = 0;
+  virtual Node *Ideal_DU_postCCP( PhaseCCP * );
+};
+
+//------------------------------CastIINode-------------------------------------
+// cast integer to integer (different range)
+class CastIINode: public ConstraintCastNode {
+  public:
+  CastIINode (Node *n, const Type *t ): ConstraintCastNode(n,t) {}
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------CastPPNode-------------------------------------
+// cast pointer to pointer (different type)
+class CastPPNode: public ConstraintCastNode {
+  public:
+  CastPPNode (Node *n, const Type *t ): ConstraintCastNode(n, t) {}
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return Op_RegP; }
+  virtual Node *Ideal_DU_postCCP( PhaseCCP * );
+};
+
+//------------------------------CheckCastPPNode--------------------------------
+// for _checkcast, cast pointer to pointer (different type), without JOIN,
+class CheckCastPPNode: public TypeNode {
+  public:
+  CheckCastPPNode( Node *c, Node *n, const Type *t ) : TypeNode(t,2) {
+    init_class_id(Class_CheckCastPP);
+    init_req(0, c);
+    init_req(1, n);
+  }
+
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual int   Opcode() const;
+  virtual uint  ideal_reg() const { return Op_RegP; }
+  // No longer remove CheckCast after CCP as it gives me a place to hang
+  // the proper address type - which is required to compute anti-deps.
+  //virtual Node *Ideal_DU_postCCP( PhaseCCP * );
+};
+
+
+//------------------------------CastX2PNode-------------------------------------
+// convert a machine-pointer-sized integer to a raw pointer
+class CastX2PNode : public Node {
+  public:
+  CastX2PNode( Node *n ) : Node(NULL, n) {}
+  virtual int Opcode() const;
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual uint ideal_reg() const { return Op_RegP; }
+  virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
+};
+
+//------------------------------CastP2XNode-------------------------------------
+// Used in both 32-bit and 64-bit land.
+// Used for card-marks and unsafe pointer math.
+class CastP2XNode : public Node {
+  public:
+  CastP2XNode( Node *ctrl, Node *n ) : Node(ctrl, n) {}
+  virtual int Opcode() const;
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual uint ideal_reg() const { return Op_RegX; }
+  virtual const Type *bottom_type() const { return TypeX_X; }
+  // Return false to keep node from moving away from an associated card mark.
+  virtual bool depends_only_on_test() const { return false; }
+};
+
+
+
+#endif // SHARE_VM_OPTO_CASTNODE_HPP
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -29,8 +29,11 @@
 #include "opto/addnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
+#include "opto/movenode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/regmask.hpp"
--- a/hotspot/src/share/vm/opto/chaitin.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -37,6 +37,7 @@
 #include "opto/indexSet.hpp"
 #include "opto/machnode.hpp"
 #include "opto/memnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/rootnode.hpp"
 
--- a/hotspot/src/share/vm/opto/classes.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/classes.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,17 +25,24 @@
 #include "precompiled.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
+#include "opto/countbitsnode.hpp"
 #include "opto/divnode.hpp"
+#include "opto/intrinsicnode.hpp"
 #include "opto/locknode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mathexactnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/multnode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/node.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/subnode.hpp"
 #include "opto/vectornode.hpp"
--- a/hotspot/src/share/vm/opto/classes.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -198,6 +198,7 @@
 macro(NeverBranch)
 macro(Opaque1)
 macro(Opaque2)
+macro(Opaque3)
 macro(OrI)
 macro(OrL)
 macro(OverflowAddI)
--- a/hotspot/src/share/vm/opto/compile.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -51,6 +51,7 @@
 #include "opto/mathexactnode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/node.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/output.hpp"
@@ -694,9 +695,10 @@
   set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
   set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
 
-  if (ProfileTraps) {
+  if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
     // Make sure the method being compiled gets its own MDO,
     // so we can at least track the decompile_count().
+    // Need MDO to record RTM code generation state.
     method()->ensure_method_data();
   }
 
@@ -907,7 +909,8 @@
                            compiler,
                            env()->comp_level(),
                            has_unsafe_access(),
-                           SharedRuntime::is_wide_vector(max_vector_size())
+                           SharedRuntime::is_wide_vector(max_vector_size()),
+                           rtm_state()
                            );
 
     if (log() != NULL) // Print code cache state into compiler log
@@ -1073,7 +1076,23 @@
   set_do_scheduling(OptoScheduling);
   set_do_count_invocations(false);
   set_do_method_data_update(false);
-
+  set_rtm_state(NoRTM); // No RTM lock eliding by default
+#if INCLUDE_RTM_OPT
+  if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
+    int rtm_state = method()->method_data()->rtm_state();
+    if (method_has_option("NoRTMLockEliding") || ((rtm_state & NoRTM) != 0)) {
+      // Don't generate RTM lock eliding code.
+      set_rtm_state(NoRTM);
+    } else if (method_has_option("UseRTMLockEliding") || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) {
+      // Generate RTM lock eliding code without abort ratio calculation code.
+      set_rtm_state(UseRTM);
+    } else if (UseRTMDeopt) {
+      // Generate RTM lock eliding code and include abort ratio calculation
+      // code if UseRTMDeopt is on.
+      set_rtm_state(ProfileRTM);
+    }
+  }
+#endif
   if (debug_info()->recording_non_safepoints()) {
     set_node_note_array(new(comp_arena()) GrowableArray<Node_Notes*>
                         (comp_arena(), 8, 0, NULL));
@@ -2581,6 +2600,7 @@
     break;
   case Op_Opaque1:              // Remove Opaque Nodes before matching
   case Op_Opaque2:              // Remove Opaque Nodes before matching
+  case Op_Opaque3:
     n->subsume_by(n->in(1), this);
     break;
   case Op_CallStaticJava:
--- a/hotspot/src/share/vm/opto/compile.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -319,9 +319,9 @@
   bool                  _trace_opto_output;
   bool                  _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
 #endif
-
   // JSR 292
   bool                  _has_method_handle_invokes; // True if this method has MethodHandle invokes.
+  RTMState              _rtm_state;             // State of Restricted Transactional Memory usage
 
   // Compilation environment.
   Arena                 _comp_arena;            // Arena with lifetime equivalent to Compile
@@ -591,6 +591,10 @@
   void          set_print_inlining(bool z)       { _print_inlining = z; }
   bool              print_intrinsics() const     { return _print_intrinsics; }
   void          set_print_intrinsics(bool z)     { _print_intrinsics = z; }
+  RTMState          rtm_state()  const           { return _rtm_state; }
+  void          set_rtm_state(RTMState s)        { _rtm_state = s; }
+  bool              use_rtm() const              { return (_rtm_state & NoRTM) == 0; }
+  bool          profile_rtm() const              { return _rtm_state == ProfileRTM; }
   // check the CompilerOracle for special behaviours for this compile
   bool          method_has_option(const char * option) {
     return method() != NULL && method()->has_option(option);
--- a/hotspot/src/share/vm/opto/connode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/connode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -66,1313 +66,4 @@
   return NULL;
 }
 
-//=============================================================================
-/*
-The major change is for CMoveP and StrComp.  They have related but slightly
-different problems.  They both take in TWO oops which are both null-checked
-independently before the using Node.  After CCP removes the CastPP's they need
-to pick up the guarding test edge - in this case TWO control edges.  I tried
-various solutions, all have problems:
 
-(1) Do nothing.  This leads to a bug where we hoist a Load from a CMoveP or a
-StrComp above a guarding null check.  I've seen both cases in normal -Xcomp
-testing.
-
-(2) Plug the control edge from 1 of the 2 oops in.  Apparent problem here is
-to figure out which test post-dominates.  The real problem is that it doesn't
-matter which one you pick.  After you pick up, the dominating-test elider in
-IGVN can remove the test and allow you to hoist up to the dominating test on
-the chosen oop bypassing the test on the not-chosen oop.  Seen in testing.
-Oops.
-
-(3) Leave the CastPP's in.  This makes the graph more accurate in some sense;
-we get to keep around the knowledge that an oop is not-null after some test.
-Alas, the CastPP's interfere with GVN (some values are the regular oop, some
-are the CastPP of the oop, all merge at Phi's which cannot collapse, etc).
-This cost us 10% on SpecJVM, even when I removed some of the more trivial
-cases in the optimizer.  Removing more useless Phi's started allowing Loads to
-illegally float above null checks.  I gave up on this approach.
-
-(4) Add BOTH control edges to both tests.  Alas, too much code knows that
-control edges are in slot-zero ONLY.  Many quick asserts fail; no way to do
-this one.  Note that I really want to allow the CMoveP to float and add both
-control edges to the dependent Load op - meaning I can select early but I
-cannot Load until I pass both tests.
-
-(5) Do not hoist CMoveP and StrComp.  To this end I added the v-call
-depends_only_on_test().  No obvious performance loss on Spec, but we are
-clearly conservative on CMoveP (also so on StrComp but that's unlikely to
-matter ever).
-
-*/
-
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.
-// Move constants to the right.
-Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if( in(0) && remove_dead_region(phase, can_reshape) ) return this;
-  // Don't bother trying to transform a dead node
-  if( in(0) && in(0)->is_top() )  return NULL;
-  assert( !phase->eqv(in(Condition), this) &&
-          !phase->eqv(in(IfFalse), this) &&
-          !phase->eqv(in(IfTrue), this), "dead loop in CMoveNode::Ideal" );
-  if( phase->type(in(Condition)) == Type::TOP )
-    return NULL; // return NULL when Condition is dead
-
-  if( in(IfFalse)->is_Con() && !in(IfTrue)->is_Con() ) {
-    if( in(Condition)->is_Bool() ) {
-      BoolNode* b  = in(Condition)->as_Bool();
-      BoolNode* b2 = b->negate(phase);
-      return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type );
-    }
-  }
-  return NULL;
-}
-
-//------------------------------is_cmove_id------------------------------------
-// Helper function to check for CMOVE identity.  Shared with PhiNode::Identity
-Node *CMoveNode::is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b ) {
-  // Check for Cmp'ing and CMove'ing same values
-  if( (phase->eqv(cmp->in(1),f) &&
-       phase->eqv(cmp->in(2),t)) ||
-      // Swapped Cmp is OK
-      (phase->eqv(cmp->in(2),f) &&
-       phase->eqv(cmp->in(1),t)) ) {
-    // Give up this identity check for floating points because it may choose incorrect
-    // value around 0.0 and -0.0
-    if ( cmp->Opcode()==Op_CmpF || cmp->Opcode()==Op_CmpD )
-      return NULL;
-    // Check for "(t==f)?t:f;" and replace with "f"
-    if( b->_test._test == BoolTest::eq )
-      return f;
-    // Allow the inverted case as well
-    // Check for "(t!=f)?t:f;" and replace with "t"
-    if( b->_test._test == BoolTest::ne )
-      return t;
-  }
-  return NULL;
-}
-
-//------------------------------Identity---------------------------------------
-// Conditional-move is an identity if both inputs are the same, or the test
-// true or false.
-Node *CMoveNode::Identity( PhaseTransform *phase ) {
-  if( phase->eqv(in(IfFalse),in(IfTrue)) ) // C-moving identical inputs?
-    return in(IfFalse);         // Then it doesn't matter
-  if( phase->type(in(Condition)) == TypeInt::ZERO )
-    return in(IfFalse);         // Always pick left(false) input
-  if( phase->type(in(Condition)) == TypeInt::ONE )
-    return in(IfTrue);          // Always pick right(true) input
-
-  // Check for CMove'ing a constant after comparing against the constant.
-  // Happens all the time now, since if we compare equality vs a constant in
-  // the parser, we "know" the variable is constant on one path and we force
-  // it.  Thus code like "if( x==0 ) {/*EMPTY*/}" ends up inserting a
-  // conditional move: "x = (x==0)?0:x;".  Yucko.  This fix is slightly more
-  // general in that we don't need constants.
-  if( in(Condition)->is_Bool() ) {
-    BoolNode *b = in(Condition)->as_Bool();
-    Node *cmp = b->in(1);
-    if( cmp->is_Cmp() ) {
-      Node *id = is_cmove_id( phase, cmp, in(IfTrue), in(IfFalse), b );
-      if( id ) return id;
-    }
-  }
-
-  return this;
-}
-
-//------------------------------Value------------------------------------------
-// Result is the meet of inputs
-const Type *CMoveNode::Value( PhaseTransform *phase ) const {
-  if( phase->type(in(Condition)) == Type::TOP )
-    return Type::TOP;
-  return phase->type(in(IfFalse))->meet_speculative(phase->type(in(IfTrue)));
-}
-
-//------------------------------make-------------------------------------------
-// Make a correctly-flavored CMove.  Since _type is directly determined
-// from the inputs we do not need to specify it here.
-CMoveNode *CMoveNode::make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ) {
-  switch( t->basic_type() ) {
-  case T_INT:     return new (C) CMoveINode( bol, left, right, t->is_int() );
-  case T_FLOAT:   return new (C) CMoveFNode( bol, left, right, t );
-  case T_DOUBLE:  return new (C) CMoveDNode( bol, left, right, t );
-  case T_LONG:    return new (C) CMoveLNode( bol, left, right, t->is_long() );
-  case T_OBJECT:  return new (C) CMovePNode( c, bol, left, right, t->is_oopptr() );
-  case T_ADDRESS: return new (C) CMovePNode( c, bol, left, right, t->is_ptr() );
-  case T_NARROWOOP: return new (C) CMoveNNode( c, bol, left, right, t );
-  default:
-    ShouldNotReachHere();
-    return NULL;
-  }
-}
-
-//=============================================================================
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.
-// Check for conversions to boolean
-Node *CMoveINode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  // Try generic ideal's first
-  Node *x = CMoveNode::Ideal(phase, can_reshape);
-  if( x ) return x;
-
-  // If zero is on the left (false-case, no-move-case) it must mean another
-  // constant is on the right (otherwise the shared CMove::Ideal code would
-  // have moved the constant to the right).  This situation is bad for Intel
-  // and a don't-care for Sparc.  It's bad for Intel because the zero has to
-  // be manifested in a register with a XOR which kills flags, which are live
-  // on input to the CMoveI, leading to a situation which causes excessive
-  // spilling on Intel.  For Sparc, if the zero in on the left the Sparc will
-  // zero a register via G0 and conditionally-move the other constant.  If the
-  // zero is on the right, the Sparc will load the first constant with a
-  // 13-bit set-lo and conditionally move G0.  See bug 4677505.
-  if( phase->type(in(IfFalse)) == TypeInt::ZERO && !(phase->type(in(IfTrue)) == TypeInt::ZERO) ) {
-    if( in(Condition)->is_Bool() ) {
-      BoolNode* b  = in(Condition)->as_Bool();
-      BoolNode* b2 = b->negate(phase);
-      return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type );
-    }
-  }
-
-  // Now check for booleans
-  int flip = 0;
-
-  // Check for picking from zero/one
-  if( phase->type(in(IfFalse)) == TypeInt::ZERO && phase->type(in(IfTrue)) == TypeInt::ONE ) {
-    flip = 1 - flip;
-  } else if( phase->type(in(IfFalse)) == TypeInt::ONE && phase->type(in(IfTrue)) == TypeInt::ZERO ) {
-  } else return NULL;
-
-  // Check for eq/ne test
-  if( !in(1)->is_Bool() ) return NULL;
-  BoolNode *bol = in(1)->as_Bool();
-  if( bol->_test._test == BoolTest::eq ) {
-  } else if( bol->_test._test == BoolTest::ne ) {
-    flip = 1-flip;
-  } else return NULL;
-
-  // Check for vs 0 or 1
-  if( !bol->in(1)->is_Cmp() ) return NULL;
-  const CmpNode *cmp = bol->in(1)->as_Cmp();
-  if( phase->type(cmp->in(2)) == TypeInt::ZERO ) {
-  } else if( phase->type(cmp->in(2)) == TypeInt::ONE ) {
-    // Allow cmp-vs-1 if the other input is bounded by 0-1
-    if( phase->type(cmp->in(1)) != TypeInt::BOOL )
-      return NULL;
-    flip = 1 - flip;
-  } else return NULL;
-
-  // Convert to a bool (flipped)
-  // Build int->bool conversion
-#ifndef PRODUCT
-  if( PrintOpto ) tty->print_cr("CMOV to I2B");
-#endif
-  Node *n = new (phase->C) Conv2BNode( cmp->in(1) );
-  if( flip )
-    n = new (phase->C) XorINode( phase->transform(n), phase->intcon(1) );
-
-  return n;
-}
-
-//=============================================================================
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.
-// Check for absolute value
-Node *CMoveFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  // Try generic ideal's first
-  Node *x = CMoveNode::Ideal(phase, can_reshape);
-  if( x ) return x;
-
-  int  cmp_zero_idx = 0;        // Index of compare input where to look for zero
-  int  phi_x_idx = 0;           // Index of phi input where to find naked x
-
-  // Find the Bool
-  if( !in(1)->is_Bool() ) return NULL;
-  BoolNode *bol = in(1)->as_Bool();
-  // Check bool sense
-  switch( bol->_test._test ) {
-  case BoolTest::lt: cmp_zero_idx = 1; phi_x_idx = IfTrue;  break;
-  case BoolTest::le: cmp_zero_idx = 2; phi_x_idx = IfFalse; break;
-  case BoolTest::gt: cmp_zero_idx = 2; phi_x_idx = IfTrue;  break;
-  case BoolTest::ge: cmp_zero_idx = 1; phi_x_idx = IfFalse; break;
-  default:           return NULL;                           break;
-  }
-
-  // Find zero input of CmpF; the other input is being abs'd
-  Node *cmpf = bol->in(1);
-  if( cmpf->Opcode() != Op_CmpF ) return NULL;
-  Node *X = NULL;
-  bool flip = false;
-  if( phase->type(cmpf->in(cmp_zero_idx)) == TypeF::ZERO ) {
-    X = cmpf->in(3 - cmp_zero_idx);
-  } else if (phase->type(cmpf->in(3 - cmp_zero_idx)) == TypeF::ZERO) {
-    // The test is inverted, we should invert the result...
-    X = cmpf->in(cmp_zero_idx);
-    flip = true;
-  } else {
-    return NULL;
-  }
-
-  // If X is found on the appropriate phi input, find the subtract on the other
-  if( X != in(phi_x_idx) ) return NULL;
-  int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
-  Node *sub = in(phi_sub_idx);
-
-  // Allow only SubF(0,X) and fail out for all others; NegF is not OK
-  if( sub->Opcode() != Op_SubF ||
-      sub->in(2) != X ||
-      phase->type(sub->in(1)) != TypeF::ZERO ) return NULL;
-
-  Node *abs = new (phase->C) AbsFNode( X );
-  if( flip )
-    abs = new (phase->C) SubFNode(sub->in(1), phase->transform(abs));
-
-  return abs;
-}
-
-//=============================================================================
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.
-// Check for absolute value
-Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  // Try generic ideal's first
-  Node *x = CMoveNode::Ideal(phase, can_reshape);
-  if( x ) return x;
-
-  int  cmp_zero_idx = 0;        // Index of compare input where to look for zero
-  int  phi_x_idx = 0;           // Index of phi input where to find naked x
-
-  // Find the Bool
-  if( !in(1)->is_Bool() ) return NULL;
-  BoolNode *bol = in(1)->as_Bool();
-  // Check bool sense
-  switch( bol->_test._test ) {
-  case BoolTest::lt: cmp_zero_idx = 1; phi_x_idx = IfTrue;  break;
-  case BoolTest::le: cmp_zero_idx = 2; phi_x_idx = IfFalse; break;
-  case BoolTest::gt: cmp_zero_idx = 2; phi_x_idx = IfTrue;  break;
-  case BoolTest::ge: cmp_zero_idx = 1; phi_x_idx = IfFalse; break;
-  default:           return NULL;                           break;
-  }
-
-  // Find zero input of CmpD; the other input is being abs'd
-  Node *cmpd = bol->in(1);
-  if( cmpd->Opcode() != Op_CmpD ) return NULL;
-  Node *X = NULL;
-  bool flip = false;
-  if( phase->type(cmpd->in(cmp_zero_idx)) == TypeD::ZERO ) {
-    X = cmpd->in(3 - cmp_zero_idx);
-  } else if (phase->type(cmpd->in(3 - cmp_zero_idx)) == TypeD::ZERO) {
-    // The test is inverted, we should invert the result...
-    X = cmpd->in(cmp_zero_idx);
-    flip = true;
-  } else {
-    return NULL;
-  }
-
-  // If X is found on the appropriate phi input, find the subtract on the other
-  if( X != in(phi_x_idx) ) return NULL;
-  int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
-  Node *sub = in(phi_sub_idx);
-
-  // Allow only SubD(0,X) and fail out for all others; NegD is not OK
-  if( sub->Opcode() != Op_SubD ||
-      sub->in(2) != X ||
-      phase->type(sub->in(1)) != TypeD::ZERO ) return NULL;
-
-  Node *abs = new (phase->C) AbsDNode( X );
-  if( flip )
-    abs = new (phase->C) SubDNode(sub->in(1), phase->transform(abs));
-
-  return abs;
-}
-
-
-//=============================================================================
-// If input is already higher or equal to cast type, then this is an identity.
-Node *ConstraintCastNode::Identity( PhaseTransform *phase ) {
-  return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
-}
-
-//------------------------------Value------------------------------------------
-// Take 'join' of input and cast-up type
-const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
-  if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
-const Type* ft = phase->type(in(1))->filter_speculative(_type);
-
-#ifdef ASSERT
-  // Previous versions of this function had some special case logic,
-  // which is no longer necessary.  Make sure of the required effects.
-  switch (Opcode()) {
-  case Op_CastII:
-    {
-      const Type* t1 = phase->type(in(1));
-      if( t1 == Type::TOP )  assert(ft == Type::TOP, "special case #1");
-      const Type* rt = t1->join_speculative(_type);
-      if (rt->empty())       assert(ft == Type::TOP, "special case #2");
-      break;
-    }
-  case Op_CastPP:
-    if (phase->type(in(1)) == TypePtr::NULL_PTR &&
-        _type->isa_ptr() && _type->is_ptr()->_ptr == TypePtr::NotNull)
-      assert(ft == Type::TOP, "special case #3");
-    break;
-  }
-#endif //ASSERT
-
-  return ft;
-}
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.  Strip out
-// control copies
-Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape){
-  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
-}
-
-//------------------------------Ideal_DU_postCCP-------------------------------
-// Throw away cast after constant propagation
-Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
-  const Type *t = ccp->type(in(1));
-  ccp->hash_delete(this);
-  set_type(t);                   // Turn into ID function
-  ccp->hash_insert(this);
-  return this;
-}
-
-
-//=============================================================================
-
-//------------------------------Ideal_DU_postCCP-------------------------------
-// If not converting int->oop, throw away cast after constant propagation
-Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
-  const Type *t = ccp->type(in(1));
-  if (!t->isa_oop_ptr() || ((in(1)->is_DecodeN()) && Matcher::gen_narrow_oop_implicit_null_checks())) {
-    return NULL; // do not transform raw pointers or narrow oops
-  }
-  return ConstraintCastNode::Ideal_DU_postCCP(ccp);
-}
-
-
-
-//=============================================================================
-//------------------------------Identity---------------------------------------
-// If input is already higher or equal to cast type, then this is an identity.
-Node *CheckCastPPNode::Identity( PhaseTransform *phase ) {
-  // Toned down to rescue meeting at a Phi 3 different oops all implementing
-  // the same interface.  CompileTheWorld starting at 502, kd12rc1.zip.
-  return (phase->type(in(1)) == phase->type(this)) ? in(1) : this;
-}
-
-//------------------------------Value------------------------------------------
-// Take 'join' of input and cast-up type, unless working with an Interface
-const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const {
-  if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
-
-  const Type *inn = phase->type(in(1));
-  if( inn == Type::TOP ) return Type::TOP;  // No information yet
-
-  const TypePtr *in_type   = inn->isa_ptr();
-  const TypePtr *my_type   = _type->isa_ptr();
-  const Type *result = _type;
-  if( in_type != NULL && my_type != NULL ) {
-    TypePtr::PTR   in_ptr    = in_type->ptr();
-    if( in_ptr == TypePtr::Null ) {
-      result = in_type;
-    } else if( in_ptr == TypePtr::Constant ) {
-      // Casting a constant oop to an interface?
-      // (i.e., a String to a Comparable?)
-      // Then return the interface.
-      const TypeOopPtr *jptr = my_type->isa_oopptr();
-      assert( jptr, "" );
-      result =  (jptr->klass()->is_interface() || !in_type->higher_equal(_type))
-        ? my_type->cast_to_ptr_type( TypePtr::NotNull )
-        : in_type;
-    } else {
-      result =  my_type->cast_to_ptr_type( my_type->join_ptr(in_ptr) );
-    }
-  }
-  return result;
-
-  // JOIN NOT DONE HERE BECAUSE OF INTERFACE ISSUES.
-  // FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR!
-
-  //
-  // Remove this code after overnight run indicates no performance
-  // loss from not performing JOIN at CheckCastPPNode
-  //
-  // const TypeInstPtr *in_oop = in->isa_instptr();
-  // const TypeInstPtr *my_oop = _type->isa_instptr();
-  // // If either input is an 'interface', return destination type
-  // assert (in_oop == NULL || in_oop->klass() != NULL, "");
-  // assert (my_oop == NULL || my_oop->klass() != NULL, "");
-  // if( (in_oop && in_oop->klass()->is_interface())
-  //   ||(my_oop && my_oop->klass()->is_interface()) ) {
-  //   TypePtr::PTR  in_ptr = in->isa_ptr() ? in->is_ptr()->_ptr : TypePtr::BotPTR;
-  //   // Preserve cast away nullness for interfaces
-  //   if( in_ptr == TypePtr::NotNull && my_oop && my_oop->_ptr == TypePtr::BotPTR ) {
-  //     return my_oop->cast_to_ptr_type(TypePtr::NotNull);
-  //   }
-  //   return _type;
-  // }
-  //
-  // // Neither the input nor the destination type is an interface,
-  //
-  // // history: JOIN used to cause weird corner case bugs
-  // //          return (in == TypeOopPtr::NULL_PTR) ? in : _type;
-  // // JOIN picks up NotNull in common instance-of/check-cast idioms, both oops.
-  // // JOIN does not preserve NotNull in other cases, e.g. RawPtr vs InstPtr
-  // const Type *join = in->join(_type);
-  // // Check if join preserved NotNull'ness for pointers
-  // if( join->isa_ptr() && _type->isa_ptr() ) {
-  //   TypePtr::PTR join_ptr = join->is_ptr()->_ptr;
-  //   TypePtr::PTR type_ptr = _type->is_ptr()->_ptr;
-  //   // If there isn't any NotNull'ness to preserve
-  //   // OR if join preserved NotNull'ness then return it
-  //   if( type_ptr == TypePtr::BotPTR  || type_ptr == TypePtr::Null ||
-  //       join_ptr == TypePtr::NotNull || join_ptr == TypePtr::Constant ) {
-  //     return join;
-  //   }
-  //   // ELSE return same old type as before
-  //   return _type;
-  // }
-  // // Not joining two pointers
-  // return join;
-}
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.  Strip out
-// control copies
-Node *CheckCastPPNode::Ideal(PhaseGVN *phase, bool can_reshape){
-  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
-}
-
-
-Node* DecodeNNode::Identity(PhaseTransform* phase) {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return in(1);
-
-  if (in(1)->is_EncodeP()) {
-    // (DecodeN (EncodeP p)) -> p
-    return in(1)->in(1);
-  }
-  return this;
-}
-
-const Type *DecodeNNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if (t == Type::TOP) return Type::TOP;
-  if (t == TypeNarrowOop::NULL_PTR) return TypePtr::NULL_PTR;
-
-  assert(t->isa_narrowoop(), "only  narrowoop here");
-  return t->make_ptr();
-}
-
-Node* EncodePNode::Identity(PhaseTransform* phase) {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return in(1);
-
-  if (in(1)->is_DecodeN()) {
-    // (EncodeP (DecodeN p)) -> p
-    return in(1)->in(1);
-  }
-  return this;
-}
-
-const Type *EncodePNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if (t == Type::TOP) return Type::TOP;
-  if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR;
-
-  assert(t->isa_oop_ptr(), "only oopptr here");
-  return t->make_narrowoop();
-}
-
-
-Node *EncodeNarrowPtrNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
-  return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1));
-}
-
-Node* DecodeNKlassNode::Identity(PhaseTransform* phase) {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return in(1);
-
-  if (in(1)->is_EncodePKlass()) {
-    // (DecodeNKlass (EncodePKlass p)) -> p
-    return in(1)->in(1);
-  }
-  return this;
-}
-
-const Type *DecodeNKlassNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if (t == Type::TOP) return Type::TOP;
-  assert(t != TypeNarrowKlass::NULL_PTR, "null klass?");
-
-  assert(t->isa_narrowklass(), "only narrow klass ptr here");
-  return t->make_ptr();
-}
-
-Node* EncodePKlassNode::Identity(PhaseTransform* phase) {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return in(1);
-
-  if (in(1)->is_DecodeNKlass()) {
-    // (EncodePKlass (DecodeNKlass p)) -> p
-    return in(1)->in(1);
-  }
-  return this;
-}
-
-const Type *EncodePKlassNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if (t == Type::TOP) return Type::TOP;
-  assert (t != TypePtr::NULL_PTR, "null klass?");
-
-  assert(UseCompressedClassPointers && t->isa_klassptr(), "only klass ptr here");
-  return t->make_narrowklass();
-}
-
-
-//=============================================================================
-//------------------------------Identity---------------------------------------
-Node *Conv2BNode::Identity( PhaseTransform *phase ) {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return in(1);
-  if( t == TypeInt::ZERO ) return in(1);
-  if( t == TypeInt::ONE ) return in(1);
-  if( t == TypeInt::BOOL ) return in(1);
-  return this;
-}
-
-//------------------------------Value------------------------------------------
-const Type *Conv2BNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == TypeInt::ZERO ) return TypeInt::ZERO;
-  if( t == TypePtr::NULL_PTR ) return TypeInt::ZERO;
-  const TypePtr *tp = t->isa_ptr();
-  if( tp != NULL ) {
-    if( tp->ptr() == TypePtr::AnyNull ) return Type::TOP;
-    if( tp->ptr() == TypePtr::Constant) return TypeInt::ONE;
-    if (tp->ptr() == TypePtr::NotNull)  return TypeInt::ONE;
-    return TypeInt::BOOL;
-  }
-  if (t->base() != Type::Int) return TypeInt::BOOL;
-  const TypeInt *ti = t->is_int();
-  if( ti->_hi < 0 || ti->_lo > 0 ) return TypeInt::ONE;
-  return TypeInt::BOOL;
-}
-
-
-// The conversions operations are all Alpha sorted.  Please keep it that way!
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvD2FNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == Type::DOUBLE ) return Type::FLOAT;
-  const TypeD *td = t->is_double_constant();
-  return TypeF::make( (float)td->getd() );
-}
-
-//------------------------------Identity---------------------------------------
-// Float's can be converted to doubles with no loss of bits.  Hence
-// converting a float to a double and back to a float is a NOP.
-Node *ConvD2FNode::Identity(PhaseTransform *phase) {
-  return (in(1)->Opcode() == Op_ConvF2D) ? in(1)->in(1) : this;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvD2INode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == Type::DOUBLE ) return TypeInt::INT;
-  const TypeD *td = t->is_double_constant();
-  return TypeInt::make( SharedRuntime::d2i( td->getd() ) );
-}
-
-//------------------------------Ideal------------------------------------------
-// If converting to an int type, skip any rounding nodes
-Node *ConvD2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if( in(1)->Opcode() == Op_RoundDouble )
-    set_req(1,in(1)->in(1));
-  return NULL;
-}
-
-//------------------------------Identity---------------------------------------
-// Int's can be converted to doubles with no loss of bits.  Hence
-// converting an integer to a double and back to an integer is a NOP.
-Node *ConvD2INode::Identity(PhaseTransform *phase) {
-  return (in(1)->Opcode() == Op_ConvI2D) ? in(1)->in(1) : this;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvD2LNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == Type::DOUBLE ) return TypeLong::LONG;
-  const TypeD *td = t->is_double_constant();
-  return TypeLong::make( SharedRuntime::d2l( td->getd() ) );
-}
-
-//------------------------------Identity---------------------------------------
-Node *ConvD2LNode::Identity(PhaseTransform *phase) {
-  // Remove ConvD2L->ConvL2D->ConvD2L sequences.
-  if( in(1)       ->Opcode() == Op_ConvL2D &&
-      in(1)->in(1)->Opcode() == Op_ConvD2L )
-    return in(1)->in(1);
-  return this;
-}
-
-//------------------------------Ideal------------------------------------------
-// If converting to an int type, skip any rounding nodes
-Node *ConvD2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if( in(1)->Opcode() == Op_RoundDouble )
-    set_req(1,in(1)->in(1));
-  return NULL;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvF2DNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == Type::FLOAT ) return Type::DOUBLE;
-  const TypeF *tf = t->is_float_constant();
-  return TypeD::make( (double)tf->getf() );
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvF2INode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP )       return Type::TOP;
-  if( t == Type::FLOAT ) return TypeInt::INT;
-  const TypeF *tf = t->is_float_constant();
-  return TypeInt::make( SharedRuntime::f2i( tf->getf() ) );
-}
-
-//------------------------------Identity---------------------------------------
-Node *ConvF2INode::Identity(PhaseTransform *phase) {
-  // Remove ConvF2I->ConvI2F->ConvF2I sequences.
-  if( in(1)       ->Opcode() == Op_ConvI2F &&
-      in(1)->in(1)->Opcode() == Op_ConvF2I )
-    return in(1)->in(1);
-  return this;
-}
-
-//------------------------------Ideal------------------------------------------
-// If converting to an int type, skip any rounding nodes
-Node *ConvF2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if( in(1)->Opcode() == Op_RoundFloat )
-    set_req(1,in(1)->in(1));
-  return NULL;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvF2LNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP )       return Type::TOP;
-  if( t == Type::FLOAT ) return TypeLong::LONG;
-  const TypeF *tf = t->is_float_constant();
-  return TypeLong::make( SharedRuntime::f2l( tf->getf() ) );
-}
-
-//------------------------------Identity---------------------------------------
-Node *ConvF2LNode::Identity(PhaseTransform *phase) {
-  // Remove ConvF2L->ConvL2F->ConvF2L sequences.
-  if( in(1)       ->Opcode() == Op_ConvL2F &&
-      in(1)->in(1)->Opcode() == Op_ConvF2L )
-    return in(1)->in(1);
-  return this;
-}
-
-//------------------------------Ideal------------------------------------------
-// If converting to an int type, skip any rounding nodes
-Node *ConvF2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if( in(1)->Opcode() == Op_RoundFloat )
-    set_req(1,in(1)->in(1));
-  return NULL;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvI2DNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeInt *ti = t->is_int();
-  if( ti->is_con() ) return TypeD::make( (double)ti->get_con() );
-  return bottom_type();
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvI2FNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeInt *ti = t->is_int();
-  if( ti->is_con() ) return TypeF::make( (float)ti->get_con() );
-  return bottom_type();
-}
-
-//------------------------------Identity---------------------------------------
-Node *ConvI2FNode::Identity(PhaseTransform *phase) {
-  // Remove ConvI2F->ConvF2I->ConvI2F sequences.
-  if( in(1)       ->Opcode() == Op_ConvF2I &&
-      in(1)->in(1)->Opcode() == Op_ConvI2F )
-    return in(1)->in(1);
-  return this;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvI2LNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeInt *ti = t->is_int();
-  const Type* tl = TypeLong::make(ti->_lo, ti->_hi, ti->_widen);
-  // Join my declared type against my incoming type.
-  tl = tl->filter(_type);
-  return tl;
-}
-
-#ifdef _LP64
-static inline bool long_ranges_overlap(jlong lo1, jlong hi1,
-                                       jlong lo2, jlong hi2) {
-  // Two ranges overlap iff one range's low point falls in the other range.
-  return (lo2 <= lo1 && lo1 <= hi2) || (lo1 <= lo2 && lo2 <= hi1);
-}
-#endif
-
-//------------------------------Ideal------------------------------------------
-Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  const TypeLong* this_type = this->type()->is_long();
-  Node* this_changed = NULL;
-
-  // If _major_progress, then more loop optimizations follow.  Do NOT
-  // remove this node's type assertion until no more loop ops can happen.
-  // The progress bit is set in the major loop optimizations THEN comes the
-  // call to IterGVN and any chance of hitting this code.  Cf. Opaque1Node.
-  if (can_reshape && !phase->C->major_progress()) {
-    const TypeInt* in_type = phase->type(in(1))->isa_int();
-    if (in_type != NULL && this_type != NULL &&
-        (in_type->_lo != this_type->_lo ||
-         in_type->_hi != this_type->_hi)) {
-      // Although this WORSENS the type, it increases GVN opportunities,
-      // because I2L nodes with the same input will common up, regardless
-      // of slightly differing type assertions.  Such slight differences
-      // arise routinely as a result of loop unrolling, so this is a
-      // post-unrolling graph cleanup.  Choose a type which depends only
-      // on my input.  (Exception:  Keep a range assertion of >=0 or <0.)
-      jlong lo1 = this_type->_lo;
-      jlong hi1 = this_type->_hi;
-      int   w1  = this_type->_widen;
-      if (lo1 != (jint)lo1 ||
-          hi1 != (jint)hi1 ||
-          lo1 > hi1) {
-        // Overflow leads to wraparound, wraparound leads to range saturation.
-        lo1 = min_jint; hi1 = max_jint;
-      } else if (lo1 >= 0) {
-        // Keep a range assertion of >=0.
-        lo1 = 0;        hi1 = max_jint;
-      } else if (hi1 < 0) {
-        // Keep a range assertion of <0.
-        lo1 = min_jint; hi1 = -1;
-      } else {
-        lo1 = min_jint; hi1 = max_jint;
-      }
-      const TypeLong* wtype = TypeLong::make(MAX2((jlong)in_type->_lo, lo1),
-                                             MIN2((jlong)in_type->_hi, hi1),
-                                             MAX2((int)in_type->_widen, w1));
-      if (wtype != type()) {
-        set_type(wtype);
-        // Note: this_type still has old type value, for the logic below.
-        this_changed = this;
-      }
-    }
-  }
-
-#ifdef _LP64
-  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) ,
-  // but only if x and y have subranges that cannot cause 32-bit overflow,
-  // under the assumption that x+y is in my own subrange this->type().
-
-  // This assumption is based on a constraint (i.e., type assertion)
-  // established in Parse::array_addressing or perhaps elsewhere.
-  // This constraint has been adjoined to the "natural" type of
-  // the incoming argument in(0).  We know (because of runtime
-  // checks) - that the result value I2L(x+y) is in the joined range.
-  // Hence we can restrict the incoming terms (x, y) to values such
-  // that their sum also lands in that range.
-
-  // This optimization is useful only on 64-bit systems, where we hope
-  // the addition will end up subsumed in an addressing mode.
-  // It is necessary to do this when optimizing an unrolled array
-  // copy loop such as x[i++] = y[i++].
-
-  // On 32-bit systems, it's better to perform as much 32-bit math as
-  // possible before the I2L conversion, because 32-bit math is cheaper.
-  // There's no common reason to "leak" a constant offset through the I2L.
-  // Addressing arithmetic will not absorb it as part of a 64-bit AddL.
-
-  Node* z = in(1);
-  int op = z->Opcode();
-  if (op == Op_AddI || op == Op_SubI) {
-    Node* x = z->in(1);
-    Node* y = z->in(2);
-    assert (x != z && y != z, "dead loop in ConvI2LNode::Ideal");
-    if (phase->type(x) == Type::TOP)  return this_changed;
-    if (phase->type(y) == Type::TOP)  return this_changed;
-    const TypeInt*  tx = phase->type(x)->is_int();
-    const TypeInt*  ty = phase->type(y)->is_int();
-    const TypeLong* tz = this_type;
-    jlong xlo = tx->_lo;
-    jlong xhi = tx->_hi;
-    jlong ylo = ty->_lo;
-    jlong yhi = ty->_hi;
-    jlong zlo = tz->_lo;
-    jlong zhi = tz->_hi;
-    jlong vbit = CONST64(1) << BitsPerInt;
-    int widen =  MAX2(tx->_widen, ty->_widen);
-    if (op == Op_SubI) {
-      jlong ylo0 = ylo;
-      ylo = -yhi;
-      yhi = -ylo0;
-    }
-    // See if x+y can cause positive overflow into z+2**32
-    if (long_ranges_overlap(xlo+ylo, xhi+yhi, zlo+vbit, zhi+vbit)) {
-      return this_changed;
-    }
-    // See if x+y can cause negative overflow into z-2**32
-    if (long_ranges_overlap(xlo+ylo, xhi+yhi, zlo-vbit, zhi-vbit)) {
-      return this_changed;
-    }
-    // Now it's always safe to assume x+y does not overflow.
-    // This is true even if some pairs x,y might cause overflow, as long
-    // as that overflow value cannot fall into [zlo,zhi].
-
-    // Confident that the arithmetic is "as if infinite precision",
-    // we can now use z's range to put constraints on those of x and y.
-    // The "natural" range of x [xlo,xhi] can perhaps be narrowed to a
-    // more "restricted" range by intersecting [xlo,xhi] with the
-    // range obtained by subtracting y's range from the asserted range
-    // of the I2L conversion.  Here's the interval arithmetic algebra:
-    //    x == z-y == [zlo,zhi]-[ylo,yhi] == [zlo,zhi]+[-yhi,-ylo]
-    //    => x in [zlo-yhi, zhi-ylo]
-    //    => x in [zlo-yhi, zhi-ylo] INTERSECT [xlo,xhi]
-    //    => x in [xlo MAX zlo-yhi, xhi MIN zhi-ylo]
-    jlong rxlo = MAX2(xlo, zlo - yhi);
-    jlong rxhi = MIN2(xhi, zhi - ylo);
-    // And similarly, x changing place with y:
-    jlong rylo = MAX2(ylo, zlo - xhi);
-    jlong ryhi = MIN2(yhi, zhi - xlo);
-    if (rxlo > rxhi || rylo > ryhi) {
-      return this_changed;  // x or y is dying; don't mess w/ it
-    }
-    if (op == Op_SubI) {
-      jlong rylo0 = rylo;
-      rylo = -ryhi;
-      ryhi = -rylo0;
-    }
-
-    Node* cx = phase->transform( new (phase->C) ConvI2LNode(x, TypeLong::make(rxlo, rxhi, widen)) );
-    Node* cy = phase->transform( new (phase->C) ConvI2LNode(y, TypeLong::make(rylo, ryhi, widen)) );
-    switch (op) {
-    case Op_AddI:  return new (phase->C) AddLNode(cx, cy);
-    case Op_SubI:  return new (phase->C) SubLNode(cx, cy);
-    default:       ShouldNotReachHere();
-    }
-  }
-#endif //_LP64
-
-  return this_changed;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvL2DNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeLong *tl = t->is_long();
-  if( tl->is_con() ) return TypeD::make( (double)tl->get_con() );
-  return bottom_type();
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *ConvL2FNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeLong *tl = t->is_long();
-  if( tl->is_con() ) return TypeF::make( (float)tl->get_con() );
-  return bottom_type();
-}
-
-//=============================================================================
-//----------------------------Identity-----------------------------------------
-Node *ConvL2INode::Identity( PhaseTransform *phase ) {
-  // Convert L2I(I2L(x)) => x
-  if (in(1)->Opcode() == Op_ConvI2L)  return in(1)->in(1);
-  return this;
-}
-
-//------------------------------Value------------------------------------------
-const Type *ConvL2INode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeLong *tl = t->is_long();
-  if (tl->is_con())
-    // Easy case.
-    return TypeInt::make((jint)tl->get_con());
-  return bottom_type();
-}
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.
-// Blow off prior masking to int
-Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  Node *andl = in(1);
-  uint andl_op = andl->Opcode();
-  if( andl_op == Op_AndL ) {
-    // Blow off prior masking to int
-    if( phase->type(andl->in(2)) == TypeLong::make( 0xFFFFFFFF ) ) {
-      set_req(1,andl->in(1));
-      return this;
-    }
-  }
-
-  // Swap with a prior add: convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y))
-  // This replaces an 'AddL' with an 'AddI'.
-  if( andl_op == Op_AddL ) {
-    // Don't do this for nodes which have more than one user since
-    // we'll end up computing the long add anyway.
-    if (andl->outcnt() > 1) return NULL;
-
-    Node* x = andl->in(1);
-    Node* y = andl->in(2);
-    assert( x != andl && y != andl, "dead loop in ConvL2INode::Ideal" );
-    if (phase->type(x) == Type::TOP)  return NULL;
-    if (phase->type(y) == Type::TOP)  return NULL;
-    Node *add1 = phase->transform(new (phase->C) ConvL2INode(x));
-    Node *add2 = phase->transform(new (phase->C) ConvL2INode(y));
-    return new (phase->C) AddINode(add1,add2);
-  }
-
-  // Disable optimization: LoadL->ConvL2I ==> LoadI.
-  // It causes problems (sizes of Load and Store nodes do not match)
-  // in objects initialization code and Escape Analysis.
-  return NULL;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *CastX2PNode::Value( PhaseTransform *phase ) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  if (t->base() == Type_X && t->singleton()) {
-    uintptr_t bits = (uintptr_t) t->is_intptr_t()->get_con();
-    if (bits == 0)   return TypePtr::NULL_PTR;
-    return TypeRawPtr::make((address) bits);
-  }
-  return CastX2PNode::bottom_type();
-}
-
-//------------------------------Idealize---------------------------------------
-static inline bool fits_in_int(const Type* t, bool but_not_min_int = false) {
-  if (t == Type::TOP)  return false;
-  const TypeX* tl = t->is_intptr_t();
-  jint lo = min_jint;
-  jint hi = max_jint;
-  if (but_not_min_int)  ++lo;  // caller wants to negate the value w/o overflow
-  return (tl->_lo >= lo) && (tl->_hi <= hi);
-}
-
-static inline Node* addP_of_X2P(PhaseGVN *phase,
-                                Node* base,
-                                Node* dispX,
-                                bool negate = false) {
-  if (negate) {
-    dispX = new (phase->C) SubXNode(phase->MakeConX(0), phase->transform(dispX));
-  }
-  return new (phase->C) AddPNode(phase->C->top(),
-                          phase->transform(new (phase->C) CastX2PNode(base)),
-                          phase->transform(dispX));
-}
-
-Node *CastX2PNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  // convert CastX2P(AddX(x, y)) to AddP(CastX2P(x), y) if y fits in an int
-  int op = in(1)->Opcode();
-  Node* x;
-  Node* y;
-  switch (op) {
-  case Op_SubX:
-    x = in(1)->in(1);
-    // Avoid ideal transformations ping-pong between this and AddP for raw pointers.
-    if (phase->find_intptr_t_con(x, -1) == 0)
-      break;
-    y = in(1)->in(2);
-    if (fits_in_int(phase->type(y), true)) {
-      return addP_of_X2P(phase, x, y, true);
-    }
-    break;
-  case Op_AddX:
-    x = in(1)->in(1);
-    y = in(1)->in(2);
-    if (fits_in_int(phase->type(y))) {
-      return addP_of_X2P(phase, x, y);
-    }
-    if (fits_in_int(phase->type(x))) {
-      return addP_of_X2P(phase, y, x);
-    }
-    break;
-  }
-  return NULL;
-}
-
-//------------------------------Identity---------------------------------------
-Node *CastX2PNode::Identity( PhaseTransform *phase ) {
-  if (in(1)->Opcode() == Op_CastP2X)  return in(1)->in(1);
-  return this;
-}
-
-//=============================================================================
-//------------------------------Value------------------------------------------
-const Type *CastP2XNode::Value( PhaseTransform *phase ) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  if (t->base() == Type::RawPtr && t->singleton()) {
-    uintptr_t bits = (uintptr_t) t->is_rawptr()->get_con();
-    return TypeX::make(bits);
-  }
-  return CastP2XNode::bottom_type();
-}
-
-Node *CastP2XNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
-}
-
-//------------------------------Identity---------------------------------------
-Node *CastP2XNode::Identity( PhaseTransform *phase ) {
-  if (in(1)->Opcode() == Op_CastX2P)  return in(1)->in(1);
-  return this;
-}
-
-
-//=============================================================================
-//------------------------------Identity---------------------------------------
-// Remove redundant roundings
-Node *RoundFloatNode::Identity( PhaseTransform *phase ) {
-  assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
-  // Do not round constants
-  if (phase->type(in(1))->base() == Type::FloatCon)  return in(1);
-  int op = in(1)->Opcode();
-  // Redundant rounding
-  if( op == Op_RoundFloat ) return in(1);
-  // Already rounded
-  if( op == Op_Parm ) return in(1);
-  if( op == Op_LoadF ) return in(1);
-  return this;
-}
-
-//------------------------------Value------------------------------------------
-const Type *RoundFloatNode::Value( PhaseTransform *phase ) const {
-  return phase->type( in(1) );
-}
-
-//=============================================================================
-//------------------------------Identity---------------------------------------
-// Remove redundant roundings.  Incoming arguments are already rounded.
-Node *RoundDoubleNode::Identity( PhaseTransform *phase ) {
-  assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
-  // Do not round constants
-  if (phase->type(in(1))->base() == Type::DoubleCon)  return in(1);
-  int op = in(1)->Opcode();
-  // Redundant rounding
-  if( op == Op_RoundDouble ) return in(1);
-  // Already rounded
-  if( op == Op_Parm ) return in(1);
-  if( op == Op_LoadD ) return in(1);
-  if( op == Op_ConvF2D ) return in(1);
-  if( op == Op_ConvI2D ) return in(1);
-  return this;
-}
-
-//------------------------------Value------------------------------------------
-const Type *RoundDoubleNode::Value( PhaseTransform *phase ) const {
-  return phase->type( in(1) );
-}
-
-
-//=============================================================================
-// Do not allow value-numbering
-uint Opaque1Node::hash() const { return NO_HASH; }
-uint Opaque1Node::cmp( const Node &n ) const {
-  return (&n == this);          // Always fail except on self
-}
-
-//------------------------------Identity---------------------------------------
-// If _major_progress, then more loop optimizations follow.  Do NOT remove
-// the opaque Node until no more loop ops can happen.  Note the timing of
-// _major_progress; it's set in the major loop optimizations THEN comes the
-// call to IterGVN and any chance of hitting this code.  Hence there's no
-// phase-ordering problem with stripping Opaque1 in IGVN followed by some
-// more loop optimizations that require it.
-Node *Opaque1Node::Identity( PhaseTransform *phase ) {
-  return phase->C->major_progress() ? this : in(1);
-}
-
-//=============================================================================
-// A node to prevent unwanted optimizations.  Allows constant folding.  Stops
-// value-numbering, most Ideal calls or Identity functions.  This Node is
-// specifically designed to prevent the pre-increment value of a loop trip
-// counter from being live out of the bottom of the loop (hence causing the
-// pre- and post-increment values both being live and thus requiring an extra
-// temp register and an extra move).  If we "accidentally" optimize through
-// this kind of a Node, we'll get slightly pessimal, but correct, code.  Thus
-// it's OK to be slightly sloppy on optimizations here.
-
-// Do not allow value-numbering
-uint Opaque2Node::hash() const { return NO_HASH; }
-uint Opaque2Node::cmp( const Node &n ) const {
-  return (&n == this);          // Always fail except on self
-}
-
-
-//------------------------------Value------------------------------------------
-const Type *MoveL2DNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeLong *tl = t->is_long();
-  if( !tl->is_con() ) return bottom_type();
-  JavaValue v;
-  v.set_jlong(tl->get_con());
-  return TypeD::make( v.get_jdouble() );
-}
-
-//------------------------------Value------------------------------------------
-const Type *MoveI2FNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  const TypeInt *ti = t->is_int();
-  if( !ti->is_con() )   return bottom_type();
-  JavaValue v;
-  v.set_jint(ti->get_con());
-  return TypeF::make( v.get_jfloat() );
-}
-
-//------------------------------Value------------------------------------------
-const Type *MoveF2INode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP )       return Type::TOP;
-  if( t == Type::FLOAT ) return TypeInt::INT;
-  const TypeF *tf = t->is_float_constant();
-  JavaValue v;
-  v.set_jfloat(tf->getf());
-  return TypeInt::make( v.get_jint() );
-}
-
-//------------------------------Value------------------------------------------
-const Type *MoveD2LNode::Value( PhaseTransform *phase ) const {
-  const Type *t = phase->type( in(1) );
-  if( t == Type::TOP ) return Type::TOP;
-  if( t == Type::DOUBLE ) return TypeLong::LONG;
-  const TypeD *td = t->is_double_constant();
-  JavaValue v;
-  v.set_jdouble(td->getd());
-  return TypeLong::make( v.get_jlong() );
-}
-
-//------------------------------Value------------------------------------------
-const Type* CountLeadingZerosINode::Value(PhaseTransform* phase) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  const TypeInt* ti = t->isa_int();
-  if (ti && ti->is_con()) {
-    jint i = ti->get_con();
-    // HD, Figure 5-6
-    if (i == 0)
-      return TypeInt::make(BitsPerInt);
-    int n = 1;
-    unsigned int x = i;
-    if (x >> 16 == 0) { n += 16; x <<= 16; }
-    if (x >> 24 == 0) { n +=  8; x <<=  8; }
-    if (x >> 28 == 0) { n +=  4; x <<=  4; }
-    if (x >> 30 == 0) { n +=  2; x <<=  2; }
-    n -= x >> 31;
-    return TypeInt::make(n);
-  }
-  return TypeInt::INT;
-}
-
-//------------------------------Value------------------------------------------
-const Type* CountLeadingZerosLNode::Value(PhaseTransform* phase) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  const TypeLong* tl = t->isa_long();
-  if (tl && tl->is_con()) {
-    jlong l = tl->get_con();
-    // HD, Figure 5-6
-    if (l == 0)
-      return TypeInt::make(BitsPerLong);
-    int n = 1;
-    unsigned int x = (((julong) l) >> 32);
-    if (x == 0) { n += 32; x = (int) l; }
-    if (x >> 16 == 0) { n += 16; x <<= 16; }
-    if (x >> 24 == 0) { n +=  8; x <<=  8; }
-    if (x >> 28 == 0) { n +=  4; x <<=  4; }
-    if (x >> 30 == 0) { n +=  2; x <<=  2; }
-    n -= x >> 31;
-    return TypeInt::make(n);
-  }
-  return TypeInt::INT;
-}
-
-//------------------------------Value------------------------------------------
-const Type* CountTrailingZerosINode::Value(PhaseTransform* phase) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  const TypeInt* ti = t->isa_int();
-  if (ti && ti->is_con()) {
-    jint i = ti->get_con();
-    // HD, Figure 5-14
-    int y;
-    if (i == 0)
-      return TypeInt::make(BitsPerInt);
-    int n = 31;
-    y = i << 16; if (y != 0) { n = n - 16; i = y; }
-    y = i <<  8; if (y != 0) { n = n -  8; i = y; }
-    y = i <<  4; if (y != 0) { n = n -  4; i = y; }
-    y = i <<  2; if (y != 0) { n = n -  2; i = y; }
-    y = i <<  1; if (y != 0) { n = n -  1; }
-    return TypeInt::make(n);
-  }
-  return TypeInt::INT;
-}
-
-//------------------------------Value------------------------------------------
-const Type* CountTrailingZerosLNode::Value(PhaseTransform* phase) const {
-  const Type* t = phase->type(in(1));
-  if (t == Type::TOP) return Type::TOP;
-  const TypeLong* tl = t->isa_long();
-  if (tl && tl->is_con()) {
-    jlong l = tl->get_con();
-    // HD, Figure 5-14
-    int x, y;
-    if (l == 0)
-      return TypeInt::make(BitsPerLong);
-    int n = 63;
-    y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32);
-    y = x << 16; if (y != 0) { n = n - 16; x = y; }
-    y = x <<  8; if (y != 0) { n = n -  8; x = y; }
-    y = x <<  4; if (y != 0) { n = n -  4; x = y; }
-    y = x <<  2; if (y != 0) { n = n -  2; x = y; }
-    y = x <<  1; if (y != 0) { n = n -  1; }
-    return TypeInt::make(n);
-  }
-  return TypeInt::INT;
-}
--- a/hotspot/src/share/vm/opto/connode.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/connode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -139,617 +139,16 @@
 
 };
 
-//------------------------------BinaryNode-------------------------------------
-// Place holder for the 2 conditional inputs to a CMove.  CMove needs 4
-// inputs: the Bool (for the lt/gt/eq/ne bits), the flags (result of some
-// compare), and the 2 values to select between.  The Matcher requires a
-// binary tree so we break it down like this:
-//     (CMove (Binary bol cmp) (Binary src1 src2))
-class BinaryNode : public Node {
-public:
-  BinaryNode( Node *n1, Node *n2 ) : Node(0,n1,n2) { }
-  virtual int Opcode() const;
-  virtual uint ideal_reg() const { return 0; }
-};
-
-//------------------------------CMoveNode--------------------------------------
-// Conditional move
-class CMoveNode : public TypeNode {
-public:
-  enum { Control,               // When is it safe to do this cmove?
-         Condition,             // Condition controlling the cmove
-         IfFalse,               // Value if condition is false
-         IfTrue };              // Value if condition is true
-  CMoveNode( Node *bol, Node *left, Node *right, const Type *t ) : TypeNode(t,4)
-  {
-    init_class_id(Class_CMove);
-    // all inputs are nullified in Node::Node(int)
-    // init_req(Control,NULL);
-    init_req(Condition,bol);
-    init_req(IfFalse,left);
-    init_req(IfTrue,right);
-  }
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  static CMoveNode *make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t );
-  // Helper function to spot cmove graph shapes
-  static Node *is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b );
-};
-
-//------------------------------CMoveDNode-------------------------------------
-class CMoveDNode : public CMoveNode {
-public:
-  CMoveDNode( Node *bol, Node *left, Node *right, const Type* t) : CMoveNode(bol,left,right,t){}
-  virtual int Opcode() const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-};
-
-//------------------------------CMoveFNode-------------------------------------
-class CMoveFNode : public CMoveNode {
-public:
-  CMoveFNode( Node *bol, Node *left, Node *right, const Type* t ) : CMoveNode(bol,left,right,t) {}
-  virtual int Opcode() const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-};
-
-//------------------------------CMoveINode-------------------------------------
-class CMoveINode : public CMoveNode {
-public:
-  CMoveINode( Node *bol, Node *left, Node *right, const TypeInt *ti ) : CMoveNode(bol,left,right,ti){}
-  virtual int Opcode() const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-};
-
-//------------------------------CMoveLNode-------------------------------------
-class CMoveLNode : public CMoveNode {
-public:
-  CMoveLNode(Node *bol, Node *left, Node *right, const TypeLong *tl ) : CMoveNode(bol,left,right,tl){}
-  virtual int Opcode() const;
-};
-
-//------------------------------CMovePNode-------------------------------------
-class CMovePNode : public CMoveNode {
-public:
-  CMovePNode( Node *c, Node *bol, Node *left, Node *right, const TypePtr* t ) : CMoveNode(bol,left,right,t) { init_req(Control,c); }
-  virtual int Opcode() const;
-};
-
-//------------------------------CMoveNNode-------------------------------------
-class CMoveNNode : public CMoveNode {
-public:
-  CMoveNNode( Node *c, Node *bol, Node *left, Node *right, const Type* t ) : CMoveNode(bol,left,right,t) { init_req(Control,c); }
-  virtual int Opcode() const;
-};
-
-//------------------------------ConstraintCastNode-----------------------------
-// cast to a different range
-class ConstraintCastNode: public TypeNode {
-public:
-  ConstraintCastNode (Node *n, const Type *t ): TypeNode(t,2) {
-    init_class_id(Class_ConstraintCast);
-    init_req(1, n);
-  }
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual int Opcode() const;
-  virtual uint ideal_reg() const = 0;
-  virtual Node *Ideal_DU_postCCP( PhaseCCP * );
-};
-
-//------------------------------CastIINode-------------------------------------
-// cast integer to integer (different range)
-class CastIINode: public ConstraintCastNode {
-public:
-  CastIINode (Node *n, const Type *t ): ConstraintCastNode(n,t) {}
-  virtual int Opcode() const;
-  virtual uint ideal_reg() const { return Op_RegI; }
-};
-
-//------------------------------CastPPNode-------------------------------------
-// cast pointer to pointer (different type)
-class CastPPNode: public ConstraintCastNode {
-public:
-  CastPPNode (Node *n, const Type *t ): ConstraintCastNode(n, t) {}
-  virtual int Opcode() const;
-  virtual uint ideal_reg() const { return Op_RegP; }
-  virtual Node *Ideal_DU_postCCP( PhaseCCP * );
-};
-
-//------------------------------CheckCastPPNode--------------------------------
-// for _checkcast, cast pointer to pointer (different type), without JOIN,
-class CheckCastPPNode: public TypeNode {
-public:
-  CheckCastPPNode( Node *c, Node *n, const Type *t ) : TypeNode(t,2) {
-    init_class_id(Class_CheckCastPP);
-    init_req(0, c);
-    init_req(1, n);
-  }
-
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual int   Opcode() const;
-  virtual uint  ideal_reg() const { return Op_RegP; }
-  // No longer remove CheckCast after CCP as it gives me a place to hang
-  // the proper address type - which is required to compute anti-deps.
-  //virtual Node *Ideal_DU_postCCP( PhaseCCP * );
-};
-
-
-//------------------------------EncodeNarrowPtr--------------------------------
-class EncodeNarrowPtrNode : public TypeNode {
- protected:
-  EncodeNarrowPtrNode(Node* value, const Type* type):
-    TypeNode(type, 2) {
-    init_class_id(Class_EncodeNarrowPtr);
-    init_req(0, NULL);
-    init_req(1, value);
-  }
- public:
-  virtual uint  ideal_reg() const { return Op_RegN; }
-  virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
-};
-
-//------------------------------EncodeP--------------------------------
-// Encodes an oop pointers into its compressed form
-// Takes an extra argument which is the real heap base as a long which
-// may be useful for code generation in the backend.
-class EncodePNode : public EncodeNarrowPtrNode {
- public:
-  EncodePNode(Node* value, const Type* type):
-    EncodeNarrowPtrNode(value, type) {
-    init_class_id(Class_EncodeP);
-  }
-  virtual int Opcode() const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-};
-
-//------------------------------EncodePKlass--------------------------------
-// Encodes a klass pointer into its compressed form
-// Takes an extra argument which is the real heap base as a long which
-// may be useful for code generation in the backend.
-class EncodePKlassNode : public EncodeNarrowPtrNode {
- public:
-  EncodePKlassNode(Node* value, const Type* type):
-    EncodeNarrowPtrNode(value, type) {
-    init_class_id(Class_EncodePKlass);
-  }
-  virtual int Opcode() const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-};
-
-//------------------------------DecodeNarrowPtr--------------------------------
-class DecodeNarrowPtrNode : public TypeNode {
- protected:
-  DecodeNarrowPtrNode(Node* value, const Type* type):
-    TypeNode(type, 2) {
-    init_class_id(Class_DecodeNarrowPtr);
-    init_req(0, NULL);
-    init_req(1, value);
-  }
- public:
-  virtual uint  ideal_reg() const { return Op_RegP; }
-};
-
-//------------------------------DecodeN--------------------------------
-// Converts a narrow oop into a real oop ptr.
-// Takes an extra argument which is the real heap base as a long which
-// may be useful for code generation in the backend.
-class DecodeNNode : public DecodeNarrowPtrNode {
- public:
-  DecodeNNode(Node* value, const Type* type):
-    DecodeNarrowPtrNode(value, type) {
-    init_class_id(Class_DecodeN);
-  }
-  virtual int Opcode() const;
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-};
-
-//------------------------------DecodeNKlass--------------------------------
-// Converts a narrow klass pointer into a real klass ptr.
-// Takes an extra argument which is the real heap base as a long which
-// may be useful for code generation in the backend.
-class DecodeNKlassNode : public DecodeNarrowPtrNode {
- public:
-  DecodeNKlassNode(Node* value, const Type* type):
-    DecodeNarrowPtrNode(value, type) {
-    init_class_id(Class_DecodeNKlass);
-  }
-  virtual int Opcode() const;
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-};
-
-//------------------------------Conv2BNode-------------------------------------
-// Convert int/pointer to a Boolean.  Map zero to zero, all else to 1.
-class Conv2BNode : public Node {
-public:
-  Conv2BNode( Node *i ) : Node(0,i) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::BOOL; }
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual uint  ideal_reg() const { return Op_RegI; }
-};
-
-// The conversions operations are all Alpha sorted.  Please keep it that way!
-//------------------------------ConvD2FNode------------------------------------
-// Convert double to float
-class ConvD2FNode : public Node {
-public:
-  ConvD2FNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::FLOAT; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual uint  ideal_reg() const { return Op_RegF; }
-};
-
-//------------------------------ConvD2INode------------------------------------
-// Convert Double to Integer
-class ConvD2INode : public Node {
-public:
-  ConvD2INode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint  ideal_reg() const { return Op_RegI; }
-};
-
-//------------------------------ConvD2LNode------------------------------------
-// Convert Double to Long
-class ConvD2LNode : public Node {
-public:
-  ConvD2LNode( Node *dbl ) : Node(0,dbl) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeLong::LONG; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint ideal_reg() const { return Op_RegL; }
-};
-
-//------------------------------ConvF2DNode------------------------------------
-// Convert Float to a Double.
-class ConvF2DNode : public Node {
-public:
-  ConvF2DNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual uint  ideal_reg() const { return Op_RegD; }
-};
-
-//------------------------------ConvF2INode------------------------------------
-// Convert float to integer
-class ConvF2INode : public Node {
-public:
-  ConvF2INode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint  ideal_reg() const { return Op_RegI; }
-};
-
-//------------------------------ConvF2LNode------------------------------------
-// Convert float to long
-class ConvF2LNode : public Node {
-public:
-  ConvF2LNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeLong::LONG; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint  ideal_reg() const { return Op_RegL; }
-};
-
-//------------------------------ConvI2DNode------------------------------------
-// Convert Integer to Double
-class ConvI2DNode : public Node {
-public:
-  ConvI2DNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual uint  ideal_reg() const { return Op_RegD; }
-};
-
-//------------------------------ConvI2FNode------------------------------------
-// Convert Integer to Float
-class ConvI2FNode : public Node {
-public:
-  ConvI2FNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::FLOAT; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual uint  ideal_reg() const { return Op_RegF; }
-};
-
-//------------------------------ConvI2LNode------------------------------------
-// Convert integer to long
-class ConvI2LNode : public TypeNode {
-public:
-  ConvI2LNode(Node *in1, const TypeLong* t = TypeLong::INT)
-    : TypeNode(t, 2)
-  { init_req(1, in1); }
-  virtual int Opcode() const;
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint  ideal_reg() const { return Op_RegL; }
-};
-
-//------------------------------ConvL2DNode------------------------------------
-// Convert Long to Double
-class ConvL2DNode : public Node {
-public:
-  ConvL2DNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual uint ideal_reg() const { return Op_RegD; }
-};
-
-//------------------------------ConvL2FNode------------------------------------
-// Convert Long to Float
-class ConvL2FNode : public Node {
-public:
-  ConvL2FNode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::FLOAT; }
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual uint  ideal_reg() const { return Op_RegF; }
-};
-
-//------------------------------ConvL2INode------------------------------------
-// Convert long to integer
-class ConvL2INode : public Node {
-public:
-  ConvL2INode( Node *in1 ) : Node(0,in1) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual uint  ideal_reg() const { return Op_RegI; }
-};
-
-//------------------------------CastX2PNode-------------------------------------
-// convert a machine-pointer-sized integer to a raw pointer
-class CastX2PNode : public Node {
-public:
-  CastX2PNode( Node *n ) : Node(NULL, n) {}
-  virtual int Opcode() const;
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual uint ideal_reg() const { return Op_RegP; }
-  virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
-};
-
-//------------------------------CastP2XNode-------------------------------------
-// Used in both 32-bit and 64-bit land.
-// Used for card-marks and unsafe pointer math.
-class CastP2XNode : public Node {
-public:
-  CastP2XNode( Node *ctrl, Node *n ) : Node(ctrl, n) {}
-  virtual int Opcode() const;
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual uint ideal_reg() const { return Op_RegX; }
-  virtual const Type *bottom_type() const { return TypeX_X; }
-  // Return false to keep node from moving away from an associated card mark.
-  virtual bool depends_only_on_test() const { return false; }
-};
-
 //------------------------------ThreadLocalNode--------------------------------
 // Ideal Node which returns the base of ThreadLocalStorage.
 class ThreadLocalNode : public Node {
 public:
-  ThreadLocalNode( ) : Node((Node*)Compile::current()->root()) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM;}
-  virtual uint ideal_reg() const { return Op_RegP; }
-};
-
-//------------------------------LoadReturnPCNode-------------------------------
-class LoadReturnPCNode: public Node {
-public:
-  LoadReturnPCNode(Node *c) : Node(c) { }
-  virtual int Opcode() const;
-  virtual uint ideal_reg() const { return Op_RegP; }
-};
-
-
-//-----------------------------RoundFloatNode----------------------------------
-class RoundFloatNode: public Node {
-public:
-  RoundFloatNode(Node* c, Node *in1): Node(c, in1) {}
-  virtual int   Opcode() const;
-  virtual const Type *bottom_type() const { return Type::FLOAT; }
-  virtual uint  ideal_reg() const { return Op_RegF; }
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
+    ThreadLocalNode( ) : Node((Node*)Compile::current()->root()) {}
+    virtual int Opcode() const;
+    virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM;}
+    virtual uint ideal_reg() const { return Op_RegP; }
 };
 
 
-//-----------------------------RoundDoubleNode---------------------------------
-class RoundDoubleNode: public Node {
-public:
-  RoundDoubleNode(Node* c, Node *in1): Node(c, in1) {}
-  virtual int   Opcode() const;
-  virtual const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual uint  ideal_reg() const { return Op_RegD; }
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-};
-
-//------------------------------Opaque1Node------------------------------------
-// A node to prevent unwanted optimizations.  Allows constant folding.
-// Stops value-numbering, Ideal calls or Identity functions.
-class Opaque1Node : public Node {
-  virtual uint hash() const ;                  // { return NO_HASH; }
-  virtual uint cmp( const Node &n ) const;
-public:
-  Opaque1Node( Compile* C, Node *n ) : Node(0,n) {
-    // Put it on the Macro nodes list to removed during macro nodes expansion.
-    init_flags(Flag_is_macro);
-    C->add_macro_node(this);
-  }
-  // Special version for the pre-loop to hold the original loop limit
-  // which is consumed by range check elimination.
-  Opaque1Node( Compile* C, Node *n, Node* orig_limit ) : Node(0,n,orig_limit) {
-    // Put it on the Macro nodes list to removed during macro nodes expansion.
-    init_flags(Flag_is_macro);
-    C->add_macro_node(this);
-  }
-  Node* original_loop_limit() { return req()==3 ? in(2) : NULL; }
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-  virtual Node *Identity( PhaseTransform *phase );
-};
-
-//------------------------------Opaque2Node------------------------------------
-// A node to prevent unwanted optimizations.  Allows constant folding.  Stops
-// value-numbering, most Ideal calls or Identity functions.  This Node is
-// specifically designed to prevent the pre-increment value of a loop trip
-// counter from being live out of the bottom of the loop (hence causing the
-// pre- and post-increment values both being live and thus requiring an extra
-// temp register and an extra move).  If we "accidentally" optimize through
-// this kind of a Node, we'll get slightly pessimal, but correct, code.  Thus
-// it's OK to be slightly sloppy on optimizations here.
-class Opaque2Node : public Node {
-  virtual uint hash() const ;                  // { return NO_HASH; }
-  virtual uint cmp( const Node &n ) const;
-public:
-  Opaque2Node( Compile* C, Node *n ) : Node(0,n) {
-    // Put it on the Macro nodes list to removed during macro nodes expansion.
-    init_flags(Flag_is_macro);
-    C->add_macro_node(this);
-  }
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-};
-
-//----------------------PartialSubtypeCheckNode--------------------------------
-// The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
-// array for an instance of the superklass.  Set a hidden internal cache on a
-// hit (cache is checked with exposed code in gen_subtype_check()).  Return
-// not zero for a miss or zero for a hit.
-class PartialSubtypeCheckNode : public Node {
-public:
-  PartialSubtypeCheckNode(Node* c, Node* sub, Node* super) : Node(c,sub,super) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
-  virtual uint ideal_reg() const { return Op_RegP; }
-};
-
-//
-class MoveI2FNode : public Node {
- public:
-  MoveI2FNode( Node *value ) : Node(0,value) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::FLOAT; }
-  virtual uint ideal_reg() const { return Op_RegF; }
-  virtual const Type* Value( PhaseTransform *phase ) const;
-};
-
-class MoveL2DNode : public Node {
- public:
-  MoveL2DNode( Node *value ) : Node(0,value) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return Type::DOUBLE; }
-  virtual uint ideal_reg() const { return Op_RegD; }
-  virtual const Type* Value( PhaseTransform *phase ) const;
-};
-
-class MoveF2INode : public Node {
- public:
-  MoveF2INode( Node *value ) : Node(0,value) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeInt::INT; }
-  virtual uint ideal_reg() const { return Op_RegI; }
-  virtual const Type* Value( PhaseTransform *phase ) const;
-};
-
-class MoveD2LNode : public Node {
- public:
-  MoveD2LNode( Node *value ) : Node(0,value) {}
-  virtual int Opcode() const;
-  virtual const Type *bottom_type() const { return TypeLong::LONG; }
-  virtual uint ideal_reg() const { return Op_RegL; }
-  virtual const Type* Value( PhaseTransform *phase ) const;
-};
-
-//---------- CountBitsNode -----------------------------------------------------
-class CountBitsNode : public Node {
-public:
-  CountBitsNode(Node* in1) : Node(0, in1) {}
-  const Type* bottom_type() const { return TypeInt::INT; }
-  virtual uint ideal_reg() const { return Op_RegI; }
-};
-
-//---------- CountLeadingZerosINode --------------------------------------------
-// Count leading zeros (0-bit count starting from MSB) of an integer.
-class CountLeadingZerosINode : public CountBitsNode {
-public:
-  CountLeadingZerosINode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-  virtual const Type* Value(PhaseTransform* phase) const;
-};
-
-//---------- CountLeadingZerosLNode --------------------------------------------
-// Count leading zeros (0-bit count starting from MSB) of a long.
-class CountLeadingZerosLNode : public CountBitsNode {
-public:
-  CountLeadingZerosLNode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-  virtual const Type* Value(PhaseTransform* phase) const;
-};
-
-//---------- CountTrailingZerosINode -------------------------------------------
-// Count trailing zeros (0-bit count starting from LSB) of an integer.
-class CountTrailingZerosINode : public CountBitsNode {
-public:
-  CountTrailingZerosINode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-  virtual const Type* Value(PhaseTransform* phase) const;
-};
-
-//---------- CountTrailingZerosLNode -------------------------------------------
-// Count trailing zeros (0-bit count starting from LSB) of a long.
-class CountTrailingZerosLNode : public CountBitsNode {
-public:
-  CountTrailingZerosLNode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-  virtual const Type* Value(PhaseTransform* phase) const;
-};
-
-//---------- PopCountINode -----------------------------------------------------
-// Population count (bit count) of an integer.
-class PopCountINode : public CountBitsNode {
-public:
-  PopCountINode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-};
-
-//---------- PopCountLNode -----------------------------------------------------
-// Population count (bit count) of a long.
-class PopCountLNode : public CountBitsNode {
-public:
-  PopCountLNode(Node* in1) : CountBitsNode(in1) {}
-  virtual int Opcode() const;
-};
 
 #endif // SHARE_VM_OPTO_CONNODE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/convertnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 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 "opto/addnode.hpp"
+#include "opto/convertnode.hpp"
+#include "opto/matcher.hpp"
+#include "opto/phaseX.hpp"
+#include "opto/subnode.hpp"
+
+//=============================================================================
+//------------------------------Identity---------------------------------------
+Node *Conv2BNode::Identity( PhaseTransform *phase ) {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return in(1);
+  if( t == TypeInt::ZERO ) return in(1);
+  if( t == TypeInt::ONE ) return in(1);
+  if( t == TypeInt::BOOL ) return in(1);
+  return this;
+}
+
+//------------------------------Value------------------------------------------
+const Type *Conv2BNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == TypeInt::ZERO ) return TypeInt::ZERO;
+  if( t == TypePtr::NULL_PTR ) return TypeInt::ZERO;
+  const TypePtr *tp = t->isa_ptr();
+  if( tp != NULL ) {
+    if( tp->ptr() == TypePtr::AnyNull ) return Type::TOP;
+    if( tp->ptr() == TypePtr::Constant) return TypeInt::ONE;
+    if (tp->ptr() == TypePtr::NotNull)  return TypeInt::ONE;
+    return TypeInt::BOOL;
+  }
+  if (t->base() != Type::Int) return TypeInt::BOOL;
+  const TypeInt *ti = t->is_int();
+  if( ti->_hi < 0 || ti->_lo > 0 ) return TypeInt::ONE;
+  return TypeInt::BOOL;
+}
+
+
+// The conversions operations are all Alpha sorted.  Please keep it that way!
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvD2FNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == Type::DOUBLE ) return Type::FLOAT;
+  const TypeD *td = t->is_double_constant();
+  return TypeF::make( (float)td->getd() );
+}
+
+//------------------------------Identity---------------------------------------
+// Float's can be converted to doubles with no loss of bits.  Hence
+// converting a float to a double and back to a float is a NOP.
+Node *ConvD2FNode::Identity(PhaseTransform *phase) {
+  return (in(1)->Opcode() == Op_ConvF2D) ? in(1)->in(1) : this;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvD2INode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == Type::DOUBLE ) return TypeInt::INT;
+  const TypeD *td = t->is_double_constant();
+  return TypeInt::make( SharedRuntime::d2i( td->getd() ) );
+}
+
+//------------------------------Ideal------------------------------------------
+// If converting to an int type, skip any rounding nodes
+Node *ConvD2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if( in(1)->Opcode() == Op_RoundDouble )
+  set_req(1,in(1)->in(1));
+  return NULL;
+}
+
+//------------------------------Identity---------------------------------------
+// Int's can be converted to doubles with no loss of bits.  Hence
+// converting an integer to a double and back to an integer is a NOP.
+Node *ConvD2INode::Identity(PhaseTransform *phase) {
+  return (in(1)->Opcode() == Op_ConvI2D) ? in(1)->in(1) : this;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvD2LNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == Type::DOUBLE ) return TypeLong::LONG;
+  const TypeD *td = t->is_double_constant();
+  return TypeLong::make( SharedRuntime::d2l( td->getd() ) );
+}
+
+//------------------------------Identity---------------------------------------
+Node *ConvD2LNode::Identity(PhaseTransform *phase) {
+  // Remove ConvD2L->ConvL2D->ConvD2L sequences.
+  if( in(1)       ->Opcode() == Op_ConvL2D &&
+     in(1)->in(1)->Opcode() == Op_ConvD2L )
+  return in(1)->in(1);
+  return this;
+}
+
+//------------------------------Ideal------------------------------------------
+// If converting to an int type, skip any rounding nodes
+Node *ConvD2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if( in(1)->Opcode() == Op_RoundDouble )
+  set_req(1,in(1)->in(1));
+  return NULL;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvF2DNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == Type::FLOAT ) return Type::DOUBLE;
+  const TypeF *tf = t->is_float_constant();
+  return TypeD::make( (double)tf->getf() );
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvF2INode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP )       return Type::TOP;
+  if( t == Type::FLOAT ) return TypeInt::INT;
+  const TypeF *tf = t->is_float_constant();
+  return TypeInt::make( SharedRuntime::f2i( tf->getf() ) );
+}
+
+//------------------------------Identity---------------------------------------
+Node *ConvF2INode::Identity(PhaseTransform *phase) {
+  // Remove ConvF2I->ConvI2F->ConvF2I sequences.
+  if( in(1)       ->Opcode() == Op_ConvI2F &&
+     in(1)->in(1)->Opcode() == Op_ConvF2I )
+  return in(1)->in(1);
+  return this;
+}
+
+//------------------------------Ideal------------------------------------------
+// If converting to an int type, skip any rounding nodes
+Node *ConvF2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if( in(1)->Opcode() == Op_RoundFloat )
+  set_req(1,in(1)->in(1));
+  return NULL;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvF2LNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP )       return Type::TOP;
+  if( t == Type::FLOAT ) return TypeLong::LONG;
+  const TypeF *tf = t->is_float_constant();
+  return TypeLong::make( SharedRuntime::f2l( tf->getf() ) );
+}
+
+//------------------------------Identity---------------------------------------
+Node *ConvF2LNode::Identity(PhaseTransform *phase) {
+  // Remove ConvF2L->ConvL2F->ConvF2L sequences.
+  if( in(1)       ->Opcode() == Op_ConvL2F &&
+     in(1)->in(1)->Opcode() == Op_ConvF2L )
+  return in(1)->in(1);
+  return this;
+}
+
+//------------------------------Ideal------------------------------------------
+// If converting to an int type, skip any rounding nodes
+Node *ConvF2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if( in(1)->Opcode() == Op_RoundFloat )
+  set_req(1,in(1)->in(1));
+  return NULL;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvI2DNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeInt *ti = t->is_int();
+  if( ti->is_con() ) return TypeD::make( (double)ti->get_con() );
+  return bottom_type();
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvI2FNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeInt *ti = t->is_int();
+  if( ti->is_con() ) return TypeF::make( (float)ti->get_con() );
+  return bottom_type();
+}
+
+//------------------------------Identity---------------------------------------
+Node *ConvI2FNode::Identity(PhaseTransform *phase) {
+  // Remove ConvI2F->ConvF2I->ConvI2F sequences.
+  if( in(1)       ->Opcode() == Op_ConvF2I &&
+     in(1)->in(1)->Opcode() == Op_ConvI2F )
+  return in(1)->in(1);
+  return this;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvI2LNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeInt *ti = t->is_int();
+  const Type* tl = TypeLong::make(ti->_lo, ti->_hi, ti->_widen);
+  // Join my declared type against my incoming type.
+  tl = tl->filter(_type);
+  return tl;
+}
+
+#ifdef _LP64
+static inline bool long_ranges_overlap(jlong lo1, jlong hi1,
+                                       jlong lo2, jlong hi2) {
+  // Two ranges overlap iff one range's low point falls in the other range.
+  return (lo2 <= lo1 && lo1 <= hi2) || (lo1 <= lo2 && lo2 <= hi1);
+}
+#endif
+
+//------------------------------Ideal------------------------------------------
+Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  const TypeLong* this_type = this->type()->is_long();
+  Node* this_changed = NULL;
+
+  // If _major_progress, then more loop optimizations follow.  Do NOT
+  // remove this node's type assertion until no more loop ops can happen.
+  // The progress bit is set in the major loop optimizations THEN comes the
+  // call to IterGVN and any chance of hitting this code.  Cf. Opaque1Node.
+  if (can_reshape && !phase->C->major_progress()) {
+    const TypeInt* in_type = phase->type(in(1))->isa_int();
+    if (in_type != NULL && this_type != NULL &&
+        (in_type->_lo != this_type->_lo ||
+         in_type->_hi != this_type->_hi)) {
+          // Although this WORSENS the type, it increases GVN opportunities,
+          // because I2L nodes with the same input will common up, regardless
+          // of slightly differing type assertions.  Such slight differences
+          // arise routinely as a result of loop unrolling, so this is a
+          // post-unrolling graph cleanup.  Choose a type which depends only
+          // on my input.  (Exception:  Keep a range assertion of >=0 or <0.)
+          jlong lo1 = this_type->_lo;
+          jlong hi1 = this_type->_hi;
+          int   w1  = this_type->_widen;
+          if (lo1 != (jint)lo1 ||
+              hi1 != (jint)hi1 ||
+              lo1 > hi1) {
+            // Overflow leads to wraparound, wraparound leads to range saturation.
+            lo1 = min_jint; hi1 = max_jint;
+          } else if (lo1 >= 0) {
+            // Keep a range assertion of >=0.
+            lo1 = 0;        hi1 = max_jint;
+          } else if (hi1 < 0) {
+            // Keep a range assertion of <0.
+            lo1 = min_jint; hi1 = -1;
+          } else {
+            lo1 = min_jint; hi1 = max_jint;
+          }
+          const TypeLong* wtype = TypeLong::make(MAX2((jlong)in_type->_lo, lo1),
+                                                 MIN2((jlong)in_type->_hi, hi1),
+                                                 MAX2((int)in_type->_widen, w1));
+          if (wtype != type()) {
+            set_type(wtype);
+            // Note: this_type still has old type value, for the logic below.
+            this_changed = this;
+          }
+        }
+  }
+
+#ifdef _LP64
+  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) ,
+  // but only if x and y have subranges that cannot cause 32-bit overflow,
+  // under the assumption that x+y is in my own subrange this->type().
+
+  // This assumption is based on a constraint (i.e., type assertion)
+  // established in Parse::array_addressing or perhaps elsewhere.
+  // This constraint has been adjoined to the "natural" type of
+  // the incoming argument in(0).  We know (because of runtime
+  // checks) - that the result value I2L(x+y) is in the joined range.
+  // Hence we can restrict the incoming terms (x, y) to values such
+  // that their sum also lands in that range.
+
+  // This optimization is useful only on 64-bit systems, where we hope
+  // the addition will end up subsumed in an addressing mode.
+  // It is necessary to do this when optimizing an unrolled array
+  // copy loop such as x[i++] = y[i++].
+
+  // On 32-bit systems, it's better to perform as much 32-bit math as
+  // possible before the I2L conversion, because 32-bit math is cheaper.
+  // There's no common reason to "leak" a constant offset through the I2L.
+  // Addressing arithmetic will not absorb it as part of a 64-bit AddL.
+
+  Node* z = in(1);
+  int op = z->Opcode();
+  if (op == Op_AddI || op == Op_SubI) {
+    Node* x = z->in(1);
+    Node* y = z->in(2);
+    assert (x != z && y != z, "dead loop in ConvI2LNode::Ideal");
+    if (phase->type(x) == Type::TOP)  return this_changed;
+    if (phase->type(y) == Type::TOP)  return this_changed;
+    const TypeInt*  tx = phase->type(x)->is_int();
+    const TypeInt*  ty = phase->type(y)->is_int();
+    const TypeLong* tz = this_type;
+    jlong xlo = tx->_lo;
+    jlong xhi = tx->_hi;
+    jlong ylo = ty->_lo;
+    jlong yhi = ty->_hi;
+    jlong zlo = tz->_lo;
+    jlong zhi = tz->_hi;
+    jlong vbit = CONST64(1) << BitsPerInt;
+    int widen =  MAX2(tx->_widen, ty->_widen);
+    if (op == Op_SubI) {
+      jlong ylo0 = ylo;
+      ylo = -yhi;
+      yhi = -ylo0;
+    }
+    // See if x+y can cause positive overflow into z+2**32
+    if (long_ranges_overlap(xlo+ylo, xhi+yhi, zlo+vbit, zhi+vbit)) {
+      return this_changed;
+    }
+    // See if x+y can cause negative overflow into z-2**32
+    if (long_ranges_overlap(xlo+ylo, xhi+yhi, zlo-vbit, zhi-vbit)) {
+      return this_changed;
+    }
+    // Now it's always safe to assume x+y does not overflow.
+    // This is true even if some pairs x,y might cause overflow, as long
+    // as that overflow value cannot fall into [zlo,zhi].
+
+    // Confident that the arithmetic is "as if infinite precision",
+    // we can now use z's range to put constraints on those of x and y.
+    // The "natural" range of x [xlo,xhi] can perhaps be narrowed to a
+    // more "restricted" range by intersecting [xlo,xhi] with the
+    // range obtained by subtracting y's range from the asserted range
+    // of the I2L conversion.  Here's the interval arithmetic algebra:
+    //    x == z-y == [zlo,zhi]-[ylo,yhi] == [zlo,zhi]+[-yhi,-ylo]
+    //    => x in [zlo-yhi, zhi-ylo]
+    //    => x in [zlo-yhi, zhi-ylo] INTERSECT [xlo,xhi]
+    //    => x in [xlo MAX zlo-yhi, xhi MIN zhi-ylo]
+    jlong rxlo = MAX2(xlo, zlo - yhi);
+    jlong rxhi = MIN2(xhi, zhi - ylo);
+    // And similarly, x changing place with y:
+    jlong rylo = MAX2(ylo, zlo - xhi);
+    jlong ryhi = MIN2(yhi, zhi - xlo);
+    if (rxlo > rxhi || rylo > ryhi) {
+      return this_changed;  // x or y is dying; don't mess w/ it
+    }
+    if (op == Op_SubI) {
+      jlong rylo0 = rylo;
+      rylo = -ryhi;
+      ryhi = -rylo0;
+    }
+
+    Node* cx = phase->transform( new (phase->C) ConvI2LNode(x, TypeLong::make(rxlo, rxhi, widen)) );
+    Node* cy = phase->transform( new (phase->C) ConvI2LNode(y, TypeLong::make(rylo, ryhi, widen)) );
+    switch (op) {
+      case Op_AddI:  return new (phase->C) AddLNode(cx, cy);
+      case Op_SubI:  return new (phase->C) SubLNode(cx, cy);
+      default:       ShouldNotReachHere();
+    }
+  }
+#endif //_LP64
+
+  return this_changed;
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvL2DNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeLong *tl = t->is_long();
+  if( tl->is_con() ) return TypeD::make( (double)tl->get_con() );
+  return bottom_type();
+}
+
+//=============================================================================
+//------------------------------Value------------------------------------------
+const Type *ConvL2FNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeLong *tl = t->is_long();
+  if( tl->is_con() ) return TypeF::make( (float)tl->get_con() );
+  return bottom_type();
+}
+
+//=============================================================================
+//----------------------------Identity-----------------------------------------
+Node *ConvL2INode::Identity( PhaseTransform *phase ) {
+  // Convert L2I(I2L(x)) => x
+  if (in(1)->Opcode() == Op_ConvI2L)  return in(1)->in(1);
+  return this;
+}
+
+//------------------------------Value------------------------------------------
+const Type *ConvL2INode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeLong *tl = t->is_long();
+  if (tl->is_con())
+  // Easy case.
+  return TypeInt::make((jint)tl->get_con());
+  return bottom_type();
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.
+// Blow off prior masking to int
+Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  Node *andl = in(1);
+  uint andl_op = andl->Opcode();
+  if( andl_op == Op_AndL ) {
+    // Blow off prior masking to int
+    if( phase->type(andl->in(2)) == TypeLong::make( 0xFFFFFFFF ) ) {
+      set_req(1,andl->in(1));
+      return this;
+    }
+  }
+
+  // Swap with a prior add: convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y))
+  // This replaces an 'AddL' with an 'AddI'.
+  if( andl_op == Op_AddL ) {
+    // Don't do this for nodes which have more than one user since
+    // we'll end up computing the long add anyway.
+    if (andl->outcnt() > 1) return NULL;
+
+    Node* x = andl->in(1);
+    Node* y = andl->in(2);
+    assert( x != andl && y != andl, "dead loop in ConvL2INode::Ideal" );
+    if (phase->type(x) == Type::TOP)  return NULL;
+    if (phase->type(y) == Type::TOP)  return NULL;
+    Node *add1 = phase->transform(new (phase->C) ConvL2INode(x));
+    Node *add2 = phase->transform(new (phase->C) ConvL2INode(y));
+    return new (phase->C) AddINode(add1,add2);
+  }
+
+  // Disable optimization: LoadL->ConvL2I ==> LoadI.
+  // It causes problems (sizes of Load and Store nodes do not match)
+  // in objects initialization code and Escape Analysis.
+  return NULL;
+}
+
+
+
+//=============================================================================
+//------------------------------Identity---------------------------------------
+// Remove redundant roundings
+Node *RoundFloatNode::Identity( PhaseTransform *phase ) {
+  assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
+  // Do not round constants
+  if (phase->type(in(1))->base() == Type::FloatCon)  return in(1);
+  int op = in(1)->Opcode();
+  // Redundant rounding
+  if( op == Op_RoundFloat ) return in(1);
+  // Already rounded
+  if( op == Op_Parm ) return in(1);
+  if( op == Op_LoadF ) return in(1);
+  return this;
+}
+
+//------------------------------Value------------------------------------------
+const Type *RoundFloatNode::Value( PhaseTransform *phase ) const {
+  return phase->type( in(1) );
+}
+
+//=============================================================================
+//------------------------------Identity---------------------------------------
+// Remove redundant roundings.  Incoming arguments are already rounded.
+Node *RoundDoubleNode::Identity( PhaseTransform *phase ) {
+  assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
+  // Do not round constants
+  if (phase->type(in(1))->base() == Type::DoubleCon)  return in(1);
+  int op = in(1)->Opcode();
+  // Redundant rounding
+  if( op == Op_RoundDouble ) return in(1);
+  // Already rounded
+  if( op == Op_Parm ) return in(1);
+  if( op == Op_LoadD ) return in(1);
+  if( op == Op_ConvF2D ) return in(1);
+  if( op == Op_ConvI2D ) return in(1);
+  return this;
+}
+
+//------------------------------Value------------------------------------------
+const Type *RoundDoubleNode::Value( PhaseTransform *phase ) const {
+  return phase->type( in(1) );
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/convertnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 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_OPTO_CONVERTNODE_HPP
+#define SHARE_VM_OPTO_CONVERTNODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+
+//------------------------------Conv2BNode-------------------------------------
+// Convert int/pointer to a Boolean.  Map zero to zero, all else to 1.
+class Conv2BNode : public Node {
+  public:
+  Conv2BNode( Node *i ) : Node(0,i) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::BOOL; }
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual uint  ideal_reg() const { return Op_RegI; }
+};
+
+// The conversions operations are all Alpha sorted.  Please keep it that way!
+//------------------------------ConvD2FNode------------------------------------
+// Convert double to float
+class ConvD2FNode : public Node {
+  public:
+  ConvD2FNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::FLOAT; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual uint  ideal_reg() const { return Op_RegF; }
+};
+
+//------------------------------ConvD2INode------------------------------------
+// Convert Double to Integer
+class ConvD2INode : public Node {
+  public:
+  ConvD2INode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint  ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------ConvD2LNode------------------------------------
+// Convert Double to Long
+class ConvD2LNode : public Node {
+  public:
+  ConvD2LNode( Node *dbl ) : Node(0,dbl) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeLong::LONG; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint ideal_reg() const { return Op_RegL; }
+};
+
+//------------------------------ConvF2DNode------------------------------------
+// Convert Float to a Double.
+class ConvF2DNode : public Node {
+  public:
+  ConvF2DNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::DOUBLE; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual uint  ideal_reg() const { return Op_RegD; }
+};
+
+//------------------------------ConvF2INode------------------------------------
+// Convert float to integer
+class ConvF2INode : public Node {
+  public:
+  ConvF2INode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint  ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------ConvF2LNode------------------------------------
+// Convert float to long
+class ConvF2LNode : public Node {
+  public:
+  ConvF2LNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeLong::LONG; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint  ideal_reg() const { return Op_RegL; }
+};
+
+//------------------------------ConvI2DNode------------------------------------
+// Convert Integer to Double
+class ConvI2DNode : public Node {
+  public:
+  ConvI2DNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::DOUBLE; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual uint  ideal_reg() const { return Op_RegD; }
+};
+
+//------------------------------ConvI2FNode------------------------------------
+// Convert Integer to Float
+class ConvI2FNode : public Node {
+  public:
+  ConvI2FNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::FLOAT; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual uint  ideal_reg() const { return Op_RegF; }
+};
+
+//------------------------------ConvI2LNode------------------------------------
+// Convert integer to long
+class ConvI2LNode : public TypeNode {
+  public:
+  ConvI2LNode(Node *in1, const TypeLong* t = TypeLong::INT)
+  : TypeNode(t, 2)
+  { init_req(1, in1); }
+  virtual int Opcode() const;
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint  ideal_reg() const { return Op_RegL; }
+};
+
+//------------------------------ConvL2DNode------------------------------------
+// Convert Long to Double
+class ConvL2DNode : public Node {
+  public:
+  ConvL2DNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::DOUBLE; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual uint ideal_reg() const { return Op_RegD; }
+};
+
+//------------------------------ConvL2FNode------------------------------------
+// Convert Long to Float
+class ConvL2FNode : public Node {
+  public:
+  ConvL2FNode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::FLOAT; }
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual uint  ideal_reg() const { return Op_RegF; }
+};
+
+//------------------------------ConvL2INode------------------------------------
+// Convert long to integer
+class ConvL2INode : public Node {
+  public:
+  ConvL2INode( Node *in1 ) : Node(0,in1) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual uint  ideal_reg() const { return Op_RegI; }
+};
+
+//-----------------------------RoundFloatNode----------------------------------
+class RoundFloatNode: public Node {
+  public:
+  RoundFloatNode(Node* c, Node *in1): Node(c, in1) {}
+  virtual int   Opcode() const;
+  virtual const Type *bottom_type() const { return Type::FLOAT; }
+  virtual uint  ideal_reg() const { return Op_RegF; }
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+};
+
+
+//-----------------------------RoundDoubleNode---------------------------------
+class RoundDoubleNode: public Node {
+  public:
+  RoundDoubleNode(Node* c, Node *in1): Node(c, in1) {}
+  virtual int   Opcode() const;
+  virtual const Type *bottom_type() const { return Type::DOUBLE; }
+  virtual uint  ideal_reg() const { return Op_RegD; }
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+};
+
+
+#endif // SHARE_VM_OPTO_CONVERTNODE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/countbitsnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 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 "opto/countbitsnode.hpp"
+#include "opto/opcodes.hpp"
+#include "opto/phaseX.hpp"
+#include "opto/type.hpp"
+
+//------------------------------Value------------------------------------------
+const Type* CountLeadingZerosINode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeInt* ti = t->isa_int();
+  if (ti && ti->is_con()) {
+    jint i = ti->get_con();
+    // HD, Figure 5-6
+    if (i == 0)
+    return TypeInt::make(BitsPerInt);
+    int n = 1;
+    unsigned int x = i;
+    if (x >> 16 == 0) { n += 16; x <<= 16; }
+    if (x >> 24 == 0) { n +=  8; x <<=  8; }
+    if (x >> 28 == 0) { n +=  4; x <<=  4; }
+    if (x >> 30 == 0) { n +=  2; x <<=  2; }
+    n -= x >> 31;
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountLeadingZerosLNode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeLong* tl = t->isa_long();
+  if (tl && tl->is_con()) {
+    jlong l = tl->get_con();
+    // HD, Figure 5-6
+    if (l == 0)
+    return TypeInt::make(BitsPerLong);
+    int n = 1;
+    unsigned int x = (((julong) l) >> 32);
+    if (x == 0) { n += 32; x = (int) l; }
+    if (x >> 16 == 0) { n += 16; x <<= 16; }
+    if (x >> 24 == 0) { n +=  8; x <<=  8; }
+    if (x >> 28 == 0) { n +=  4; x <<=  4; }
+    if (x >> 30 == 0) { n +=  2; x <<=  2; }
+    n -= x >> 31;
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountTrailingZerosINode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeInt* ti = t->isa_int();
+  if (ti && ti->is_con()) {
+    jint i = ti->get_con();
+    // HD, Figure 5-14
+    int y;
+    if (i == 0)
+    return TypeInt::make(BitsPerInt);
+    int n = 31;
+    y = i << 16; if (y != 0) { n = n - 16; i = y; }
+    y = i <<  8; if (y != 0) { n = n -  8; i = y; }
+    y = i <<  4; if (y != 0) { n = n -  4; i = y; }
+    y = i <<  2; if (y != 0) { n = n -  2; i = y; }
+    y = i <<  1; if (y != 0) { n = n -  1; }
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountTrailingZerosLNode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeLong* tl = t->isa_long();
+  if (tl && tl->is_con()) {
+    jlong l = tl->get_con();
+    // HD, Figure 5-14
+    int x, y;
+    if (l == 0)
+    return TypeInt::make(BitsPerLong);
+    int n = 63;
+    y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32);
+    y = x << 16; if (y != 0) { n = n - 16; x = y; }
+    y = x <<  8; if (y != 0) { n = n -  8; x = y; }
+    y = x <<  4; if (y != 0) { n = n -  4; x = y; }
+    y = x <<  2; if (y != 0) { n = n -  2; x = y; }
+    y = x <<  1; if (y != 0) { n = n -  1; }
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/countbitsnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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_OPTO_COUNTBITSNODE_HPP
+#define SHARE_VM_OPTO_COUNTBITSNODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+class PhaseTransform;
+
+//---------- CountBitsNode -----------------------------------------------------
+class CountBitsNode : public Node {
+  public:
+  CountBitsNode(Node* in1) : Node(0, in1) {}
+  const Type* bottom_type() const { return TypeInt::INT; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//---------- CountLeadingZerosINode --------------------------------------------
+// Count leading zeros (0-bit count starting from MSB) of an integer.
+class CountLeadingZerosINode : public CountBitsNode {
+  public:
+  CountLeadingZerosINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountLeadingZerosLNode --------------------------------------------
+// Count leading zeros (0-bit count starting from MSB) of a long.
+class CountLeadingZerosLNode : public CountBitsNode {
+  public:
+  CountLeadingZerosLNode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountTrailingZerosINode -------------------------------------------
+// Count trailing zeros (0-bit count starting from LSB) of an integer.
+class CountTrailingZerosINode : public CountBitsNode {
+  public:
+  CountTrailingZerosINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountTrailingZerosLNode -------------------------------------------
+// Count trailing zeros (0-bit count starting from LSB) of a long.
+class CountTrailingZerosLNode : public CountBitsNode {
+  public:
+  CountTrailingZerosLNode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- PopCountINode -----------------------------------------------------
+// Population count (bit count) of an integer.
+class PopCountINode : public CountBitsNode {
+  public:
+  PopCountINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+};
+
+//---------- PopCountLNode -----------------------------------------------------
+// Population count (bit count) of a long.
+class PopCountLNode : public CountBitsNode {
+  public:
+  PopCountLNode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+};
+
+
+#endif // SHARE_VM_OPTO_COUNTBITSNODE_HPP
--- a/hotspot/src/share/vm/opto/divnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/divnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -26,8 +26,10 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/machnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/phaseX.hpp"
--- a/hotspot/src/share/vm/opto/doCall.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -31,6 +31,7 @@
 #include "interpreter/linkResolver.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callGenerator.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/parse.hpp"
@@ -249,8 +250,7 @@
           }
           CallGenerator* miss_cg;
           Deoptimization::DeoptReason reason = morphism == 2 ?
-                                    Deoptimization::Reason_bimorphic :
-                                    (speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check);
+            Deoptimization::Reason_bimorphic : Deoptimization::reason_class_check(speculative_receiver_type != NULL);
           if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
               !too_many_traps(jvms->method(), jvms->bci(), reason)
              ) {
@@ -631,13 +631,7 @@
     }
     BasicType ct = ctype->basic_type();
     if (ct == T_OBJECT || ct == T_ARRAY) {
-      ciKlass* better_type = method()->return_profiled_type(bci());
-      if (UseTypeSpeculation && better_type != NULL) {
-        // If profiling reports a single type for the return value,
-        // feed it to the type system so it can propagate it as a
-        // speculative type
-        record_profile_for_speculation(stack(sp()-1), better_type);
-      }
+      record_profiled_return_for_speculation();
     }
   }
 
--- a/hotspot/src/share/vm/opto/escape.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -33,6 +33,7 @@
 #include "opto/compile.hpp"
 #include "opto/escape.hpp"
 #include "opto/phaseX.hpp"
+#include "opto/movenode.hpp"
 #include "opto/rootnode.hpp"
 
 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
--- a/hotspot/src/share/vm/opto/generateOptoStub.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,7 +27,7 @@
 #include "opto/callnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/compile.hpp"
-#include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/locknode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mulnode.hpp"
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,10 +30,14 @@
 #include "memory/barrierSet.hpp"
 #include "memory/cardTableModRefBS.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/graphKit.hpp"
 #include "opto/idealKit.hpp"
+#include "opto/intrinsicnode.hpp"
 #include "opto/locknode.hpp"
 #include "opto/machnode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
@@ -612,10 +616,10 @@
   // Usual case:  Bail to interpreter.
   // Reserve the right to recompile if we haven't seen anything yet.
 
-  assert(!Deoptimization::reason_is_speculate(reason), "unsupported");
+  ciMethod* m = Deoptimization::reason_is_speculate(reason) ? C->method() : NULL;
   Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile;
   if (treat_throw_as_hot
-      && (method()->method_data()->trap_recompiled_at(bci(), NULL)
+      && (method()->method_data()->trap_recompiled_at(bci(), m)
           || C->too_many_traps(reason))) {
     // We cannot afford to take more traps here.  Suffer in the interpreter.
     if (C->log() != NULL)
@@ -1125,6 +1129,17 @@
   }
   return _gvn.transform( new (C) ConvI2LNode(offset));
 }
+
+Node* GraphKit::ConvI2UL(Node* offset) {
+  juint offset_con = (juint) find_int_con(offset, Type::OffsetBot);
+  if (offset_con != (juint) Type::OffsetBot) {
+    return longcon((julong) offset_con);
+  }
+  Node* conv = _gvn.transform( new (C) ConvI2LNode(offset));
+  Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) );
+  return _gvn.transform( new (C) AndLNode(conv, mask) );
+}
+
 Node* GraphKit::ConvL2I(Node* offset) {
   // short-circuit a common case
   jlong offset_con = find_long_con(offset, (jlong)Type::OffsetBot);
@@ -1170,7 +1185,8 @@
 Node* GraphKit::null_check_common(Node* value, BasicType type,
                                   // optional arguments for variations:
                                   bool assert_null,
-                                  Node* *null_control) {
+                                  Node* *null_control,
+                                  bool speculative) {
   assert(!assert_null || null_control == NULL, "not both at once");
   if (stopped())  return top();
   if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) {
@@ -1280,13 +1296,13 @@
   // Branch to failure if null
   float ok_prob = PROB_MAX;  // a priori estimate:  nulls never happen
   Deoptimization::DeoptReason reason;
-  if (assert_null)
+  if (assert_null) {
     reason = Deoptimization::Reason_null_assert;
-  else if (type == T_OBJECT)
-    reason = Deoptimization::Reason_null_check;
-  else
+  } else if (type == T_OBJECT) {
+    reason = Deoptimization::reason_null_check(speculative);
+  } else {
     reason = Deoptimization::Reason_div0_check;
-
+  }
   // %%% Since Reason_unhandled is not recorded on a per-bytecode basis,
   // ciMethodData::has_trap_at will return a conservative -1 if any
   // must-be-null assertion has failed.  This could cause performance
@@ -2109,21 +2125,36 @@
  *
  * @param n          node that the type applies to
  * @param exact_kls  type from profiling
+ * @param maybe_null did profiling see null?
  *
  * @return           node with improved type
  */
-Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) {
+Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null) {
   const Type* current_type = _gvn.type(n);
   assert(UseTypeSpeculation, "type speculation must be on");
 
-  const TypeOopPtr* speculative = current_type->speculative();
-
+  const TypePtr* speculative = current_type->speculative();
+
+  // Should the klass from the profile be recorded in the speculative type?
   if (current_type->would_improve_type(exact_kls, jvms()->depth())) {
     const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
     const TypeOopPtr* xtype = tklass->as_instance_type();
     assert(xtype->klass_is_exact(), "Should be exact");
+    // Any reason to believe n is not null (from this profiling or a previous one)?
+    const TypePtr* ptr = (maybe_null && current_type->speculative_maybe_null()) ? TypePtr::BOTTOM : TypePtr::NOTNULL;
     // record the new speculative type's depth
-    speculative = xtype->with_inline_depth(jvms()->depth());
+    speculative = xtype->cast_to_ptr_type(ptr->ptr())->is_ptr();
+    speculative = speculative->with_inline_depth(jvms()->depth());
+  } else if (current_type->would_improve_ptr(maybe_null)) {
+    // Profiling report that null was never seen so we can change the
+    // speculative type to non null ptr.
+    assert(!maybe_null, "nothing to improve");
+    if (speculative == NULL) {
+      speculative = TypePtr::NOTNULL;
+    } else {
+      const TypePtr* ptr = TypePtr::NOTNULL;
+      speculative = speculative->cast_to_ptr_type(ptr->ptr())->is_ptr();
+    }
   }
 
   if (speculative != current_type->speculative()) {
@@ -2156,7 +2187,15 @@
     return n;
   }
   ciKlass* exact_kls = profile_has_unique_klass();
-  return record_profile_for_speculation(n, exact_kls);
+  bool maybe_null = true;
+  if (java_bc() == Bytecodes::_checkcast ||
+      java_bc() == Bytecodes::_instanceof ||
+      java_bc() == Bytecodes::_aastore) {
+    ciProfileData* data = method()->method_data()->bci_to_data(bci());
+    bool maybe_null = data == NULL ? true : data->as_BitData()->null_seen();
+  }
+  return record_profile_for_speculation(n, exact_kls, maybe_null);
+  return n;
 }
 
 /**
@@ -2176,9 +2215,10 @@
   for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) {
     const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms);
     if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) {
-      ciKlass* better_type = method()->argument_profiled_type(bci(), i);
-      if (better_type != NULL) {
-        record_profile_for_speculation(argument(j), better_type);
+      bool maybe_null = true;
+      ciKlass* better_type = NULL;
+      if (method()->argument_profiled_type(bci(), i, better_type, maybe_null)) {
+        record_profile_for_speculation(argument(j), better_type, maybe_null);
       }
       i++;
     }
@@ -2195,15 +2235,34 @@
   }
   for (int i = 0, j = 0; i < method()->arg_size() ; i++) {
     if (_gvn.type(local(i))->isa_oopptr()) {
-      ciKlass* better_type = method()->parameter_profiled_type(j);
-      if (better_type != NULL) {
-        record_profile_for_speculation(local(i), better_type);
+      bool maybe_null = true;
+      ciKlass* better_type = NULL;
+      if (method()->parameter_profiled_type(j, better_type, maybe_null)) {
+        record_profile_for_speculation(local(i), better_type, maybe_null);
       }
       j++;
     }
   }
 }
 
+/**
+ * Record profiling data from return value profiling at an invoke with
+ * the type system so that it can propagate it (speculation)
+ */
+void GraphKit::record_profiled_return_for_speculation() {
+  if (!UseTypeSpeculation) {
+    return;
+  }
+  bool maybe_null = true;
+  ciKlass* better_type = NULL;
+  if (method()->return_profiled_type(bci(), better_type, maybe_null)) {
+    // If profiling reports a single type for the return value,
+    // feed it to the type system so it can propagate it as a
+    // speculative type
+    record_profile_for_speculation(stack(sp()-1), better_type, maybe_null);
+  }
+}
+
 void GraphKit::round_double_result(ciMethod* dest_method) {
   // A non-strict method may return a double value which has an extended
   // exponent, but this must not be visible in a caller which is 'strict'
@@ -2283,10 +2342,12 @@
 // Null check oop.  Set null-path control into Region in slot 3.
 // Make a cast-not-nullness use the other not-null control.  Return cast.
 Node* GraphKit::null_check_oop(Node* value, Node* *null_control,
-                               bool never_see_null, bool safe_for_replace) {
+                               bool never_see_null,
+                               bool safe_for_replace,
+                               bool speculative) {
   // Initial NULL check taken path
   (*null_control) = top();
-  Node* cast = null_check_common(value, T_OBJECT, false, null_control);
+  Node* cast = null_check_common(value, T_OBJECT, false, null_control, speculative);
 
   // Generate uncommon_trap:
   if (never_see_null && (*null_control) != top()) {
@@ -2297,7 +2358,8 @@
     PreserveJVMState pjvms(this);
     set_control(*null_control);
     replace_in_map(value, null());
-    uncommon_trap(Deoptimization::Reason_null_check,
+    Deoptimization::DeoptReason reason = Deoptimization::reason_null_check(speculative);
+    uncommon_trap(reason,
                   Deoptimization::Action_make_not_entrant);
     (*null_control) = top();    // NULL path is dead
   }
@@ -2721,11 +2783,16 @@
 // recompile; the offending check will be recompiled to handle NULLs.
 // If we see several offending BCIs, then all checks in the
 // method will be recompiled.
-bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) {
+bool GraphKit::seems_never_null(Node* obj, ciProfileData* data, bool& speculating) {
+  speculating = !_gvn.type(obj)->speculative_maybe_null();
+  Deoptimization::DeoptReason reason = Deoptimization::reason_null_check(speculating);
   if (UncommonNullCast               // Cutout for this technique
       && obj != null()               // And not the -Xcomp stupid case?
-      && !too_many_traps(Deoptimization::Reason_null_check)
+      && !too_many_traps(reason)
       ) {
+    if (speculating) {
+      return true;
+    }
     if (data == NULL)
       // Edge case:  no mature data.  Be optimistic here.
       return true;
@@ -2735,6 +2802,7 @@
            java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here");
     return !data->as_BitData()->null_seen();
   }
+  speculating = false;
   return false;
 }
 
@@ -2747,7 +2815,7 @@
                                              bool safe_for_replace) {
   if (!UseTypeProfile || !TypeProfileCasts) return NULL;
 
-  Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check;
+  Deoptimization::DeoptReason reason = Deoptimization::reason_class_check(spec_klass != NULL);
 
   // Make sure we haven't already deoptimized from this tactic.
   if (too_many_traps(reason))
@@ -2800,7 +2868,7 @@
   // type == NULL if profiling tells us this object is always null
   if (type != NULL) {
     Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check;
-    Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check;
+    Deoptimization::DeoptReason null_reason = Deoptimization::Reason_speculate_null_check;
     if (!too_many_traps(null_reason) &&
         !too_many_traps(class_reason)) {
       Node* not_null_obj = NULL;
@@ -2808,7 +2876,7 @@
       // there's no need for a null check
       if (!not_null) {
         Node* null_ctl = top();
-        not_null_obj = null_check_oop(obj, &null_ctl, true, true);
+        not_null_obj = null_check_oop(obj, &null_ctl, true, true, true);
         assert(null_ctl->is_top(), "no null control here");
       } else {
         not_null_obj = obj;
@@ -2856,12 +2924,13 @@
   if (java_bc() == Bytecodes::_instanceof) {  // Only for the bytecode
     data = method()->method_data()->bci_to_data(bci());
   }
+  bool speculative_not_null = false;
   bool never_see_null = (ProfileDynamicTypes  // aggressive use of profile
-                         && seems_never_null(obj, data));
+                         && seems_never_null(obj, data, speculative_not_null));
 
   // Null check; get casted pointer; set region slot 3
   Node* null_ctl = top();
-  Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace);
+  Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null);
 
   // If not_null_obj is dead, only null-path is taken
   if (stopped()) {              // Doing instance-of on a NULL?
@@ -2984,12 +3053,13 @@
   C->set_has_split_ifs(true); // Has chance for split-if optimization
 
   // Use null-cast information if it is available
+  bool speculative_not_null = false;
   bool never_see_null = ((failure_control == NULL)  // regular case only
-                         && seems_never_null(obj, data));
+                         && seems_never_null(obj, data, speculative_not_null));
 
   // Null check; get casted pointer; set region slot 3
   Node* null_ctl = top();
-  Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace);
+  Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null);
 
   // If not_null_obj is dead, only null-path is taken
   if (stopped()) {              // Doing instance-of on a NULL?
@@ -3151,10 +3221,14 @@
   Node* mem = reset_memory();
 
   FastLockNode * flock = _gvn.transform(new (C) FastLockNode(0, obj, box) )->as_FastLock();
-  if (PrintPreciseBiasedLockingStatistics) {
+  if (UseBiasedLocking && PrintPreciseBiasedLockingStatistics) {
     // Create the counters for this fast lock.
     flock->create_lock_counter(sync_jvms()); // sync_jvms used to get current bci
   }
+
+  // Create the rtm counters for this fast lock if needed.
+  flock->create_rtm_lock_counter(sync_jvms()); // sync_jvms used to get current bci
+
   // Add monitor to debug info for the slow path.  If we block inside the
   // slow path and de-opt, we need the monitor hanging around
   map()->push_monitor( flock );
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -338,6 +338,7 @@
   // Convert between int and long, and size_t.
   // (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.)
   Node* ConvI2L(Node* offset);
+  Node* ConvI2UL(Node* offset);
   Node* ConvL2I(Node* offset);
   // Find out the klass of an object.
   Node* load_object_klass(Node* object);
@@ -350,9 +351,11 @@
   // Return the value cast to not-null.
   // Be clever about equivalent dominating null checks.
   Node* null_check_common(Node* value, BasicType type,
-                          bool assert_null = false, Node* *null_control = NULL);
+                          bool assert_null = false,
+                          Node* *null_control = NULL,
+                          bool speculative = false);
   Node* null_check(Node* value, BasicType type = T_OBJECT) {
-    return null_check_common(value, type);
+    return null_check_common(value, type, false, NULL, !_gvn.type(value)->speculative_maybe_null());
   }
   Node* null_check_receiver() {
     assert(argument(0)->bottom_type()->isa_ptr(), "must be");
@@ -381,10 +384,12 @@
   // If safe_for_replace, then we can replace the value with the cast
   // in the parsing map (the cast is guaranteed to dominate the map)
   Node* null_check_oop(Node* value, Node* *null_control,
-                       bool never_see_null = false, bool safe_for_replace = false);
+                       bool never_see_null = false,
+                       bool safe_for_replace = false,
+                       bool speculative = false);
 
   // Check the null_seen bit.
-  bool seems_never_null(Node* obj, ciProfileData* data);
+  bool seems_never_null(Node* obj, ciProfileData* data, bool& speculating);
 
   // Check for unique class for receiver at call
   ciKlass* profile_has_unique_klass() {
@@ -398,10 +403,11 @@
   }
 
   // record type from profiling with the type system
-  Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls);
-  Node* record_profiled_receiver_for_speculation(Node* n);
+  Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null);
   void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc);
   void record_profiled_parameters_for_speculation();
+  void record_profiled_return_for_speculation();
+  Node* record_profiled_receiver_for_speculation(Node* n);
 
   // Use the type profile to narrow an object type.
   Node* maybe_cast_profiled_receiver(Node* not_null_obj,
--- a/hotspot/src/share/vm/opto/idealKit.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/idealKit.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,6 +27,7 @@
 
 #include "opto/addnode.hpp"
 #include "opto/cfgnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/connode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/graphKit.hpp"
--- a/hotspot/src/share/vm/opto/ifg.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/ifg.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -31,7 +31,6 @@
 #include "opto/cfgnode.hpp"
 #include "opto/chaitin.hpp"
 #include "opto/coalesce.hpp"
-#include "opto/connode.hpp"
 #include "opto/indexSet.hpp"
 #include "opto/machnode.hpp"
 #include "opto/memnode.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/intrinsicnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 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 "opto/intrinsicnode.hpp"
+#include "opto/memnode.hpp"
+#include "opto/phaseX.hpp"
+
+//=============================================================================
+// Do not match memory edge.
+uint StrIntrinsicNode::match_edge(uint idx) const {
+  return idx == 2 || idx == 3;
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if (remove_dead_region(phase, can_reshape)) return this;
+  // Don't bother trying to transform a dead node
+  if (in(0) && in(0)->is_top())  return NULL;
+
+  if (can_reshape) {
+    Node* mem = phase->transform(in(MemNode::Memory));
+    // If transformed to a MergeMem, get the desired slice
+    uint alias_idx = phase->C->get_alias_index(adr_type());
+    mem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(alias_idx) : mem;
+    if (mem != in(MemNode::Memory)) {
+      set_req(MemNode::Memory, mem);
+      return this;
+    }
+  }
+  return NULL;
+}
+
+//------------------------------Value------------------------------------------
+const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const {
+  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
+  return bottom_type();
+}
+
+//=============================================================================
+//------------------------------match_edge-------------------------------------
+// Do not match memory edge
+uint EncodeISOArrayNode::match_edge(uint idx) const {
+  return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len)
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
+//------------------------------Value------------------------------------------
+const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const {
+  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
+  return bottom_type();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/intrinsicnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 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_OPTO_INTRINSICNODE_HPP
+#define SHARE_VM_OPTO_INTRINSICNODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+
+//----------------------PartialSubtypeCheckNode--------------------------------
+// The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
+// array for an instance of the superklass.  Set a hidden internal cache on a
+// hit (cache is checked with exposed code in gen_subtype_check()).  Return
+// not zero for a miss or zero for a hit.
+class PartialSubtypeCheckNode : public Node {
+  public:
+  PartialSubtypeCheckNode(Node* c, Node* sub, Node* super) : Node(c,sub,super) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
+  virtual uint ideal_reg() const { return Op_RegP; }
+};
+
+//------------------------------StrIntrinsic-------------------------------
+// Base class for Ideal nodes used in String instrinsic code.
+class StrIntrinsicNode: public Node {
+  public:
+  StrIntrinsicNode(Node* control, Node* char_array_mem,
+                   Node* s1, Node* c1, Node* s2, Node* c2):
+  Node(control, char_array_mem, s1, c1, s2, c2) {
+  }
+
+  StrIntrinsicNode(Node* control, Node* char_array_mem,
+                   Node* s1, Node* s2, Node* c):
+  Node(control, char_array_mem, s1, s2, c) {
+  }
+
+  StrIntrinsicNode(Node* control, Node* char_array_mem,
+                   Node* s1, Node* s2):
+  Node(control, char_array_mem, s1, s2) {
+  }
+
+  virtual bool depends_only_on_test() const { return false; }
+  virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
+  virtual uint match_edge(uint idx) const;
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual const Type *Value(PhaseTransform *phase) const;
+};
+
+//------------------------------StrComp-------------------------------------
+class StrCompNode: public StrIntrinsicNode {
+  public:
+  StrCompNode(Node* control, Node* char_array_mem,
+              Node* s1, Node* c1, Node* s2, Node* c2):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+};
+
+//------------------------------StrEquals-------------------------------------
+class StrEqualsNode: public StrIntrinsicNode {
+  public:
+  StrEqualsNode(Node* control, Node* char_array_mem,
+                Node* s1, Node* s2, Node* c):
+  StrIntrinsicNode(control, char_array_mem, s1, s2, c) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
+};
+
+//------------------------------StrIndexOf-------------------------------------
+class StrIndexOfNode: public StrIntrinsicNode {
+  public:
+  StrIndexOfNode(Node* control, Node* char_array_mem,
+                 Node* s1, Node* c1, Node* s2, Node* c2):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+};
+
+//------------------------------AryEq---------------------------------------
+class AryEqNode: public StrIntrinsicNode {
+  public:
+  AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2):
+  StrIntrinsicNode(control, char_array_mem, s1, s2) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
+};
+
+
+//------------------------------EncodeISOArray--------------------------------
+// encode char[] to byte[] in ISO_8859_1
+class EncodeISOArrayNode: public Node {
+  public:
+  EncodeISOArrayNode(Node *control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {};
+  virtual int Opcode() const;
+  virtual bool depends_only_on_test() const { return false; }
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
+  virtual uint match_edge(uint idx) const;
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual const Type *Value(PhaseTransform *phase) const;
+};
+
+#endif // SHARE_VM_OPTO_INTRINSICNODE_HPP
--- a/hotspot/src/share/vm/opto/library_call.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,10 +30,16 @@
 #include "oops/objArrayKlass.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callGenerator.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
+#include "opto/convertnode.hpp"
+#include "opto/countbitsnode.hpp"
+#include "opto/intrinsicnode.hpp"
 #include "opto/idealKit.hpp"
 #include "opto/mathexactnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/parse.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
@@ -2600,7 +2606,7 @@
     case T_ADDRESS:
       // Cast to an int type.
       p = _gvn.transform(new (C) CastP2XNode(NULL, p));
-      p = ConvX2L(p);
+      p = ConvX2UL(p);
       break;
     default:
       fatal(err_msg_res("unexpected type %d: %s", type, type2name(type)));
@@ -4658,7 +4664,7 @@
 
     ciKlass* src_k = NULL;
     if (!has_src) {
-      src_k = src_type->speculative_type();
+      src_k = src_type->speculative_type_not_null();
       if (src_k != NULL && src_k->is_array_klass()) {
         could_have_src = true;
       }
@@ -4666,7 +4672,7 @@
 
     ciKlass* dest_k = NULL;
     if (!has_dest) {
-      dest_k = dest_type->speculative_type();
+      dest_k = dest_type->speculative_type_not_null();
       if (dest_k != NULL && dest_k->is_array_klass()) {
         could_have_dest = true;
       }
@@ -4738,13 +4744,13 @@
     ciKlass* src_k = top_src->klass();
     ciKlass* dest_k = top_dest->klass();
     if (!src_spec) {
-      src_k = src_type->speculative_type();
+      src_k = src_type->speculative_type_not_null();
       if (src_k != NULL && src_k->is_array_klass()) {
           could_have_src = true;
       }
     }
     if (!dest_spec) {
-      dest_k = dest_type->speculative_type();
+      dest_k = dest_type->speculative_type_not_null();
       if (dest_k != NULL && dest_k->is_array_klass()) {
         could_have_dest = true;
       }
--- a/hotspot/src/share/vm/opto/locknode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/locknode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -136,6 +136,8 @@
 //-----------------------------hash--------------------------------------------
 uint FastLockNode::hash() const { return NO_HASH; }
 
+uint FastLockNode::size_of() const { return sizeof(*this); }
+
 //------------------------------cmp--------------------------------------------
 uint FastLockNode::cmp( const Node &n ) const {
   return (&n == this);                // Always fail except on self
@@ -159,6 +161,22 @@
   _counters = blnc->counters();
 }
 
+void FastLockNode::create_rtm_lock_counter(JVMState* state) {
+#if INCLUDE_RTM_OPT
+  Compile* C = Compile::current();
+  if (C->profile_rtm() || (PrintPreciseRTMLockingStatistics && C->use_rtm())) {
+    RTMLockingNamedCounter* rlnc = (RTMLockingNamedCounter*)
+           OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter);
+    _rtm_counters = rlnc->counters();
+    if (UseRTMForStackLocks) {
+      rlnc = (RTMLockingNamedCounter*)
+           OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter);
+      _stack_rtm_counters = rlnc->counters();
+    }
+  }
+#endif
+}
+
 //=============================================================================
 //------------------------------do_monitor_enter-------------------------------
 void Parse::do_monitor_enter() {
--- a/hotspot/src/share/vm/opto/locknode.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/locknode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -92,13 +92,17 @@
 //------------------------------FastLockNode-----------------------------------
 class FastLockNode: public CmpNode {
 private:
-  BiasedLockingCounters* _counters;
+  BiasedLockingCounters*        _counters;
+  RTMLockingCounters*       _rtm_counters; // RTM lock counters for inflated locks
+  RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks
 
 public:
   FastLockNode(Node *ctrl, Node *oop, Node *box) : CmpNode(oop,box) {
     init_req(0,ctrl);
     init_class_id(Class_FastLock);
     _counters = NULL;
+    _rtm_counters = NULL;
+    _stack_rtm_counters = NULL;
   }
   Node* obj_node() const { return in(1); }
   Node* box_node() const { return in(2); }
@@ -107,13 +111,17 @@
   // FastLock and FastUnlockNode do not hash, we need one for each correspoding
   // LockNode/UnLockNode to avoid creating Phi's.
   virtual uint hash() const ;                  // { return NO_HASH; }
+  virtual uint size_of() const;
   virtual uint cmp( const Node &n ) const ;    // Always fail, except on self
   virtual int Opcode() const;
   virtual const Type *Value( PhaseTransform *phase ) const { return TypeInt::CC; }
   const Type *sub(const Type *t1, const Type *t2) const { return TypeInt::CC;}
 
   void create_lock_counter(JVMState* s);
-  BiasedLockingCounters* counters() const { return _counters; }
+  void create_rtm_lock_counter(JVMState* state);
+  BiasedLockingCounters*        counters() const { return _counters; }
+  RTMLockingCounters*       rtm_counters() const { return _rtm_counters; }
+  RTMLockingCounters* stack_rtm_counters() const { return _stack_rtm_counters; }
 };
 
 
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,8 +27,10 @@
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/subnode.hpp"
 
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -28,9 +28,12 @@
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/movenode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
@@ -617,6 +620,15 @@
       case Op_AryEq: {
         return false;
       }
+#if INCLUDE_RTM_OPT
+      case Op_FastLock:
+      case Op_FastUnlock: {
+        // Don't unroll RTM locking code because it is large.
+        if (UseRTMLocking) {
+          return false;
+        }
+      }
+#endif
     } // switch
   }
 
@@ -722,6 +734,15 @@
         // String intrinsics are large and have loops.
         return false;
       }
+#if INCLUDE_RTM_OPT
+      case Op_FastLock:
+      case Op_FastUnlock: {
+        // Don't unroll RTM locking code because it is large.
+        if (UseRTMLocking) {
+          return false;
+        }
+      }
+#endif
     } // switch
   }
 
--- a/hotspot/src/share/vm/opto/loopUnswitch.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,7 +25,9 @@
 #include "precompiled.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/loopnode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
 
 //================= Loop Unswitching =====================
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,6 +30,7 @@
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #include "opto/loopnode.hpp"
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,6 +30,8 @@
 #include "opto/loopnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/movenode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/subnode.hpp"
 
--- a/hotspot/src/share/vm/opto/machnode.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/machnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -53,6 +53,7 @@
 class Matcher;
 class PhaseRegAlloc;
 class RegMask;
+class RTMLockingCounters;
 class State;
 
 //---------------------------MachOper------------------------------------------
@@ -714,8 +715,9 @@
 class MachFastLockNode : public MachNode {
   virtual uint size_of() const { return sizeof(*this); } // Size is bigger
 public:
-  BiasedLockingCounters* _counters;
-
+  BiasedLockingCounters*        _counters;
+  RTMLockingCounters*       _rtm_counters; // RTM lock counters for inflated locks
+  RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks
   MachFastLockNode() : MachNode() {}
 };
 
--- a/hotspot/src/share/vm/opto/macro.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,14 +27,17 @@
 #include "libadt/vectset.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/compile.hpp"
-#include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/locknode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/macro.hpp"
 #include "opto/memnode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/node.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
@@ -2439,6 +2442,7 @@
     }
   }
   // Next, attempt to eliminate allocations
+  _has_locks = false;
   progress = true;
   while (progress) {
     progress = false;
@@ -2457,11 +2461,13 @@
       case Node::Class_Lock:
       case Node::Class_Unlock:
         assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
+        _has_locks = true;
         break;
       default:
         assert(n->Opcode() == Op_LoopLimit ||
                n->Opcode() == Op_Opaque1   ||
-               n->Opcode() == Op_Opaque2, "unknown node type in macro list");
+               n->Opcode() == Op_Opaque2   ||
+               n->Opcode() == Op_Opaque3, "unknown node type in macro list");
       }
       assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
       progress = progress || success;
@@ -2502,6 +2508,30 @@
       } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
         _igvn.replace_node(n, n->in(1));
         success = true;
+#if INCLUDE_RTM_OPT
+      } else if ((n->Opcode() == Op_Opaque3) && ((Opaque3Node*)n)->rtm_opt()) {
+        assert(C->profile_rtm(), "should be used only in rtm deoptimization code");
+        assert((n->outcnt() == 1) && n->unique_out()->is_Cmp(), "");
+        Node* cmp = n->unique_out();
+#ifdef ASSERT
+        // Validate graph.
+        assert((cmp->outcnt() == 1) && cmp->unique_out()->is_Bool(), "");
+        BoolNode* bol = cmp->unique_out()->as_Bool();
+        assert((bol->outcnt() == 1) && bol->unique_out()->is_If() &&
+               (bol->_test._test == BoolTest::ne), "");
+        IfNode* ifn = bol->unique_out()->as_If();
+        assert((ifn->outcnt() == 2) &&
+               ifn->proj_out(1)->is_uncommon_trap_proj(Deoptimization::Reason_rtm_state_change), "");
+#endif
+        Node* repl = n->in(1);
+        if (!_has_locks) {
+          // Remove RTM state check if there are no locks in the code.
+          // Replace input to compare the same value.
+          repl = (cmp->in(1) == n) ? cmp->in(2) : cmp->in(1);
+        }
+        _igvn.replace_node(n, repl);
+        success = true;
+#endif
       }
       assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
       progress = progress || success;
--- a/hotspot/src/share/vm/opto/macro.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/macro.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -76,6 +76,8 @@
   ProjNode *_memproj_catchall;
   ProjNode *_resproj;
 
+  // Additional data collected during macro expansion
+  bool _has_locks;
 
   void expand_allocate(AllocateNode *alloc);
   void expand_allocate_array(AllocateArrayNode *alloc);
@@ -118,7 +120,7 @@
                             Node* length);
 
 public:
-  PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) {
+  PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
     _igvn.set_delay_transform(true);
   }
   void eliminate_macro_nodes();
--- a/hotspot/src/share/vm/opto/matcher.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -26,10 +26,10 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #include "opto/matcher.hpp"
 #include "opto/memnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/regmask.hpp"
 #include "opto/rootnode.hpp"
--- a/hotspot/src/share/vm/opto/memnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -31,11 +31,13 @@
 #include "opto/cfgnode.hpp"
 #include "opto/compile.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/narrowptrnode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/regmask.hpp"
 
@@ -2904,59 +2906,6 @@
 }
 
 //=============================================================================
-// Do not match memory edge.
-uint StrIntrinsicNode::match_edge(uint idx) const {
-  return idx == 2 || idx == 3;
-}
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.  Strip out
-// control copies
-Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  if (remove_dead_region(phase, can_reshape)) return this;
-  // Don't bother trying to transform a dead node
-  if (in(0) && in(0)->is_top())  return NULL;
-
-  if (can_reshape) {
-    Node* mem = phase->transform(in(MemNode::Memory));
-    // If transformed to a MergeMem, get the desired slice
-    uint alias_idx = phase->C->get_alias_index(adr_type());
-    mem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(alias_idx) : mem;
-    if (mem != in(MemNode::Memory)) {
-      set_req(MemNode::Memory, mem);
-      return this;
-    }
-  }
-  return NULL;
-}
-
-//------------------------------Value------------------------------------------
-const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const {
-  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
-  return bottom_type();
-}
-
-//=============================================================================
-//------------------------------match_edge-------------------------------------
-// Do not match memory edge
-uint EncodeISOArrayNode::match_edge(uint idx) const {
-  return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len)
-}
-
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.  Strip out
-// control copies
-Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  return remove_dead_region(phase, can_reshape) ? this : NULL;
-}
-
-//------------------------------Value------------------------------------------
-const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const {
-  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
-  return bottom_type();
-}
-
-//=============================================================================
 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent)
   : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)),
     _adr_type(C->get_adr_type(alias_idx))
--- a/hotspot/src/share/vm/opto/memnode.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -866,88 +866,6 @@
   static bool step_through(Node** np, uint instance_id, PhaseTransform* phase);
 };
 
-//------------------------------StrIntrinsic-------------------------------
-// Base class for Ideal nodes used in String instrinsic code.
-class StrIntrinsicNode: public Node {
-public:
-  StrIntrinsicNode(Node* control, Node* char_array_mem,
-                   Node* s1, Node* c1, Node* s2, Node* c2):
-    Node(control, char_array_mem, s1, c1, s2, c2) {
-  }
-
-  StrIntrinsicNode(Node* control, Node* char_array_mem,
-                   Node* s1, Node* s2, Node* c):
-    Node(control, char_array_mem, s1, s2, c) {
-  }
-
-  StrIntrinsicNode(Node* control, Node* char_array_mem,
-                   Node* s1, Node* s2):
-    Node(control, char_array_mem, s1, s2) {
-  }
-
-  virtual bool depends_only_on_test() const { return false; }
-  virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
-  virtual uint match_edge(uint idx) const;
-  virtual uint ideal_reg() const { return Op_RegI; }
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual const Type *Value(PhaseTransform *phase) const;
-};
-
-//------------------------------StrComp-------------------------------------
-class StrCompNode: public StrIntrinsicNode {
-public:
-  StrCompNode(Node* control, Node* char_array_mem,
-              Node* s1, Node* c1, Node* s2, Node* c2):
-    StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
-  virtual int Opcode() const;
-  virtual const Type* bottom_type() const { return TypeInt::INT; }
-};
-
-//------------------------------StrEquals-------------------------------------
-class StrEqualsNode: public StrIntrinsicNode {
-public:
-  StrEqualsNode(Node* control, Node* char_array_mem,
-                Node* s1, Node* s2, Node* c):
-    StrIntrinsicNode(control, char_array_mem, s1, s2, c) {};
-  virtual int Opcode() const;
-  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
-};
-
-//------------------------------StrIndexOf-------------------------------------
-class StrIndexOfNode: public StrIntrinsicNode {
-public:
-  StrIndexOfNode(Node* control, Node* char_array_mem,
-              Node* s1, Node* c1, Node* s2, Node* c2):
-    StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
-  virtual int Opcode() const;
-  virtual const Type* bottom_type() const { return TypeInt::INT; }
-};
-
-//------------------------------AryEq---------------------------------------
-class AryEqNode: public StrIntrinsicNode {
-public:
-  AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2):
-    StrIntrinsicNode(control, char_array_mem, s1, s2) {};
-  virtual int Opcode() const;
-  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
-};
-
-
-//------------------------------EncodeISOArray--------------------------------
-// encode char[] to byte[] in ISO_8859_1
-class EncodeISOArrayNode: public Node {
-public:
-  EncodeISOArrayNode(Node *control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {};
-  virtual int Opcode() const;
-  virtual bool depends_only_on_test() const { return false; }
-  virtual const Type* bottom_type() const { return TypeInt::INT; }
-  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
-  virtual uint match_edge(uint idx) const;
-  virtual uint ideal_reg() const { return Op_RegI; }
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
-  virtual const Type *Value(PhaseTransform *phase) const;
-};
-
 //------------------------------MemBar-----------------------------------------
 // There are different flavors of Memory Barriers to match the Java Memory
 // Model.  Monitor-enter and volatile-load act as Aquires: no following ref
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/movenode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 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 "opto/addnode.hpp"
+#include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
+#include "opto/movenode.hpp"
+#include "opto/phaseX.hpp"
+#include "opto/subnode.hpp"
+
+//=============================================================================
+/*
+ The major change is for CMoveP and StrComp.  They have related but slightly
+ different problems.  They both take in TWO oops which are both null-checked
+ independently before the using Node.  After CCP removes the CastPP's they need
+ to pick up the guarding test edge - in this case TWO control edges.  I tried
+ various solutions, all have problems:
+
+ (1) Do nothing.  This leads to a bug where we hoist a Load from a CMoveP or a
+ StrComp above a guarding null check.  I've seen both cases in normal -Xcomp
+ testing.
+
+ (2) Plug the control edge from 1 of the 2 oops in.  Apparent problem here is
+ to figure out which test post-dominates.  The real problem is that it doesn't
+ matter which one you pick.  After you pick up, the dominating-test elider in
+ IGVN can remove the test and allow you to hoist up to the dominating test on
+ the chosen oop bypassing the test on the not-chosen oop.  Seen in testing.
+ Oops.
+
+ (3) Leave the CastPP's in.  This makes the graph more accurate in some sense;
+ we get to keep around the knowledge that an oop is not-null after some test.
+ Alas, the CastPP's interfere with GVN (some values are the regular oop, some
+ are the CastPP of the oop, all merge at Phi's which cannot collapse, etc).
+ This cost us 10% on SpecJVM, even when I removed some of the more trivial
+ cases in the optimizer.  Removing more useless Phi's started allowing Loads to
+ illegally float above null checks.  I gave up on this approach.
+
+ (4) Add BOTH control edges to both tests.  Alas, too much code knows that
+ control edges are in slot-zero ONLY.  Many quick asserts fail; no way to do
+ this one.  Note that I really want to allow the CMoveP to float and add both
+ control edges to the dependent Load op - meaning I can select early but I
+ cannot Load until I pass both tests.
+
+ (5) Do not hoist CMoveP and StrComp.  To this end I added the v-call
+ depends_only_on_test().  No obvious performance loss on Spec, but we are
+ clearly conservative on CMoveP (also so on StrComp but that's unlikely to
+ matter ever).
+
+ */
+
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.
+// Move constants to the right.
+Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if( in(0) && remove_dead_region(phase, can_reshape) ) return this;
+  // Don't bother trying to transform a dead node
+  if( in(0) && in(0)->is_top() )  return NULL;
+  assert( !phase->eqv(in(Condition), this) &&
+         !phase->eqv(in(IfFalse), this) &&
+         !phase->eqv(in(IfTrue), this), "dead loop in CMoveNode::Ideal" );
+  if( phase->type(in(Condition)) == Type::TOP )
+  return NULL; // return NULL when Condition is dead
+
+  if( in(IfFalse)->is_Con() && !in(IfTrue)->is_Con() ) {
+    if( in(Condition)->is_Bool() ) {
+      BoolNode* b  = in(Condition)->as_Bool();
+      BoolNode* b2 = b->negate(phase);
+      return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type );
+    }
+  }
+  return NULL;
+}
+
+//------------------------------is_cmove_id------------------------------------
+// Helper function to check for CMOVE identity.  Shared with PhiNode::Identity
+Node *CMoveNode::is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b ) {
+  // Check for Cmp'ing and CMove'ing same values
+  if( (phase->eqv(cmp->in(1),f) &&
+       phase->eqv(cmp->in(2),t)) ||
+     // Swapped Cmp is OK
+     (phase->eqv(cmp->in(2),f) &&
+      phase->eqv(cmp->in(1),t)) ) {
+       // Give up this identity check for floating points because it may choose incorrect
+       // value around 0.0 and -0.0
+       if ( cmp->Opcode()==Op_CmpF || cmp->Opcode()==Op_CmpD )
+       return NULL;
+       // Check for "(t==f)?t:f;" and replace with "f"
+       if( b->_test._test == BoolTest::eq )
+       return f;
+       // Allow the inverted case as well
+       // Check for "(t!=f)?t:f;" and replace with "t"
+       if( b->_test._test == BoolTest::ne )
+       return t;
+     }
+  return NULL;
+}
+
+//------------------------------Identity---------------------------------------
+// Conditional-move is an identity if both inputs are the same, or the test
+// true or false.
+Node *CMoveNode::Identity( PhaseTransform *phase ) {
+  if( phase->eqv(in(IfFalse),in(IfTrue)) ) // C-moving identical inputs?
+  return in(IfFalse);         // Then it doesn't matter
+  if( phase->type(in(Condition)) == TypeInt::ZERO )
+  return in(IfFalse);         // Always pick left(false) input
+  if( phase->type(in(Condition)) == TypeInt::ONE )
+  return in(IfTrue);          // Always pick right(true) input
+
+  // Check for CMove'ing a constant after comparing against the constant.
+  // Happens all the time now, since if we compare equality vs a constant in
+  // the parser, we "know" the variable is constant on one path and we force
+  // it.  Thus code like "if( x==0 ) {/*EMPTY*/}" ends up inserting a
+  // conditional move: "x = (x==0)?0:x;".  Yucko.  This fix is slightly more
+  // general in that we don't need constants.
+  if( in(Condition)->is_Bool() ) {
+    BoolNode *b = in(Condition)->as_Bool();
+    Node *cmp = b->in(1);
+    if( cmp->is_Cmp() ) {
+      Node *id = is_cmove_id( phase, cmp, in(IfTrue), in(IfFalse), b );
+      if( id ) return id;
+    }
+  }
+
+  return this;
+}
+
+//------------------------------Value------------------------------------------
+// Result is the meet of inputs
+const Type *CMoveNode::Value( PhaseTransform *phase ) const {
+  if( phase->type(in(Condition)) == Type::TOP )
+  return Type::TOP;
+  return phase->type(in(IfFalse))->meet_speculative(phase->type(in(IfTrue)));
+}
+
+//------------------------------make-------------------------------------------
+// Make a correctly-flavored CMove.  Since _type is directly determined
+// from the inputs we do not need to specify it here.
+CMoveNode *CMoveNode::make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ) {
+  switch( t->basic_type() ) {
+    case T_INT:     return new (C) CMoveINode( bol, left, right, t->is_int() );
+    case T_FLOAT:   return new (C) CMoveFNode( bol, left, right, t );
+    case T_DOUBLE:  return new (C) CMoveDNode( bol, left, right, t );
+    case T_LONG:    return new (C) CMoveLNode( bol, left, right, t->is_long() );
+    case T_OBJECT:  return new (C) CMovePNode( c, bol, left, right, t->is_oopptr() );
+    case T_ADDRESS: return new (C) CMovePNode( c, bol, left, right, t->is_ptr() );
+    case T_NARROWOOP: return new (C) CMoveNNode( c, bol, left, right, t );
+    default:
+    ShouldNotReachHere();
+    return NULL;
+  }
+}
+
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.
+// Check for conversions to boolean
+Node *CMoveINode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  // Try generic ideal's first
+  Node *x = CMoveNode::Ideal(phase, can_reshape);
+  if( x ) return x;
+
+  // If zero is on the left (false-case, no-move-case) it must mean another
+  // constant is on the right (otherwise the shared CMove::Ideal code would
+  // have moved the constant to the right).  This situation is bad for Intel
+  // and a don't-care for Sparc.  It's bad for Intel because the zero has to
+  // be manifested in a register with a XOR which kills flags, which are live
+  // on input to the CMoveI, leading to a situation which causes excessive
+  // spilling on Intel.  For Sparc, if the zero in on the left the Sparc will
+  // zero a register via G0 and conditionally-move the other constant.  If the
+  // zero is on the right, the Sparc will load the first constant with a
+  // 13-bit set-lo and conditionally move G0.  See bug 4677505.
+  if( phase->type(in(IfFalse)) == TypeInt::ZERO && !(phase->type(in(IfTrue)) == TypeInt::ZERO) ) {
+    if( in(Condition)->is_Bool() ) {
+      BoolNode* b  = in(Condition)->as_Bool();
+      BoolNode* b2 = b->negate(phase);
+      return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type );
+    }
+  }
+
+  // Now check for booleans
+  int flip = 0;
+
+  // Check for picking from zero/one
+  if( phase->type(in(IfFalse)) == TypeInt::ZERO && phase->type(in(IfTrue)) == TypeInt::ONE ) {
+    flip = 1 - flip;
+  } else if( phase->type(in(IfFalse)) == TypeInt::ONE && phase->type(in(IfTrue)) == TypeInt::ZERO ) {
+  } else return NULL;
+
+  // Check for eq/ne test
+  if( !in(1)->is_Bool() ) return NULL;
+  BoolNode *bol = in(1)->as_Bool();
+  if( bol->_test._test == BoolTest::eq ) {
+  } else if( bol->_test._test == BoolTest::ne ) {
+    flip = 1-flip;
+  } else return NULL;
+
+  // Check for vs 0 or 1
+  if( !bol->in(1)->is_Cmp() ) return NULL;
+  const CmpNode *cmp = bol->in(1)->as_Cmp();
+  if( phase->type(cmp->in(2)) == TypeInt::ZERO ) {
+  } else if( phase->type(cmp->in(2)) == TypeInt::ONE ) {
+    // Allow cmp-vs-1 if the other input is bounded by 0-1
+    if( phase->type(cmp->in(1)) != TypeInt::BOOL )
+    return NULL;
+    flip = 1 - flip;
+  } else return NULL;
+
+  // Convert to a bool (flipped)
+  // Build int->bool conversion
+#ifndef PRODUCT
+  if( PrintOpto ) tty->print_cr("CMOV to I2B");
+#endif
+  Node *n = new (phase->C) Conv2BNode( cmp->in(1) );
+  if( flip )
+  n = new (phase->C) XorINode( phase->transform(n), phase->intcon(1) );
+
+  return n;
+}
+
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.
+// Check for absolute value
+Node *CMoveFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  // Try generic ideal's first
+  Node *x = CMoveNode::Ideal(phase, can_reshape);
+  if( x ) return x;
+
+  int  cmp_zero_idx = 0;        // Index of compare input where to look for zero
+  int  phi_x_idx = 0;           // Index of phi input where to find naked x
+
+  // Find the Bool
+  if( !in(1)->is_Bool() ) return NULL;
+  BoolNode *bol = in(1)->as_Bool();
+  // Check bool sense
+  switch( bol->_test._test ) {
+    case BoolTest::lt: cmp_zero_idx = 1; phi_x_idx = IfTrue;  break;
+    case BoolTest::le: cmp_zero_idx = 2; phi_x_idx = IfFalse; break;
+    case BoolTest::gt: cmp_zero_idx = 2; phi_x_idx = IfTrue;  break;
+    case BoolTest::ge: cmp_zero_idx = 1; phi_x_idx = IfFalse; break;
+    default:           return NULL;                           break;
+  }
+
+  // Find zero input of CmpF; the other input is being abs'd
+  Node *cmpf = bol->in(1);
+  if( cmpf->Opcode() != Op_CmpF ) return NULL;
+  Node *X = NULL;
+  bool flip = false;
+  if( phase->type(cmpf->in(cmp_zero_idx)) == TypeF::ZERO ) {
+    X = cmpf->in(3 - cmp_zero_idx);
+  } else if (phase->type(cmpf->in(3 - cmp_zero_idx)) == TypeF::ZERO) {
+    // The test is inverted, we should invert the result...
+    X = cmpf->in(cmp_zero_idx);
+    flip = true;
+  } else {
+    return NULL;
+  }
+
+  // If X is found on the appropriate phi input, find the subtract on the other
+  if( X != in(phi_x_idx) ) return NULL;
+  int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
+  Node *sub = in(phi_sub_idx);
+
+  // Allow only SubF(0,X) and fail out for all others; NegF is not OK
+  if( sub->Opcode() != Op_SubF ||
+     sub->in(2) != X ||
+     phase->type(sub->in(1)) != TypeF::ZERO ) return NULL;
+
+  Node *abs = new (phase->C) AbsFNode( X );
+  if( flip )
+  abs = new (phase->C) SubFNode(sub->in(1), phase->transform(abs));
+
+  return abs;
+}
+
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.
+// Check for absolute value
+Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  // Try generic ideal's first
+  Node *x = CMoveNode::Ideal(phase, can_reshape);
+  if( x ) return x;
+
+  int  cmp_zero_idx = 0;        // Index of compare input where to look for zero
+  int  phi_x_idx = 0;           // Index of phi input where to find naked x
+
+  // Find the Bool
+  if( !in(1)->is_Bool() ) return NULL;
+  BoolNode *bol = in(1)->as_Bool();
+  // Check bool sense
+  switch( bol->_test._test ) {
+    case BoolTest::lt: cmp_zero_idx = 1; phi_x_idx = IfTrue;  break;
+    case BoolTest::le: cmp_zero_idx = 2; phi_x_idx = IfFalse; break;
+    case BoolTest::gt: cmp_zero_idx = 2; phi_x_idx = IfTrue;  break;
+    case BoolTest::ge: cmp_zero_idx = 1; phi_x_idx = IfFalse; break;
+    default:           return NULL;                           break;
+  }
+
+  // Find zero input of CmpD; the other input is being abs'd
+  Node *cmpd = bol->in(1);
+  if( cmpd->Opcode() != Op_CmpD ) return NULL;
+  Node *X = NULL;
+  bool flip = false;
+  if( phase->type(cmpd->in(cmp_zero_idx)) == TypeD::ZERO ) {
+    X = cmpd->in(3 - cmp_zero_idx);
+  } else if (phase->type(cmpd->in(3 - cmp_zero_idx)) == TypeD::ZERO) {
+    // The test is inverted, we should invert the result...
+    X = cmpd->in(cmp_zero_idx);
+    flip = true;
+  } else {
+    return NULL;
+  }
+
+  // If X is found on the appropriate phi input, find the subtract on the other
+  if( X != in(phi_x_idx) ) return NULL;
+  int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
+  Node *sub = in(phi_sub_idx);
+
+  // Allow only SubD(0,X) and fail out for all others; NegD is not OK
+  if( sub->Opcode() != Op_SubD ||
+     sub->in(2) != X ||
+     phase->type(sub->in(1)) != TypeD::ZERO ) return NULL;
+
+  Node *abs = new (phase->C) AbsDNode( X );
+  if( flip )
+  abs = new (phase->C) SubDNode(sub->in(1), phase->transform(abs));
+
+  return abs;
+}
+
+//------------------------------Value------------------------------------------
+const Type *MoveL2DNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeLong *tl = t->is_long();
+  if( !tl->is_con() ) return bottom_type();
+  JavaValue v;
+  v.set_jlong(tl->get_con());
+  return TypeD::make( v.get_jdouble() );
+}
+
+//------------------------------Value------------------------------------------
+const Type *MoveI2FNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  const TypeInt *ti = t->is_int();
+  if( !ti->is_con() )   return bottom_type();
+  JavaValue v;
+  v.set_jint(ti->get_con());
+  return TypeF::make( v.get_jfloat() );
+}
+
+//------------------------------Value------------------------------------------
+const Type *MoveF2INode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP )       return Type::TOP;
+  if( t == Type::FLOAT ) return TypeInt::INT;
+  const TypeF *tf = t->is_float_constant();
+  JavaValue v;
+  v.set_jfloat(tf->getf());
+  return TypeInt::make( v.get_jint() );
+}
+
+//------------------------------Value------------------------------------------
+const Type *MoveD2LNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return Type::TOP;
+  if( t == Type::DOUBLE ) return TypeLong::LONG;
+  const TypeD *td = t->is_double_constant();
+  JavaValue v;
+  v.set_jdouble(td->getd());
+  return TypeLong::make( v.get_jlong() );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/movenode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 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_OPTO_MOVENODE_HPP
+#define SHARE_VM_OPTO_MOVENODE_HPP
+
+#include "opto/node.hpp"
+
+//------------------------------CMoveNode--------------------------------------
+// Conditional move
+class CMoveNode : public TypeNode {
+  public:
+  enum { Control,               // When is it safe to do this cmove?
+    Condition,             // Condition controlling the cmove
+    IfFalse,               // Value if condition is false
+    IfTrue };              // Value if condition is true
+  CMoveNode( Node *bol, Node *left, Node *right, const Type *t ) : TypeNode(t,4)
+  {
+    init_class_id(Class_CMove);
+    // all inputs are nullified in Node::Node(int)
+    // init_req(Control,NULL);
+    init_req(Condition,bol);
+    init_req(IfFalse,left);
+    init_req(IfTrue,right);
+  }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  static CMoveNode *make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t );
+  // Helper function to spot cmove graph shapes
+  static Node *is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b );
+};
+
+//------------------------------CMoveDNode-------------------------------------
+class CMoveDNode : public CMoveNode {
+  public:
+  CMoveDNode( Node *bol, Node *left, Node *right, const Type* t) : CMoveNode(bol,left,right,t){}
+  virtual int Opcode() const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+//------------------------------CMoveFNode-------------------------------------
+class CMoveFNode : public CMoveNode {
+  public:
+  CMoveFNode( Node *bol, Node *left, Node *right, const Type* t ) : CMoveNode(bol,left,right,t) {}
+  virtual int Opcode() const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+//------------------------------CMoveINode-------------------------------------
+class CMoveINode : public CMoveNode {
+  public:
+  CMoveINode( Node *bol, Node *left, Node *right, const TypeInt *ti ) : CMoveNode(bol,left,right,ti){}
+  virtual int Opcode() const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+//------------------------------CMoveLNode-------------------------------------
+class CMoveLNode : public CMoveNode {
+  public:
+  CMoveLNode(Node *bol, Node *left, Node *right, const TypeLong *tl ) : CMoveNode(bol,left,right,tl){}
+  virtual int Opcode() const;
+};
+
+//------------------------------CMovePNode-------------------------------------
+class CMovePNode : public CMoveNode {
+  public:
+  CMovePNode( Node *c, Node *bol, Node *left, Node *right, const TypePtr* t ) : CMoveNode(bol,left,right,t) { init_req(Control,c); }
+  virtual int Opcode() const;
+};
+
+//------------------------------CMoveNNode-------------------------------------
+class CMoveNNode : public CMoveNode {
+  public:
+  CMoveNNode( Node *c, Node *bol, Node *left, Node *right, const Type* t ) : CMoveNode(bol,left,right,t) { init_req(Control,c); }
+  virtual int Opcode() const;
+};
+
+//
+class MoveI2FNode : public Node {
+  public:
+  MoveI2FNode( Node *value ) : Node(0,value) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::FLOAT; }
+  virtual uint ideal_reg() const { return Op_RegF; }
+  virtual const Type* Value( PhaseTransform *phase ) const;
+};
+
+class MoveL2DNode : public Node {
+  public:
+  MoveL2DNode( Node *value ) : Node(0,value) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return Type::DOUBLE; }
+  virtual uint ideal_reg() const { return Op_RegD; }
+  virtual const Type* Value( PhaseTransform *phase ) const;
+};
+
+class MoveF2INode : public Node {
+  public:
+  MoveF2INode( Node *value ) : Node(0,value) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual const Type* Value( PhaseTransform *phase ) const;
+};
+
+class MoveD2LNode : public Node {
+  public:
+  MoveD2LNode( Node *value ) : Node(0,value) {}
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeLong::LONG; }
+  virtual uint ideal_reg() const { return Op_RegL; }
+  virtual const Type* Value( PhaseTransform *phase ) const;
+};
+
+//------------------------------BinaryNode-------------------------------------
+// Place holder for the 2 conditional inputs to a CMove.  CMove needs 4
+// inputs: the Bool (for the lt/gt/eq/ne bits), the flags (result of some
+// compare), and the 2 values to select between.  The Matcher requires a
+// binary tree so we break it down like this:
+//     (CMove (Binary bol cmp) (Binary src1 src2))
+class BinaryNode : public Node {
+  public:
+  BinaryNode( Node *n1, Node *n2 ) : Node(0,n1,n2) { }
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return 0; }
+};
+
+
+#endif // SHARE_VM_OPTO_MOVENODE_HPP
+
--- a/hotspot/src/share/vm/opto/mulnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/mulnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -26,6 +26,7 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/phaseX.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/narrowptrnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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 "opto/narrowptrnode.hpp"
+#include "opto/phaseX.hpp"
+
+Node* DecodeNNode::Identity(PhaseTransform* phase) {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return in(1);
+
+  if (in(1)->is_EncodeP()) {
+    // (DecodeN (EncodeP p)) -> p
+    return in(1)->in(1);
+  }
+  return this;
+}
+
+const Type *DecodeNNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if (t == Type::TOP) return Type::TOP;
+  if (t == TypeNarrowOop::NULL_PTR) return TypePtr::NULL_PTR;
+
+  assert(t->isa_narrowoop(), "only  narrowoop here");
+  return t->make_ptr();
+}
+
+Node* EncodePNode::Identity(PhaseTransform* phase) {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return in(1);
+
+  if (in(1)->is_DecodeN()) {
+    // (EncodeP (DecodeN p)) -> p
+    return in(1)->in(1);
+  }
+  return this;
+}
+
+const Type *EncodePNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if (t == Type::TOP) return Type::TOP;
+  if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR;
+
+  assert(t->isa_oop_ptr(), "only oopptr here");
+  return t->make_narrowoop();
+}
+
+
+Node *EncodeNarrowPtrNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+  return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1));
+}
+
+Node* DecodeNKlassNode::Identity(PhaseTransform* phase) {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return in(1);
+
+  if (in(1)->is_EncodePKlass()) {
+    // (DecodeNKlass (EncodePKlass p)) -> p
+    return in(1)->in(1);
+  }
+  return this;
+}
+
+const Type *DecodeNKlassNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if (t == Type::TOP) return Type::TOP;
+  assert(t != TypeNarrowKlass::NULL_PTR, "null klass?");
+
+  assert(t->isa_narrowklass(), "only narrow klass ptr here");
+  return t->make_ptr();
+}
+
+Node* EncodePKlassNode::Identity(PhaseTransform* phase) {
+  const Type *t = phase->type( in(1) );
+  if( t == Type::TOP ) return in(1);
+
+  if (in(1)->is_DecodeNKlass()) {
+    // (EncodePKlass (DecodeNKlass p)) -> p
+    return in(1)->in(1);
+  }
+  return this;
+}
+
+const Type *EncodePKlassNode::Value( PhaseTransform *phase ) const {
+  const Type *t = phase->type( in(1) );
+  if (t == Type::TOP) return Type::TOP;
+  assert (t != TypePtr::NULL_PTR, "null klass?");
+
+  assert(UseCompressedClassPointers && t->isa_klassptr(), "only klass ptr here");
+  return t->make_narrowklass();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/narrowptrnode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 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_OPTO_NARROWPTRNODE_HPP
+#define SHARE_VM_OPTO_NARROWPTRNODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+//------------------------------EncodeNarrowPtr--------------------------------
+class EncodeNarrowPtrNode : public TypeNode {
+  protected:
+  EncodeNarrowPtrNode(Node* value, const Type* type):
+  TypeNode(type, 2) {
+    init_class_id(Class_EncodeNarrowPtr);
+    init_req(0, NULL);
+    init_req(1, value);
+  }
+  public:
+  virtual uint  ideal_reg() const { return Op_RegN; }
+  virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
+};
+
+//------------------------------EncodeP--------------------------------
+// Encodes an oop pointers into its compressed form
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class EncodePNode : public EncodeNarrowPtrNode {
+  public:
+  EncodePNode(Node* value, const Type* type):
+  EncodeNarrowPtrNode(value, type) {
+    init_class_id(Class_EncodeP);
+  }
+  virtual int Opcode() const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+};
+
+//------------------------------EncodePKlass--------------------------------
+// Encodes a klass pointer into its compressed form
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class EncodePKlassNode : public EncodeNarrowPtrNode {
+  public:
+  EncodePKlassNode(Node* value, const Type* type):
+  EncodeNarrowPtrNode(value, type) {
+    init_class_id(Class_EncodePKlass);
+  }
+  virtual int Opcode() const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual const Type *Value( PhaseTransform *phase ) const;
+};
+
+//------------------------------DecodeNarrowPtr--------------------------------
+class DecodeNarrowPtrNode : public TypeNode {
+  protected:
+  DecodeNarrowPtrNode(Node* value, const Type* type):
+  TypeNode(type, 2) {
+    init_class_id(Class_DecodeNarrowPtr);
+    init_req(0, NULL);
+    init_req(1, value);
+  }
+  public:
+  virtual uint  ideal_reg() const { return Op_RegP; }
+};
+
+//------------------------------DecodeN--------------------------------
+// Converts a narrow oop into a real oop ptr.
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class DecodeNNode : public DecodeNarrowPtrNode {
+  public:
+  DecodeNNode(Node* value, const Type* type):
+  DecodeNarrowPtrNode(value, type) {
+    init_class_id(Class_DecodeN);
+  }
+  virtual int Opcode() const;
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+};
+
+//------------------------------DecodeNKlass--------------------------------
+// Converts a narrow klass pointer into a real klass ptr.
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class DecodeNKlassNode : public DecodeNarrowPtrNode {
+  public:
+  DecodeNKlassNode(Node* value, const Type* type):
+  DecodeNarrowPtrNode(value, type) {
+    init_class_id(Class_DecodeNKlass);
+  }
+  virtual int Opcode() const;
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+};
+
+#endif // SHARE_VM_OPTO_NARROWPTRNODE_HPP
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/opaquenode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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 "opto/opaquenode.hpp"
+#include "opto/phaseX.hpp"
+
+//=============================================================================
+// Do not allow value-numbering
+uint Opaque1Node::hash() const { return NO_HASH; }
+uint Opaque1Node::cmp( const Node &n ) const {
+  return (&n == this);          // Always fail except on self
+}
+
+//------------------------------Identity---------------------------------------
+// If _major_progress, then more loop optimizations follow.  Do NOT remove
+// the opaque Node until no more loop ops can happen.  Note the timing of
+// _major_progress; it's set in the major loop optimizations THEN comes the
+// call to IterGVN and any chance of hitting this code.  Hence there's no
+// phase-ordering problem with stripping Opaque1 in IGVN followed by some
+// more loop optimizations that require it.
+Node *Opaque1Node::Identity( PhaseTransform *phase ) {
+  return phase->C->major_progress() ? this : in(1);
+}
+
+//=============================================================================
+// A node to prevent unwanted optimizations.  Allows constant folding.  Stops
+// value-numbering, most Ideal calls or Identity functions.  This Node is
+// specifically designed to prevent the pre-increment value of a loop trip
+// counter from being live out of the bottom of the loop (hence causing the
+// pre- and post-increment values both being live and thus requiring an extra
+// temp register and an extra move).  If we "accidentally" optimize through
+// this kind of a Node, we'll get slightly pessimal, but correct, code.  Thus
+// it's OK to be slightly sloppy on optimizations here.
+
+// Do not allow value-numbering
+uint Opaque2Node::hash() const { return NO_HASH; }
+uint Opaque2Node::cmp( const Node &n ) const {
+  return (&n == this);          // Always fail except on self
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/opaquenode.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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_OPTO_OPAQUENODE_HPP
+#define SHARE_VM_OPTO_OPAQUENODE_HPP
+
+#include "opto/node.hpp"
+#include "opto/opcodes.hpp"
+
+//------------------------------Opaque1Node------------------------------------
+// A node to prevent unwanted optimizations.  Allows constant folding.
+// Stops value-numbering, Ideal calls or Identity functions.
+class Opaque1Node : public Node {
+  virtual uint hash() const ;                  // { return NO_HASH; }
+  virtual uint cmp( const Node &n ) const;
+  public:
+  Opaque1Node( Compile* C, Node *n ) : Node(0,n) {
+    // Put it on the Macro nodes list to removed during macro nodes expansion.
+    init_flags(Flag_is_macro);
+    C->add_macro_node(this);
+  }
+  // Special version for the pre-loop to hold the original loop limit
+  // which is consumed by range check elimination.
+  Opaque1Node( Compile* C, Node *n, Node* orig_limit ) : Node(0,n,orig_limit) {
+    // Put it on the Macro nodes list to removed during macro nodes expansion.
+    init_flags(Flag_is_macro);
+    C->add_macro_node(this);
+  }
+  Node* original_loop_limit() { return req()==3 ? in(2) : NULL; }
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+  virtual Node *Identity( PhaseTransform *phase );
+};
+
+//------------------------------Opaque2Node------------------------------------
+// A node to prevent unwanted optimizations.  Allows constant folding.  Stops
+// value-numbering, most Ideal calls or Identity functions.  This Node is
+// specifically designed to prevent the pre-increment value of a loop trip
+// counter from being live out of the bottom of the loop (hence causing the
+// pre- and post-increment values both being live and thus requiring an extra
+// temp register and an extra move).  If we "accidentally" optimize through
+// this kind of a Node, we'll get slightly pessimal, but correct, code.  Thus
+// it's OK to be slightly sloppy on optimizations here.
+class Opaque2Node : public Node {
+  virtual uint hash() const ;                  // { return NO_HASH; }
+  virtual uint cmp( const Node &n ) const;
+  public:
+  Opaque2Node( Compile* C, Node *n ) : Node(0,n) {
+    // Put it on the Macro nodes list to removed during macro nodes expansion.
+    init_flags(Flag_is_macro);
+    C->add_macro_node(this);
+  }
+  virtual int Opcode() const;
+  virtual const Type *bottom_type() const { return TypeInt::INT; }
+};
+
+//------------------------------Opaque3Node------------------------------------
+// A node to prevent unwanted optimizations. Will be optimized only during
+// macro nodes expansion.
+class Opaque3Node : public Opaque2Node {
+  int _opt; // what optimization it was used for
+  public:
+  enum { RTM_OPT };
+  Opaque3Node(Compile* C, Node *n, int opt) : Opaque2Node(C, n), _opt(opt) {}
+  virtual int Opcode() const;
+  bool rtm_opt() const { return (_opt == RTM_OPT); }
+};
+
+#endif // SHARE_VM_OPTO_OPAQUENODE_HPP
+
--- a/hotspot/src/share/vm/opto/output.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/output.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -42,18 +42,12 @@
 #include "runtime/handles.inline.hpp"
 #include "utilities/xmlstream.hpp"
 
-extern uint size_exception_handler();
-extern uint size_deopt_handler();
-
 #ifndef PRODUCT
 #define DEBUG_ARG(x) , x
 #else
 #define DEBUG_ARG(x)
 #endif
 
-extern int emit_exception_handler(CodeBuffer &cbuf);
-extern int emit_deopt_handler(CodeBuffer &cbuf);
-
 // Convert Nodes to instruction bits and pass off to the VM
 void Compile::Output() {
   // RootNode goes
@@ -394,6 +388,11 @@
         blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding
         reloc_size += mach->reloc();
         if (mach->is_MachCall()) {
+          // add size information for trampoline stub
+          // class CallStubImpl is platform-specific and defined in the *.ad files.
+          stub_size  += CallStubImpl::size_call_trampoline();
+          reloc_size += CallStubImpl::reloc_call_trampoline();
+
           MachCallNode *mcall = mach->as_MachCall();
           // This destination address is NOT PC-relative
 
@@ -1133,10 +1132,9 @@
   shorten_branches(blk_starts, code_req, locs_req, stub_req);
 
   // nmethod and CodeBuffer count stubs & constants as part of method's code.
-  int exception_handler_req = size_exception_handler();
-  int deopt_handler_req = size_deopt_handler();
-  exception_handler_req += MAX_stubs_size; // add marginal slop for handler
-  deopt_handler_req += MAX_stubs_size; // add marginal slop for handler
+  // class HandlerImpl is platform-specific and defined in the *.ad files.
+  int exception_handler_req = HandlerImpl::size_exception_handler() + MAX_stubs_size; // add marginal slop for handler
+  int deopt_handler_req     = HandlerImpl::size_deopt_handler()     + MAX_stubs_size; // add marginal slop for handler
   stub_req += MAX_stubs_size;   // ensure per-stub margin
   code_req += MAX_inst_size;    // ensure per-instruction margin
 
@@ -1622,17 +1620,18 @@
   FillExceptionTables(inct_cnt, call_returns, inct_starts, blk_labels);
 
   // Only java methods have exception handlers and deopt handlers
+  // class HandlerImpl is platform-specific and defined in the *.ad files.
   if (_method) {
     // Emit the exception handler code.
-    _code_offsets.set_value(CodeOffsets::Exceptions, emit_exception_handler(*cb));
+    _code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb));
     // Emit the deopt handler code.
-    _code_offsets.set_value(CodeOffsets::Deopt, emit_deopt_handler(*cb));
+    _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb));
 
     // Emit the MethodHandle deopt handler code (if required).
     if (has_method_handle_invokes()) {
       // We can use the same code as for the normal deopt handler, we
       // just need a different entry point address.
-      _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb));
+      _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb));
     }
   }
 
--- a/hotspot/src/share/vm/opto/parse.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -486,6 +486,8 @@
   // Helper function to compute array addressing
   Node* array_addressing(BasicType type, int vals, const Type* *result2=NULL);
 
+  void rtm_deopt();
+
   // Pass current map to exits
   void return_current(Node* value);
 
--- a/hotspot/src/share/vm/opto/parse1.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,9 +27,11 @@
 #include "interpreter/linkResolver.hpp"
 #include "oops/method.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #include "opto/locknode.hpp"
 #include "opto/memnode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
@@ -567,6 +569,10 @@
     set_map(entry_map);
     do_method_entry();
   }
+  if (depth() == 1) {
+    // Add check to deoptimize the nmethod if RTM state was changed
+    rtm_deopt();
+  }
 
   // Check for bailouts during method entry.
   if (failing()) {
@@ -2006,6 +2012,42 @@
   set_control( _gvn.transform(result_rgn) );
 }
 
+// Add check to deoptimize if RTM state is not ProfileRTM
+void Parse::rtm_deopt() {
+#if INCLUDE_RTM_OPT
+  if (C->profile_rtm()) {
+    assert(C->method() != NULL, "only for normal compilations");
+    assert(!C->method()->method_data()->is_empty(), "MDO is needed to record RTM state");
+    assert(depth() == 1, "generate check only for main compiled method");
+
+    // Set starting bci for uncommon trap.
+    set_parse_bci(is_osr_parse() ? osr_bci() : 0);
+
+    // Load the rtm_state from the MethodData.
+    const TypePtr* adr_type = TypeMetadataPtr::make(C->method()->method_data());
+    Node* mdo = makecon(adr_type);
+    int offset = MethodData::rtm_state_offset_in_bytes();
+    Node* adr_node = basic_plus_adr(mdo, mdo, offset);
+    Node* rtm_state = make_load(control(), adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
+
+    // Separate Load from Cmp by Opaque.
+    // In expand_macro_nodes() it will be replaced either
+    // with this load when there are locks in the code
+    // or with ProfileRTM (cmp->in(2)) otherwise so that
+    // the check will fold.
+    Node* profile_state = makecon(TypeInt::make(ProfileRTM));
+    Node* opq   = _gvn.transform( new (C) Opaque3Node(C, rtm_state, Opaque3Node::RTM_OPT) );
+    Node* chk   = _gvn.transform( new (C) CmpINode(opq, profile_state) );
+    Node* tst   = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) );
+    // Branch to failure if state was changed
+    { BuildCutout unless(this, tst, PROB_ALWAYS);
+      uncommon_trap(Deoptimization::Reason_rtm_state_change,
+                    Deoptimization::Action_make_not_entrant);
+    }
+  }
+#endif
+}
+
 //------------------------------return_current---------------------------------
 // Append current _map to _exit_return
 void Parse::return_current(Node* value) {
--- a/hotspot/src/share/vm/opto/parse2.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -30,6 +30,8 @@
 #include "interpreter/linkResolver.hpp"
 #include "memory/universe.inline.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #include "opto/matcher.hpp"
@@ -1288,7 +1290,7 @@
               (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
             TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
             const Type* tcc = ccast->as_Type()->type();
-            assert(tcc != obj_type && tcc->higher_equal_speculative(obj_type), "must improve");
+            assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve");
             // Delay transform() call to allow recovery of pre-cast value
             // at the control merge.
             _gvn.set_type_bottom(ccast);
@@ -1352,7 +1354,7 @@
 
   if (ccast != NULL) {
     const Type* tcc = ccast->as_Type()->type();
-    assert(tcc != tval && tcc->higher_equal_speculative(tval), "must improve");
+    assert(tcc != tval && tcc->higher_equal(tval), "must improve");
     // Delay transform() call to allow recovery of pre-cast value
     // at the control merge.
     ccast->set_req(0, control());
@@ -1393,7 +1395,7 @@
       Node* addp = load_klass->in(2);
       Node* obj = addp->in(AddPNode::Address);
       const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
-      if (obj_type->speculative_type() != NULL) {
+      if (obj_type->speculative_type_not_null() != NULL) {
         ciKlass* k = obj_type->speculative_type();
         inc_sp(2);
         obj = maybe_cast_profiled_obj(obj, k);
@@ -2277,6 +2279,14 @@
     maybe_add_safepoint(iter().get_dest());
     a = null();
     b = pop();
+    if (!_gvn.type(b)->speculative_maybe_null() &&
+        !too_many_traps(Deoptimization::Reason_speculate_null_check)) {
+      inc_sp(1);
+      Node* null_ctl = top();
+      b = null_check_oop(b, &null_ctl, true, true, true);
+      assert(null_ctl->is_top(), "no null control here");
+      dec_sp(1);
+    }
     c = _gvn.transform( new (C) CmpPNode(b, a) );
     do_ifnull(btest, c);
     break;
--- a/hotspot/src/share/vm/opto/parse3.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -28,6 +28,7 @@
 #include "memory/universe.inline.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,7 +27,6 @@
 #include "opto/block.hpp"
 #include "opto/callnode.hpp"
 #include "opto/cfgnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
@@ -330,7 +329,7 @@
   Node *sentinel_node = sentinel();
   for (uint i = 0; i < max; ++i) {
     Node *n = at(i);
-    if(n != NULL && n != sentinel_node && n->is_Type()) {
+    if(n != NULL && n != sentinel_node && n->is_Type() && n->outcnt() > 0) {
       TypeNode* tn = n->as_Type();
       const Type* t = tn->type();
       const Type* t_no_spec = t->remove_speculative();
--- a/hotspot/src/share/vm/opto/runtime.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -48,7 +48,6 @@
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/cfgnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/graphKit.hpp"
 #include "opto/machnode.hpp"
 #include "opto/matcher.hpp"
@@ -1310,6 +1309,14 @@
         tty->print_cr("%s", c->name());
         blc->print_on(tty);
       }
+#if INCLUDE_RTM_OPT
+    } else if (c->tag() == NamedCounter::RTMLockingCounter) {
+      RTMLockingCounters* rlc = ((RTMLockingNamedCounter*)c)->counters();
+      if (rlc->nonzero()) {
+        tty->print_cr("%s", c->name());
+        rlc->print_on(tty);
+      }
+#endif
     }
     c = c->next();
   }
@@ -1349,6 +1356,8 @@
   NamedCounter* c;
   if (tag == NamedCounter::BiasedLockingCounter) {
     c = new BiasedLockingNamedCounter(strdup(st.as_string()));
+  } else if (tag == NamedCounter::RTMLockingCounter) {
+    c = new RTMLockingNamedCounter(strdup(st.as_string()));
   } else {
     c = new NamedCounter(strdup(st.as_string()), tag);
   }
@@ -1357,6 +1366,7 @@
   // add counters so this is safe.
   NamedCounter* head;
   do {
+    c->set_next(NULL);
     head = _named_counters;
     c->set_next(head);
   } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head);
--- a/hotspot/src/share/vm/opto/runtime.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/runtime.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -29,6 +29,7 @@
 #include "opto/machnode.hpp"
 #include "opto/type.hpp"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/rtmLocking.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/vframe.hpp"
 
@@ -61,7 +62,8 @@
     NoTag,
     LockCounter,
     EliminatedLockCounter,
-    BiasedLockingCounter
+    BiasedLockingCounter,
+    RTMLockingCounter
   };
 
 private:
@@ -85,7 +87,7 @@
 
   NamedCounter* next() const    { return _next; }
   void set_next(NamedCounter* next) {
-    assert(_next == NULL, "already set");
+    assert(_next == NULL || next == NULL, "already set");
     _next = next;
   }
 
@@ -102,6 +104,18 @@
   BiasedLockingCounters* counters() { return &_counters; }
 };
 
+
+class RTMLockingNamedCounter : public NamedCounter {
+ private:
+ RTMLockingCounters _counters;
+
+ public:
+  RTMLockingNamedCounter(const char *n) :
+    NamedCounter(n, RTMLockingCounter), _counters() {}
+
+  RTMLockingCounters* counters() { return &_counters; }
+};
+
 typedef const TypeFunc*(*TypeFunc_generator)();
 
 class OptoRuntime : public AllStatic {
--- a/hotspot/src/share/vm/opto/split_if.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/split_if.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -25,8 +25,8 @@
 #include "precompiled.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/callnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/loopnode.hpp"
+#include "opto/movenode.hpp"
 
 
 //------------------------------split_thru_region------------------------------
--- a/hotspot/src/share/vm/opto/subnode.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -28,9 +28,9 @@
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/cfgnode.hpp"
-#include "opto/connode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/matcher.hpp"
+#include "opto/movenode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/phaseX.hpp"
--- a/hotspot/src/share/vm/opto/superword.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -27,11 +27,14 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/memnode.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/opcodes.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/superword.hpp"
 #include "opto/vectornode.hpp"
 
--- a/hotspot/src/share/vm/opto/superword.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -24,7 +24,6 @@
 #ifndef SHARE_VM_OPTO_SUPERWORD_HPP
 #define SHARE_VM_OPTO_SUPERWORD_HPP
 
-#include "opto/connode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/node.hpp"
 #include "opto/phaseX.hpp"
--- a/hotspot/src/share/vm/opto/type.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -350,9 +350,9 @@
   floop[1] = TypeInt::INT;
   TypeTuple::LOOPBODY = TypeTuple::make( 2, floop );
 
-  TypePtr::NULL_PTR= TypePtr::make( AnyPtr, TypePtr::Null, 0 );
-  TypePtr::NOTNULL = TypePtr::make( AnyPtr, TypePtr::NotNull, OffsetBot );
-  TypePtr::BOTTOM  = TypePtr::make( AnyPtr, TypePtr::BotPTR, OffsetBot );
+  TypePtr::NULL_PTR= TypePtr::make(AnyPtr, TypePtr::Null, 0);
+  TypePtr::NOTNULL = TypePtr::make(AnyPtr, TypePtr::NotNull, OffsetBot);
+  TypePtr::BOTTOM  = TypePtr::make(AnyPtr, TypePtr::BotPTR, OffsetBot);
 
   TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR );
   TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull );
@@ -372,7 +372,7 @@
                                            false, 0, oopDesc::mark_offset_in_bytes());
   TypeInstPtr::KLASS   = TypeInstPtr::make(TypePtr::BotPTR,  current->env()->Object_klass(),
                                            false, 0, oopDesc::klass_offset_in_bytes());
-  TypeOopPtr::BOTTOM  = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot, NULL);
+  TypeOopPtr::BOTTOM  = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot);
 
   TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot);
 
@@ -620,8 +620,8 @@
     return true;
   }
   // Now check the speculative parts as well
-  const TypeOopPtr* this_spec = isa_oopptr() != NULL ? isa_oopptr()->speculative() : NULL;
-  const TypeOopPtr* t_spec = t->isa_oopptr() != NULL ? t->isa_oopptr()->speculative() : NULL;
+  const TypePtr* this_spec = isa_ptr() != NULL ? is_ptr()->speculative() : NULL;
+  const TypePtr* t_spec = t->isa_ptr() != NULL ? t->is_ptr()->speculative() : NULL;
   if (this_spec != NULL && t_spec != NULL) {
     if (this_spec->interface_vs_oop_helper(t_spec)) {
       return true;
@@ -1975,6 +1975,25 @@
   return make(_elem->remove_speculative(), _size, _stable);
 }
 
+/**
+ * Return same type with cleaned up speculative part of element
+ */
+const Type* TypeAry::cleanup_speculative() const {
+  return make(_elem->cleanup_speculative(), _size, _stable);
+}
+
+/**
+ * Return same type but with a different inline depth (used for speculation)
+ *
+ * @param depth  depth to meet with
+ */
+const TypePtr* TypePtr::with_inline_depth(int depth) const {
+  if (!UseInlineDepthForSpeculativeTypes) {
+    return this;
+  }
+  return make(AnyPtr, _ptr, _offset, _speculative, depth);
+}
+
 //----------------------interface_vs_oop---------------------------------------
 #ifdef ASSERT
 bool TypeAry::interface_vs_oop(const Type *t) const {
@@ -2179,15 +2198,15 @@
 };
 
 //------------------------------make-------------------------------------------
-const TypePtr *TypePtr::make( TYPES t, enum PTR ptr, int offset ) {
-  return (TypePtr*)(new TypePtr(t,ptr,offset))->hashcons();
+const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* speculative, int inline_depth) {
+  return (TypePtr*)(new TypePtr(t,ptr,offset, speculative, inline_depth))->hashcons();
 }
 
 //------------------------------cast_to_ptr_type-------------------------------
 const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
   assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
   if( ptr == _ptr ) return this;
-  return make(_base, ptr, _offset);
+  return make(_base, ptr, _offset, _speculative, _inline_depth);
 }
 
 //------------------------------get_con----------------------------------------
@@ -2198,7 +2217,29 @@
 
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
-const Type *TypePtr::xmeet( const Type *t ) const {
+const Type *TypePtr::xmeet(const Type *t) const {
+  const Type* res = xmeet_helper(t);
+  if (res->isa_ptr() == NULL) {
+    return res;
+  }
+
+  const TypePtr* res_ptr = res->is_ptr();
+  if (res_ptr->speculative() != NULL) {
+    // type->speculative() == NULL means that speculation is no better
+    // than type, i.e. type->speculative() == type. So there are 2
+    // ways to represent the fact that we have no useful speculative
+    // data and we should use a single one to be able to test for
+    // equality between types. Check whether type->speculative() ==
+    // type and set speculative to NULL if it is the case.
+    if (res_ptr->remove_speculative() == res_ptr->speculative()) {
+      return res_ptr->remove_speculative();
+    }
+  }
+
+  return res;
+}
+
+const Type *TypePtr::xmeet_helper(const Type *t) const {
   // Perform a fast test for common case; meeting the same types together.
   if( this == t ) return this;  // Meeting same type-rep?
 
@@ -2221,7 +2262,9 @@
 
   case AnyPtr: {                // Meeting to AnyPtrs
     const TypePtr *tp = t->is_ptr();
-    return make( AnyPtr, meet_ptr(tp->ptr()), meet_offset(tp->offset()) );
+    const TypePtr* speculative = xmeet_speculative(tp);
+    int depth = meet_inline_depth(tp->inline_depth());
+    return make(AnyPtr, meet_ptr(tp->ptr()), meet_offset(tp->offset()), speculative, depth);
   }
   case RawPtr:                  // For these, flip the call around to cut down
   case OopPtr:
@@ -2260,7 +2303,7 @@
   BotPTR, NotNull, Constant, Null, AnyNull, TopPTR
 };
 const Type *TypePtr::xdual() const {
-  return new TypePtr( AnyPtr, dual_ptr(), dual_offset() );
+  return new TypePtr(AnyPtr, dual_ptr(), dual_offset(), dual_speculative(), dual_inline_depth());
 }
 
 //------------------------------xadd_offset------------------------------------
@@ -2281,20 +2324,245 @@
 
 //------------------------------add_offset-------------------------------------
 const TypePtr *TypePtr::add_offset( intptr_t offset ) const {
-  return make( AnyPtr, _ptr, xadd_offset(offset) );
+  return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth);
 }
 
 //------------------------------eq---------------------------------------------
 // Structural equality check for Type representations
 bool TypePtr::eq( const Type *t ) const {
   const TypePtr *a = (const TypePtr*)t;
-  return _ptr == a->ptr() && _offset == a->offset();
+  return _ptr == a->ptr() && _offset == a->offset() && eq_speculative(a) && _inline_depth == a->_inline_depth;
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypePtr::hash(void) const {
-  return _ptr + _offset;
+  return _ptr + _offset + hash_speculative() + _inline_depth;
+;
+}
+
+/**
+ * Return same type without a speculative part
+ */
+const Type* TypePtr::remove_speculative() const {
+  if (_speculative == NULL) {
+    return this;
+  }
+  assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth");
+  return make(AnyPtr, _ptr, _offset, NULL, _inline_depth);
+}
+
+/**
+ * Return same type but drop speculative part if we know we won't use
+ * it
+ */
+const Type* TypePtr::cleanup_speculative() const {
+  if (speculative() == NULL) {
+    return this;
+  }
+  const Type* no_spec = remove_speculative();
+  // If this is NULL_PTR then we don't need the speculative type
+  // (with_inline_depth in case the current type inline depth is
+  // InlineDepthTop)
+  if (no_spec == NULL_PTR->with_inline_depth(inline_depth())) {
+    return no_spec;
+  }
+  if (above_centerline(speculative()->ptr())) {
+    return no_spec;
+  }
+  const TypeOopPtr* spec_oopptr = speculative()->isa_oopptr();
+  // If the speculative may be null and is an inexact klass then it
+  // doesn't help
+  if (speculative()->maybe_null() && (spec_oopptr == NULL || !spec_oopptr->klass_is_exact())) {
+    return no_spec;
+  }
+  return this;
+}
+
+/**
+ * dual of the speculative part of the type
+ */
+const TypePtr* TypePtr::dual_speculative() const {
+  if (_speculative == NULL) {
+    return NULL;
+  }
+  return _speculative->dual()->is_ptr();
+}
+
+/**
+ * meet of the speculative parts of 2 types
+ *
+ * @param other  type to meet with
+ */
+const TypePtr* TypePtr::xmeet_speculative(const TypePtr* other) const {
+  bool this_has_spec = (_speculative != NULL);
+  bool other_has_spec = (other->speculative() != NULL);
+
+  if (!this_has_spec && !other_has_spec) {
+    return NULL;
+  }
+
+  // If we are at a point where control flow meets and one branch has
+  // a speculative type and the other has not, we meet the speculative
+  // type of one branch with the actual type of the other. If the
+  // actual type is exact and the speculative is as well, then the
+  // result is a speculative type which is exact and we can continue
+  // speculation further.
+  const TypePtr* this_spec = _speculative;
+  const TypePtr* other_spec = other->speculative();
+
+  if (!this_has_spec) {
+    this_spec = this;
+  }
+
+  if (!other_has_spec) {
+    other_spec = other;
+  }
+
+  return this_spec->meet(other_spec)->is_ptr();
+}
+
+/**
+ * dual of the inline depth for this type (used for speculation)
+ */
+int TypePtr::dual_inline_depth() const {
+  return -inline_depth();
+}
+
+/**
+ * meet of 2 inline depths (used for speculation)
+ *
+ * @param depth  depth to meet with
+ */
+int TypePtr::meet_inline_depth(int depth) const {
+  return MAX2(inline_depth(), depth);
+}
+
+/**
+ * Are the speculative parts of 2 types equal?
+ *
+ * @param other  type to compare this one to
+ */
+bool TypePtr::eq_speculative(const TypePtr* other) const {
+  if (_speculative == NULL || other->speculative() == NULL) {
+    return _speculative == other->speculative();
+  }
+
+  if (_speculative->base() != other->speculative()->base()) {
+    return false;
+  }
+
+  return _speculative->eq(other->speculative());
+}
+
+/**
+ * Hash of the speculative part of the type
+ */
+int TypePtr::hash_speculative() const {
+  if (_speculative == NULL) {
+    return 0;
+  }
+
+  return _speculative->hash();
+}
+
+/**
+ * add offset to the speculative part of the type
+ *
+ * @param offset  offset to add
+ */
+const TypePtr* TypePtr::add_offset_speculative(intptr_t offset) const {
+  if (_speculative == NULL) {
+    return NULL;
+  }
+  return _speculative->add_offset(offset)->is_ptr();
+}
+
+/**
+ * return exact klass from the speculative type if there's one
+ */
+ciKlass* TypePtr::speculative_type() const {
+  if (_speculative != NULL && _speculative->isa_oopptr()) {
+    const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr();
+    if (speculative->klass_is_exact()) {
+      return speculative->klass();
+    }
+  }
+  return NULL;
+}
+
+/**
+ * return true if speculative type may be null
+ */
+bool TypePtr::speculative_maybe_null() const {
+  if (_speculative != NULL) {
+    const TypePtr* speculative = _speculative->join(this)->is_ptr();
+    return speculative->maybe_null();
+  }
+  return true;
+}
+
+/**
+ * Same as TypePtr::speculative_type() but return the klass only if
+ * the speculative tells us is not null
+ */
+ciKlass* TypePtr::speculative_type_not_null() const {
+  if (speculative_maybe_null()) {
+    return NULL;
+  }
+  return speculative_type();
+}
+
+/**
+ * Check whether new profiling would improve speculative type
+ *
+ * @param   exact_kls    class from profiling
+ * @param   inline_depth inlining depth of profile point
+ *
+ * @return  true if type profile is valuable
+ */
+bool TypePtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const {
+  // no profiling?
+  if (exact_kls == NULL) {
+    return false;
+  }
+  // no speculative type or non exact speculative type?
+  if (speculative_type() == NULL) {
+    return true;
+  }
+  // If the node already has an exact speculative type keep it,
+  // unless it was provided by profiling that is at a deeper
+  // inlining level. Profiling at a higher inlining depth is
+  // expected to be less accurate.
+  if (_speculative->inline_depth() == InlineDepthBottom) {
+    return false;
+  }
+  assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison");
+  return inline_depth < _speculative->inline_depth();
+}
+
+/**
+ * Check whether new profiling would improve ptr (= tells us it is non
+ * null)
+ *
+ * @param   maybe_null true if profiling tells the ptr may be null
+ *
+ * @return  true if ptr profile is valuable
+ */
+bool TypePtr::would_improve_ptr(bool maybe_null) const {
+  // profiling doesn't tell us anything useful
+  if (maybe_null) {
+    return false;
+  }
+  // We already know this is not be null
+  if (!this->maybe_null()) {
+    return false;
+  }
+  // We already know the speculative type cannot be null
+  if (!speculative_maybe_null()) {
+    return false;
+  }
+  return true;
 }
 
 //------------------------------dump2------------------------------------------
@@ -2309,6 +2577,32 @@
   if( _offset == OffsetTop ) st->print("+top");
   else if( _offset == OffsetBot ) st->print("+bot");
   else if( _offset ) st->print("+%d", _offset);
+  dump_inline_depth(st);
+  dump_speculative(st);
+}
+
+/**
+ *dump the speculative part of the type
+ */
+void TypePtr::dump_speculative(outputStream *st) const {
+  if (_speculative != NULL) {
+    st->print(" (speculative=");
+    _speculative->dump_on(st);
+    st->print(")");
+  }
+}
+
+/**
+ *dump the inline depth of the type
+ */
+void TypePtr::dump_inline_depth(outputStream *st) const {
+  if (_inline_depth != InlineDepthBottom) {
+    if (_inline_depth == InlineDepthTop) {
+      st->print(" (inline_depth=InlineDepthTop)");
+    } else {
+      st->print(" (inline_depth=%d)", _inline_depth);
+    }
+  }
 }
 #endif
 
@@ -2399,7 +2693,7 @@
   case TypePtr::Null:
     if( _ptr == TypePtr::TopPTR ) return t;
     return TypeRawPtr::BOTTOM;
-  case TypePtr::NotNull: return TypePtr::make( AnyPtr, meet_ptr(TypePtr::NotNull), tp->meet_offset(0) );
+  case TypePtr::NotNull: return TypePtr::make(AnyPtr, meet_ptr(TypePtr::NotNull), tp->meet_offset(0), tp->speculative(), tp->inline_depth());
   case TypePtr::AnyNull:
     if( _ptr == TypePtr::Constant) return this;
     return make( meet_ptr(TypePtr::AnyNull) );
@@ -2463,16 +2757,15 @@
 const TypeOopPtr *TypeOopPtr::BOTTOM;
 
 //------------------------------TypeOopPtr-------------------------------------
-TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth)
-  : TypePtr(t, ptr, offset),
+TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset,
+                       int instance_id, const TypePtr* speculative, int inline_depth)
+  : TypePtr(t, ptr, offset, speculative, inline_depth),
     _const_oop(o), _klass(k),
     _klass_is_exact(xk),
     _is_ptr_to_narrowoop(false),
     _is_ptr_to_narrowklass(false),
     _is_ptr_to_boxed_value(false),
-    _instance_id(instance_id),
-    _speculative(speculative),
-    _inline_depth(inline_depth){
+    _instance_id(instance_id) {
   if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
       (offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
     _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
@@ -2538,8 +2831,8 @@
 }
 
 //------------------------------make-------------------------------------------
-const TypeOopPtr *TypeOopPtr::make(PTR ptr,
-                                   int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) {
+const TypeOopPtr *TypeOopPtr::make(PTR ptr, int offset, int instance_id,
+                                     const TypePtr* speculative, int inline_depth) {
   assert(ptr != Constant, "no constant generic pointers");
   ciKlass*  k = Compile::current()->env()->Object_klass();
   bool      xk = false;
@@ -2582,28 +2875,6 @@
     return TypeKlassPtr::make(xk? Constant: NotNull, k, 0);
 }
 
-const Type *TypeOopPtr::xmeet(const Type *t) const {
-  const Type* res = xmeet_helper(t);
-  if (res->isa_oopptr() == NULL) {
-    return res;
-  }
-
-  const TypeOopPtr* res_oopptr = res->is_oopptr();
-  if (res_oopptr->speculative() != NULL) {
-    // type->speculative() == NULL means that speculation is no better
-    // than type, i.e. type->speculative() == type. So there are 2
-    // ways to represent the fact that we have no useful speculative
-    // data and we should use a single one to be able to test for
-    // equality between types. Check whether type->speculative() ==
-    // type and set speculative to NULL if it is the case.
-    if (res_oopptr->remove_speculative() == res_oopptr->speculative()) {
-      return res_oopptr->remove_speculative();
-    }
-  }
-
-  return res;
-}
-
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
 const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
@@ -2641,19 +2912,20 @@
     const TypePtr *tp = t->is_ptr();
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
+    const TypePtr* speculative = xmeet_speculative(tp);
+    int depth = meet_inline_depth(tp->inline_depth());
     switch (tp->ptr()) {
     case Null:
-      if (ptr == Null)  return TypePtr::make(AnyPtr, ptr, offset);
+      if (ptr == Null)  return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
       // else fall through:
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      const TypeOopPtr* speculative = _speculative;
-      return make(ptr, offset, instance_id, speculative, _inline_depth);
+      return make(ptr, offset, instance_id, speculative, depth);
     }
     case BotPTR:
     case NotNull:
-      return TypePtr::make(AnyPtr, ptr, offset);
+      return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
     default: typerr(t);
     }
   }
@@ -2661,7 +2933,7 @@
   case OopPtr: {                 // Meeting to other OopPtrs
     const TypeOopPtr *tp = t->is_oopptr();
     int instance_id = meet_instance_id(tp->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tp);
+    const TypePtr* speculative = xmeet_speculative(tp);
     int depth = meet_inline_depth(tp->inline_depth());
     return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth);
   }
@@ -2859,9 +3131,7 @@
 bool TypeOopPtr::eq( const Type *t ) const {
   const TypeOopPtr *a = (const TypeOopPtr*)t;
   if (_klass_is_exact != a->_klass_is_exact ||
-      _instance_id != a->_instance_id ||
-      !eq_speculative(a) ||
-      _inline_depth != a->_inline_depth)  return false;
+      _instance_id != a->_instance_id)  return false;
   ciObject* one = const_oop();
   ciObject* two = a->const_oop();
   if (one == NULL || two == NULL) {
@@ -2878,8 +3148,6 @@
     (const_oop() ? const_oop()->hash() : 0) +
     _klass_is_exact +
     _instance_id +
-    hash_speculative() +
-    _inline_depth +
     TypePtr::hash();
 }
 
@@ -2903,27 +3171,6 @@
   dump_inline_depth(st);
   dump_speculative(st);
 }
-
-/**
- *dump the speculative part of the type
- */
-void TypeOopPtr::dump_speculative(outputStream *st) const {
-  if (_speculative != NULL) {
-    st->print(" (speculative=");
-    _speculative->dump_on(st);
-    st->print(")");
-  }
-}
-
-void TypeOopPtr::dump_inline_depth(outputStream *st) const {
-  if (_inline_depth != InlineDepthBottom) {
-    if (_inline_depth == InlineDepthTop) {
-      st->print(" (inline_depth=InlineDepthTop)");
-    } else {
-      st->print(" (inline_depth=%d)", _inline_depth);
-    }
-  }
-}
 #endif
 
 //------------------------------singleton--------------------------------------
@@ -2952,49 +3199,30 @@
 }
 
 /**
+ * Return same type but drop speculative part if we know we won't use
+ * it
+ */
+const Type* TypeOopPtr::cleanup_speculative() const {
+  // If the klass is exact and the ptr is not null then there's
+  // nothing that the speculative type can help us with
+  if (klass_is_exact() && !maybe_null()) {
+    return remove_speculative();
+  }
+  return TypePtr::cleanup_speculative();
+}
+
+/**
  * Return same type but with a different inline depth (used for speculation)
  *
  * @param depth  depth to meet with
  */
-const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const {
+const TypePtr* TypeOopPtr::with_inline_depth(int depth) const {
   if (!UseInlineDepthForSpeculativeTypes) {
     return this;
   }
   return make(_ptr, _offset, _instance_id, _speculative, depth);
 }
 
-/**
- * Check whether new profiling would improve speculative type
- *
- * @param   exact_kls    class from profiling
- * @param   inline_depth inlining depth of profile point
- *
- * @return  true if type profile is valuable
- */
-bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const {
-  // no way to improve an already exact type
-  if (klass_is_exact()) {
-    return false;
-  }
-  // no profiling?
-  if (exact_kls == NULL) {
-    return false;
-  }
-  // no speculative type or non exact speculative type?
-  if (speculative_type() == NULL) {
-    return true;
-  }
-  // If the node already has an exact speculative type keep it,
-  // unless it was provided by profiling that is at a deeper
-  // inlining level. Profiling at a higher inlining depth is
-  // expected to be less accurate.
-  if (_speculative->inline_depth() == InlineDepthBottom) {
-    return false;
-  }
-  assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison");
-  return inline_depth < _speculative->inline_depth();
-}
-
 //------------------------------meet_instance_id--------------------------------
 int TypeOopPtr::meet_instance_id( int instance_id ) const {
   // Either is 'TOP' instance?  Return the other instance!
@@ -3013,102 +3241,19 @@
 }
 
 /**
- * meet of the speculative parts of 2 types
+ * Check whether new profiling would improve speculative type
  *
- * @param other  type to meet with
+ * @param   exact_kls    class from profiling
+ * @param   inline_depth inlining depth of profile point
+ *
+ * @return  true if type profile is valuable
  */
-const TypeOopPtr* TypeOopPtr::xmeet_speculative(const TypeOopPtr* other) const {
-  bool this_has_spec = (_speculative != NULL);
-  bool other_has_spec = (other->speculative() != NULL);
-
-  if (!this_has_spec && !other_has_spec) {
-    return NULL;
-  }
-
-  // If we are at a point where control flow meets and one branch has
-  // a speculative type and the other has not, we meet the speculative
-  // type of one branch with the actual type of the other. If the
-  // actual type is exact and the speculative is as well, then the
-  // result is a speculative type which is exact and we can continue
-  // speculation further.
-  const TypeOopPtr* this_spec = _speculative;
-  const TypeOopPtr* other_spec = other->speculative();
-
-  if (!this_has_spec) {
-    this_spec = this;
-  }
-
-  if (!other_has_spec) {
-    other_spec = other;
-  }
-
-  return this_spec->meet_speculative(other_spec)->is_oopptr();
-}
-
-/**
- * dual of the speculative part of the type
- */
-const TypeOopPtr* TypeOopPtr::dual_speculative() const {
-  if (_speculative == NULL) {
-    return NULL;
-  }
-  return _speculative->dual()->is_oopptr();
-}
-
-/**
- * add offset to the speculative part of the type
- *
- * @param offset  offset to add
- */
-const TypeOopPtr* TypeOopPtr::add_offset_speculative(intptr_t offset) const {
-  if (_speculative == NULL) {
-    return NULL;
-  }
-  return _speculative->add_offset(offset)->is_oopptr();
-}
-
-/**
- * Are the speculative parts of 2 types equal?
- *
- * @param other  type to compare this one to
- */
-bool TypeOopPtr::eq_speculative(const TypeOopPtr* other) const {
-  if (_speculative == NULL || other->speculative() == NULL) {
-    return _speculative == other->speculative();
-  }
-
-  if (_speculative->base() != other->speculative()->base()) {
+bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const {
+  // no way to improve an already exact type
+  if (klass_is_exact()) {
     return false;
   }
-
-  return _speculative->eq(other->speculative());
-}
-
-/**
- * Hash of the speculative part of the type
- */
-int TypeOopPtr::hash_speculative() const {
-  if (_speculative == NULL) {
-    return 0;
-  }
-
-  return _speculative->hash();
-}
-
-/**
- * dual of the inline depth for this type (used for speculation)
- */
-int TypeOopPtr::dual_inline_depth() const {
-  return -inline_depth();
-}
-
-/**
- * meet of 2 inline depth (used for speculation)
- *
- * @param depth  depth to meet with
- */
-int TypeOopPtr::meet_inline_depth(int depth) const {
-  return MAX2(inline_depth(), depth);
+  return TypePtr::would_improve_type(exact_kls, inline_depth);
 }
 
 //=============================================================================
@@ -3120,8 +3265,10 @@
 const TypeInstPtr *TypeInstPtr::KLASS;
 
 //------------------------------TypeInstPtr-------------------------------------
-TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth)
-  : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) {
+TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off,
+                         int instance_id, const TypePtr* speculative, int inline_depth)
+  : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth),
+    _name(k->name()) {
    assert(k != NULL &&
           (k->is_loaded() || o == NULL),
           "cannot have constants with non-loaded klass");
@@ -3134,7 +3281,7 @@
                                      ciObject* o,
                                      int offset,
                                      int instance_id,
-                                     const TypeOopPtr* speculative,
+                                     const TypePtr* speculative,
                                      int inline_depth) {
   assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
   // Either const_oop() is NULL or else ptr is Constant
@@ -3217,7 +3364,7 @@
     int off = meet_offset(tinst->offset());
     PTR ptr = meet_ptr(tinst->ptr());
     int instance_id = meet_instance_id(tinst->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tinst);
+    const TypePtr* speculative = xmeet_speculative(tinst);
     int depth = meet_inline_depth(tinst->inline_depth());
 
     const TypeInstPtr *loaded    = is_loaded() ? this  : tinst;
@@ -3295,7 +3442,7 @@
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
     int instance_id = meet_instance_id(tp->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tp);
+    const TypePtr* speculative = xmeet_speculative(tp);
     int depth = meet_inline_depth(tp->inline_depth());
     switch (ptr) {
     case TopPTR:
@@ -3346,7 +3493,7 @@
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      const TypeOopPtr* speculative = xmeet_speculative(tp);
+      const TypePtr* speculative = xmeet_speculative(tp);
       int depth = meet_inline_depth(tp->inline_depth());
       return make(ptr, klass(), klass_is_exact(),
                   (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
@@ -3354,7 +3501,7 @@
     case NotNull:
     case BotPTR: {
       int instance_id = meet_instance_id(tp->instance_id());
-      const TypeOopPtr* speculative = xmeet_speculative(tp);
+      const TypePtr* speculative = xmeet_speculative(tp);
       int depth = meet_inline_depth(tp->inline_depth());
       return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
     }
@@ -3367,20 +3514,21 @@
     const TypePtr *tp = t->is_ptr();
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
+    int instance_id = meet_instance_id(InstanceTop);
+    const TypePtr* speculative = xmeet_speculative(tp);
+    int depth = meet_inline_depth(tp->inline_depth());
     switch (tp->ptr()) {
     case Null:
-      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset);
+      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
       // else fall through to AnyNull
     case TopPTR:
     case AnyNull: {
-      int instance_id = meet_instance_id(InstanceTop);
-      const TypeOopPtr* speculative = _speculative;
       return make(ptr, klass(), klass_is_exact(),
-                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, _inline_depth);
+                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
     }
     case NotNull:
     case BotPTR:
-      return TypePtr::make(AnyPtr, ptr, offset);
+      return TypePtr::make(AnyPtr, ptr, offset, speculative,depth);
     default: typerr(t);
     }
   }
@@ -3407,7 +3555,7 @@
     int off = meet_offset( tinst->offset() );
     PTR ptr = meet_ptr( tinst->ptr() );
     int instance_id = meet_instance_id(tinst->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tinst);
+    const TypePtr* speculative = xmeet_speculative(tinst);
     int depth = meet_inline_depth(tinst->inline_depth());
 
     // Check for easy case; klasses are equal (and perhaps not loaded!)
@@ -3563,6 +3711,7 @@
     // class hierarchy - which means we have to fall to at least NotNull.
     if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )
       ptr = NotNull;
+
     instance_id = InstanceBot;
 
     // Now we find the LCA of Java classes
@@ -3655,7 +3804,8 @@
 
 //------------------------------add_offset-------------------------------------
 const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id, add_offset_speculative(offset));
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset),
+              _instance_id, add_offset_speculative(offset), _inline_depth);
 }
 
 const Type *TypeInstPtr::remove_speculative() const {
@@ -3663,10 +3813,11 @@
     return this;
   }
   assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth");
-  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL, _inline_depth);
-}
-
-const TypeOopPtr *TypeInstPtr::with_inline_depth(int depth) const {
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset,
+              _instance_id, NULL, _inline_depth);
+}
+
+const TypePtr *TypeInstPtr::with_inline_depth(int depth) const {
   if (!UseInlineDepthForSpeculativeTypes) {
     return this;
   }
@@ -3687,7 +3838,8 @@
 const TypeAryPtr *TypeAryPtr::DOUBLES;
 
 //------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset,
+                                   int instance_id, const TypePtr* speculative, int inline_depth) {
   assert(!(k == NULL && ary->_elem->isa_int()),
          "integral arrays must be pre-equipped with a class");
   if (!xk)  xk = ary->ary_must_be_exact();
@@ -3697,7 +3849,9 @@
 }
 
 //------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth, bool is_autobox_cache) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset,
+                                   int instance_id, const TypePtr* speculative, int inline_depth,
+                                   bool is_autobox_cache) {
   assert(!(k == NULL && ary->_elem->isa_int()),
          "integral arrays must be pre-equipped with a class");
   assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
@@ -3807,7 +3961,7 @@
 
   const TypeAry* new_ary = TypeAry::make(elem, size(), stable);
 
-  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
+  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth);
 }
 
 //-----------------------------stable_dimension--------------------------------
@@ -3868,18 +4022,17 @@
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
     int depth = meet_inline_depth(tp->inline_depth());
+    const TypePtr* speculative = xmeet_speculative(tp);
     switch (tp->ptr()) {
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      const TypeOopPtr* speculative = xmeet_speculative(tp);
       return make(ptr, (ptr == Constant ? const_oop() : NULL),
                   _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth);
     }
     case BotPTR:
     case NotNull: {
       int instance_id = meet_instance_id(tp->instance_id());
-      const TypeOopPtr* speculative = xmeet_speculative(tp);
       return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
     }
     default: ShouldNotReachHere();
@@ -3891,20 +4044,21 @@
     const TypePtr *tp = t->is_ptr();
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
+    const TypePtr* speculative = xmeet_speculative(tp);
+    int depth = meet_inline_depth(tp->inline_depth());
     switch (tp->ptr()) {
     case TopPTR:
       return this;
     case BotPTR:
     case NotNull:
-      return TypePtr::make(AnyPtr, ptr, offset);
+      return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
     case Null:
-      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset);
+      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
       // else fall through to AnyNull
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      const TypeOopPtr* speculative = _speculative;
       return make(ptr, (ptr == Constant ? const_oop() : NULL),
-                  _ary, _klass, _klass_is_exact, offset, instance_id, speculative, _inline_depth);
+                  _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth);
     }
     default: ShouldNotReachHere();
     }
@@ -3920,7 +4074,7 @@
     const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary();
     PTR ptr = meet_ptr(tap->ptr());
     int instance_id = meet_instance_id(tap->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tap);
+    const TypePtr* speculative = xmeet_speculative(tap);
     int depth = meet_inline_depth(tap->inline_depth());
     ciKlass* lazy_klass = NULL;
     if (tary->_elem->isa_int()) {
@@ -3949,7 +4103,7 @@
            // 'this' is exact and super or unrelated:
            (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
       tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
-      return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot);
+      return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth);
     }
 
     bool xk = false;
@@ -4001,7 +4155,7 @@
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
     int instance_id = meet_instance_id(tp->instance_id());
-    const TypeOopPtr* speculative = xmeet_speculative(tp);
+    const TypePtr* speculative = xmeet_speculative(tp);
     int depth = meet_inline_depth(tp->inline_depth());
     switch (ptr) {
     case TopPTR:
@@ -4125,7 +4279,7 @@
   return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth);
 }
 
-const TypeOopPtr *TypeAryPtr::with_inline_depth(int depth) const {
+const TypePtr *TypeAryPtr::with_inline_depth(int depth) const {
   if (!UseInlineDepthForSpeculativeTypes) {
     return this;
   }
@@ -4250,6 +4404,13 @@
   return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
 }
 
+const Type* TypeNarrowOop::remove_speculative() const {
+  return make(_ptrtype->remove_speculative()->is_ptr());
+}
+
+const Type* TypeNarrowOop::cleanup_speculative() const {
+  return make(_ptrtype->cleanup_speculative()->is_ptr());
+}
 
 #ifndef PRODUCT
 void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
@@ -4376,15 +4537,15 @@
     PTR ptr = meet_ptr(tp->ptr());
     switch (tp->ptr()) {
     case Null:
-      if (ptr == Null)  return TypePtr::make(AnyPtr, ptr, offset);
+      if (ptr == Null)  return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
       // else fall through:
     case TopPTR:
     case AnyNull: {
-      return make(ptr, NULL, offset);
+      return make(ptr, _metadata, offset);
     }
     case BotPTR:
     case NotNull:
-      return TypePtr::make(AnyPtr, ptr, offset);
+      return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     default: typerr(t);
     }
   }
@@ -4698,12 +4859,12 @@
     case TopPTR:
       return this;
     case Null:
-      if( ptr == Null ) return TypePtr::make( AnyPtr, ptr, offset );
+      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     case AnyNull:
       return make( ptr, klass(), offset );
     case BotPTR:
     case NotNull:
-      return TypePtr::make(AnyPtr, ptr, offset);
+      return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
     default: typerr(t);
     }
   }
--- a/hotspot/src/share/vm/opto/type.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -224,7 +224,7 @@
   }
   // Variant that keeps the speculative part of the types
   const Type *meet_speculative(const Type *t) const {
-    return meet_helper(t, true);
+    return meet_helper(t, true)->cleanup_speculative();
   }
   // WIDEN: 'widens' for Ints and other range types
   virtual const Type *widen( const Type *old, const Type* limit ) const { return this; }
@@ -247,7 +247,7 @@
   }
   // Variant that keeps the speculative part of the types
   const Type *join_speculative(const Type *t) const {
-    return join_helper(t, true);
+    return join_helper(t, true)->cleanup_speculative();
   }
 
   // Modified version of JOIN adapted to the needs Node::Value.
@@ -259,7 +259,7 @@
   }
   // Variant that keeps the speculative part of the types
   const Type *filter_speculative(const Type *kills) const {
-    return filter_helper(kills, true);
+    return filter_helper(kills, true)->cleanup_speculative();
   }
 
 #ifdef ASSERT
@@ -414,15 +414,18 @@
                                         bool require_constant = false,
                                         bool is_autobox_cache = false);
 
-  // Speculative type. See TypeInstPtr
-  virtual const TypeOopPtr* speculative() const { return NULL; }
-  virtual ciKlass* speculative_type() const { return NULL; }
+  // Speculative type helper methods. See TypePtr.
+  virtual const TypePtr* speculative() const                                  { return NULL; }
+  virtual ciKlass* speculative_type() const                                   { return NULL; }
+  virtual ciKlass* speculative_type_not_null() const                          { return NULL; }
+  virtual bool speculative_maybe_null() const                                 { return true; }
+  virtual const Type* remove_speculative() const                              { return this; }
+  virtual const Type* cleanup_speculative() const                             { return this; }
+  virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { return exact_kls != NULL; }
+  virtual bool would_improve_ptr(bool maybe_null) const                       { return !maybe_null; }
   const Type* maybe_remove_speculative(bool include_speculative) const;
-  virtual const Type* remove_speculative() const { return this; }
 
-  virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const {
-    return exact_kls != NULL;
-  }
+  virtual bool maybe_null() const { return true; }
 
 private:
   // support arrays
@@ -679,6 +682,7 @@
   virtual const Type *xdual() const;    // Compute dual right now.
   bool ary_must_be_exact() const;  // true if arrays of such are never generic
   virtual const Type* remove_speculative() const;
+  virtual const Type* cleanup_speculative() const;
 #ifdef ASSERT
   // One type is interface, the other is oop
   virtual bool interface_vs_oop(const Type *t) const;
@@ -761,13 +765,48 @@
 public:
   enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
 protected:
-  TypePtr( TYPES t, PTR ptr, int offset ) : Type(t), _ptr(ptr), _offset(offset) {}
-  virtual bool eq( const Type *t ) const;
-  virtual int  hash() const;             // Type specific hashing
+  TypePtr(TYPES t, PTR ptr, int offset,
+          const TypePtr* speculative = NULL,
+          int inline_depth = InlineDepthBottom) :
+    Type(t), _ptr(ptr), _offset(offset), _speculative(speculative),
+    _inline_depth(inline_depth) {}
   static const PTR ptr_meet[lastPTR][lastPTR];
   static const PTR ptr_dual[lastPTR];
   static const char * const ptr_msg[lastPTR];
 
+  enum {
+    InlineDepthBottom = INT_MAX,
+    InlineDepthTop = -InlineDepthBottom
+  };
+
+  // Extra type information profiling gave us. We propagate it the
+  // same way the rest of the type info is propagated. If we want to
+  // use it, then we have to emit a guard: this part of the type is
+  // not something we know but something we speculate about the type.
+  const TypePtr*   _speculative;
+  // For speculative types, we record at what inlining depth the
+  // profiling point that provided the data is. We want to favor
+  // profile data coming from outer scopes which are likely better for
+  // the current compilation.
+  int _inline_depth;
+
+  // utility methods to work on the speculative part of the type
+  const TypePtr* dual_speculative() const;
+  const TypePtr* xmeet_speculative(const TypePtr* other) const;
+  bool eq_speculative(const TypePtr* other) const;
+  int hash_speculative() const;
+  const TypePtr* add_offset_speculative(intptr_t offset) const;
+#ifndef PRODUCT
+  void dump_speculative(outputStream *st) const;
+#endif
+
+  // utility methods to work on the inline depth of the type
+  int dual_inline_depth() const;
+  int meet_inline_depth(int depth) const;
+#ifndef PRODUCT
+  void dump_inline_depth(outputStream *st) const;
+#endif
+
 public:
   const int _offset;            // Offset into oop, with TOP & BOT
   const PTR _ptr;               // Pointer equivalence class
@@ -775,7 +814,9 @@
   const int offset() const { return _offset; }
   const PTR ptr()    const { return _ptr; }
 
-  static const TypePtr *make( TYPES t, PTR ptr, int offset );
+  static const TypePtr *make(TYPES t, PTR ptr, int offset,
+                             const TypePtr* speculative = NULL,
+                             int inline_depth = InlineDepthBottom);
 
   // Return a 'ptr' version of this type
   virtual const Type *cast_to_ptr_type(PTR ptr) const;
@@ -784,10 +825,13 @@
 
   int xadd_offset( intptr_t offset ) const;
   virtual const TypePtr *add_offset( intptr_t offset ) const;
+  virtual bool eq(const Type *t) const;
+  virtual int  hash() const;             // Type specific hashing
 
   virtual bool singleton(void) const;    // TRUE if type is a singleton
   virtual bool empty(void) const;        // TRUE if type is vacuous
   virtual const Type *xmeet( const Type *t ) const;
+  virtual const Type *xmeet_helper( const Type *t ) const;
   int meet_offset( int offset ) const;
   int dual_offset( ) const;
   virtual const Type *xdual() const;    // Compute dual right now.
@@ -802,6 +846,20 @@
     return ptr_dual[ ptr_meet[ ptr_dual[in_ptr] ] [ dual_ptr() ] ];
   }
 
+  // Speculative type helper methods.
+  virtual const TypePtr* speculative() const { return _speculative; }
+  int inline_depth() const                   { return _inline_depth; }
+  virtual ciKlass* speculative_type() const;
+  virtual ciKlass* speculative_type_not_null() const;
+  virtual bool speculative_maybe_null() const;
+  virtual const Type* remove_speculative() const;
+  virtual const Type* cleanup_speculative() const;
+  virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
+  virtual bool would_improve_ptr(bool maybe_null) const;
+  virtual const TypePtr* with_inline_depth(int depth) const;
+
+  virtual bool maybe_null() const { return meet_ptr(Null) == ptr(); }
+
   // Tests for relation to centerline of type lattice:
   static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); }
   static bool below_centerline(PTR ptr) { return (ptr >= NotNull); }
@@ -850,7 +908,8 @@
 // Some kind of oop (Java pointer), either klass or instance or array.
 class TypeOopPtr : public TypePtr {
 protected:
-  TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth);
+  TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id,
+             const TypePtr* speculative, int inline_depth);
 public:
   virtual bool eq( const Type *t ) const;
   virtual int  hash() const;             // Type specific hashing
@@ -861,10 +920,6 @@
   };
 protected:
 
-  enum {
-    InlineDepthBottom = INT_MAX,
-    InlineDepthTop = -InlineDepthBottom
-  };
   // Oop is NULL, unless this is a constant oop.
   ciObject*     _const_oop;   // Constant oop
   // If _klass is NULL, then so is _sig.  This is an unloaded klass.
@@ -880,38 +935,11 @@
   // This is the the node index of the allocation node creating this instance.
   int           _instance_id;
 
-  // Extra type information profiling gave us. We propagate it the
-  // same way the rest of the type info is propagated. If we want to
-  // use it, then we have to emit a guard: this part of the type is
-  // not something we know but something we speculate about the type.
-  const TypeOopPtr*   _speculative;
-  // For speculative types, we record at what inlining depth the
-  // profiling point that provided the data is. We want to favor
-  // profile data coming from outer scopes which are likely better for
-  // the current compilation.
-  int _inline_depth;
-
   static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
 
   int dual_instance_id() const;
   int meet_instance_id(int uid) const;
 
-  // utility methods to work on the speculative part of the type
-  const TypeOopPtr* dual_speculative() const;
-  const TypeOopPtr* xmeet_speculative(const TypeOopPtr* other) const;
-  bool eq_speculative(const TypeOopPtr* other) const;
-  int hash_speculative() const;
-  const TypeOopPtr* add_offset_speculative(intptr_t offset) const;
-#ifndef PRODUCT
-  void dump_speculative(outputStream *st) const;
-#endif
-  // utility methods to work on the inline depth of the type
-  int dual_inline_depth() const;
-  int meet_inline_depth(int depth) const;
-#ifndef PRODUCT
-  void dump_inline_depth(outputStream *st) const;
-#endif
-
   // Do not allow interface-vs.-noninterface joins to collapse to top.
   virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
 
@@ -941,7 +969,9 @@
                                               bool not_null_elements = false);
 
   // Make a generic (unclassed) pointer to an oop.
-  static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom);
+  static const TypeOopPtr* make(PTR ptr, int offset, int instance_id,
+                                const TypePtr* speculative = NULL,
+                                int inline_depth = InlineDepthBottom);
 
   ciObject* const_oop()    const { return _const_oop; }
   virtual ciKlass* klass() const { return _klass;     }
@@ -955,7 +985,6 @@
   bool is_known_instance()       const { return _instance_id > 0; }
   int  instance_id()             const { return _instance_id; }
   bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; }
-  virtual const TypeOopPtr* speculative() const { return _speculative; }
 
   virtual intptr_t get_con() const;
 
@@ -969,10 +998,13 @@
   const TypeKlassPtr* as_klass_type() const;
 
   virtual const TypePtr *add_offset( intptr_t offset ) const;
-  // Return same type without a speculative part
+
+  // Speculative type helper methods.
   virtual const Type* remove_speculative() const;
+  virtual const Type* cleanup_speculative() const;
+  virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
+  virtual const TypePtr* with_inline_depth(int depth) const;
 
-  virtual const Type *xmeet(const Type *t) const;
   virtual const Type *xdual() const;    // Compute dual right now.
   // the core of the computation of the meet for TypeOopPtr and for its subclasses
   virtual const Type *xmeet_helper(const Type *t) const;
@@ -982,29 +1014,14 @@
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
 #endif
-
-  // Return the speculative type if any
-  ciKlass* speculative_type() const {
-    if (_speculative != NULL) {
-      const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr();
-      if (speculative->klass_is_exact()) {
-        return speculative->klass();
-      }
-    }
-    return NULL;
-  }
-  int inline_depth() const {
-    return _inline_depth;
-  }
-  virtual const TypeOopPtr* with_inline_depth(int depth) const;
-  virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
 };
 
 //------------------------------TypeInstPtr------------------------------------
 // Class of Java object pointers, pointing either to non-array Java instances
 // or to a Klass* (including array klasses).
 class TypeInstPtr : public TypeOopPtr {
-  TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth);
+  TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id,
+              const TypePtr* speculative, int inline_depth);
   virtual bool eq( const Type *t ) const;
   virtual int  hash() const;             // Type specific hashing
 
@@ -1040,7 +1057,10 @@
   }
 
   // Make a pointer to an oop.
-  static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom);
+  static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset,
+                                 int instance_id = InstanceBot,
+                                 const TypePtr* speculative = NULL,
+                                 int inline_depth = InlineDepthBottom);
 
   /** Create constant type for a constant boxed value */
   const Type* get_const_boxed_value() const;
@@ -1057,9 +1077,10 @@
   virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
 
   virtual const TypePtr *add_offset( intptr_t offset ) const;
-  // Return same type without a speculative part
+
+  // Speculative type helper methods.
   virtual const Type* remove_speculative() const;
-  virtual const TypeOopPtr* with_inline_depth(int depth) const;
+  virtual const TypePtr* with_inline_depth(int depth) const;
 
   // the core of the computation of the meet of 2 types
   virtual const Type *xmeet_helper(const Type *t) const;
@@ -1081,7 +1102,8 @@
 // Class of Java array pointers
 class TypeAryPtr : public TypeOopPtr {
   TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
-              int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth)
+              int offset, int instance_id, bool is_autobox_cache,
+              const TypePtr* speculative, int inline_depth)
     : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth),
     _ary(ary),
     _is_autobox_cache(is_autobox_cache)
@@ -1120,9 +1142,15 @@
 
   bool is_autobox_cache() const { return _is_autobox_cache; }
 
-  static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom);
+  static const TypeAryPtr *make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset,
+                                int instance_id = InstanceBot,
+                                const TypePtr* speculative = NULL,
+                                int inline_depth = InlineDepthBottom);
   // Constant pointer to array
-  static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false);
+  static const TypeAryPtr *make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset,
+                                int instance_id = InstanceBot,
+                                const TypePtr* speculative = NULL,
+                                int inline_depth = InlineDepthBottom, bool is_autobox_cache = false);
 
   // Return a 'ptr' version of this type
   virtual const Type *cast_to_ptr_type(PTR ptr) const;
@@ -1136,9 +1164,10 @@
 
   virtual bool empty(void) const;        // TRUE if type is vacuous
   virtual const TypePtr *add_offset( intptr_t offset ) const;
-  // Return same type without a speculative part
+
+  // Speculative type helper methods.
   virtual const Type* remove_speculative() const;
-  virtual const TypeOopPtr* with_inline_depth(int depth) const;
+  virtual const TypePtr* with_inline_depth(int depth) const;
 
   // the core of the computation of the meet of 2 types
   virtual const Type *xmeet_helper(const Type *t) const;
@@ -1367,9 +1396,8 @@
   static const TypeNarrowOop *BOTTOM;
   static const TypeNarrowOop *NULL_PTR;
 
-  virtual const Type* remove_speculative() const {
-    return make(_ptrtype->remove_speculative()->is_ptr());
-  }
+  virtual const Type* remove_speculative() const;
+  virtual const Type* cleanup_speculative() const;
 
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
@@ -1716,6 +1744,7 @@
 #define ConvL2X(x)   (x)
 #define ConvX2I(x)   ConvL2I(x)
 #define ConvX2L(x)   (x)
+#define ConvX2UL(x)  (x)
 
 #else
 
@@ -1760,6 +1789,7 @@
 #define ConvL2X(x)   ConvL2I(x)
 #define ConvX2I(x)   (x)
 #define ConvX2L(x)   ConvI2L(x)
+#define ConvX2UL(x)  ConvI2UL(x)
 
 #endif
 
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -254,18 +254,24 @@
 # include "opto/block.hpp"
 # include "opto/c2_globals.hpp"
 # include "opto/callnode.hpp"
+# include "opto/castnode.hpp"
 # include "opto/cfgnode.hpp"
 # include "opto/compile.hpp"
 # include "opto/connode.hpp"
+# include "opto/convertnode.hpp"
+# include "opto/countbitsnode.hpp"
 # include "opto/idealGraphPrinter.hpp"
+# include "opto/intrinsicnode.hpp"
 # include "opto/loopnode.hpp"
 # include "opto/machnode.hpp"
 # include "opto/matcher.hpp"
 # include "opto/memnode.hpp"
+# include "opto/movenode.hpp"
 # include "opto/mulnode.hpp"
 # include "opto/multnode.hpp"
-# include "opto/node.hpp"
+# include "opto/narrowptrnode.hpp"
 # include "opto/opcodes.hpp"
+# include "opto/opaquenode.hpp"
 # include "opto/optoreg.hpp"
 # include "opto/phase.hpp"
 # include "opto/phaseX.hpp"
--- a/hotspot/src/share/vm/prims/jni.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -3878,10 +3878,12 @@
 void TestVirtualSpaceNode_test();
 void TestNewSize_test();
 void TestKlass_test();
+void TestBitMap_test();
 #if INCLUDE_ALL_GCS
 void TestOldFreeSpaceCalculation_test();
 void TestG1BiasedArray_test();
 void TestBufferingOopClosure_test();
+void TestCodeCacheRemSet_test();
 #endif
 
 void execute_internal_vm_tests() {
@@ -3902,6 +3904,7 @@
     run_unit_test(test_loggc_filename());
     run_unit_test(TestNewSize_test());
     run_unit_test(TestKlass_test());
+    run_unit_test(TestBitMap_test());
 #if INCLUDE_VM_STRUCTS
     run_unit_test(VMStructs::test());
 #endif
@@ -3910,6 +3913,7 @@
     run_unit_test(TestG1BiasedArray_test());
     run_unit_test(HeapRegionRemSet::test_prt());
     run_unit_test(TestBufferingOopClosure_test());
+    run_unit_test(TestCodeCacheRemSet_test());
 #endif
     tty->print_cr("All internal VM tests passed");
   }
@@ -3999,7 +4003,7 @@
     }
 
 #ifndef PRODUCT
-  #ifndef TARGET_OS_FAMILY_windows
+  #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
     #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
   #endif
 
--- a/hotspot/src/share/vm/prims/jvm.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1160,18 +1160,22 @@
 // and null permissions - which gives no permissions.
 oop create_dummy_access_control_context(TRAPS) {
   InstanceKlass* pd_klass = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass());
-  // new ProtectionDomain(null,null);
-  oop null_protection_domain = pd_klass->allocate_instance(CHECK_NULL);
-  Handle null_pd(THREAD, null_protection_domain);
+  Handle obj = pd_klass->allocate_instance_handle(CHECK_NULL);
+  // Call constructor ProtectionDomain(null, null);
+  JavaValue result(T_VOID);
+  JavaCalls::call_special(&result, obj, KlassHandle(THREAD, pd_klass),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::codesource_permissioncollection_signature(),
+                          Handle(), Handle(), CHECK_NULL);
 
   // new ProtectionDomain[] {pd};
   objArrayOop context = oopFactory::new_objArray(pd_klass, 1, CHECK_NULL);
-  context->obj_at_put(0, null_pd());
+  context->obj_at_put(0, obj());
 
   // new AccessControlContext(new ProtectionDomain[] {pd})
   objArrayHandle h_context(THREAD, context);
-  oop result = java_security_AccessControlContext::create(h_context, false, Handle(), CHECK_NULL);
-  return result;
+  oop acc = java_security_AccessControlContext::create(h_context, false, Handle(), CHECK_NULL);
+  return acc;
 }
 
 JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException))
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -1020,19 +1020,12 @@
     }
 
     if (owning_thread != NULL) {  // monitor is owned
-      if ((address)owning_thread == owner) {
-        // the owner field is the JavaThread *
-        assert(mon != NULL,
-          "must have heavyweight monitor with JavaThread * owner");
-        ret.entry_count = mon->recursions() + 1;
-      } else {
-        // The owner field is the Lock word on the JavaThread's stack
-        // so the recursions field is not valid. We have to count the
-        // number of recursive monitor entries the hard way. We pass
-        // a handle to survive any GCs along the way.
-        ResourceMark rm;
-        ret.entry_count = count_locked_objects(owning_thread, hobj);
-      }
+      // The recursions field of a monitor does not reflect recursions
+      // as lightweight locks before inflating the monitor are not included.
+      // We have to count the number of recursive monitor entries the hard way.
+      // We pass a handle to survive any GCs along the way.
+      ResourceMark rm;
+      ret.entry_count = count_locked_objects(owning_thread, hobj);
     }
     // implied else: entry_count == 0
   }
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -993,7 +993,9 @@
         // Before we call the JVMTI agent, we have to set the state in the
         // thread for which we are proxying.
         JavaThreadState prev_state = real_thread->thread_state();
-        assert(prev_state == _thread_blocked, "JavaThread should be at safepoint");
+        assert(((Thread *)real_thread)->is_ConcurrentGC_thread() ||
+               (real_thread->is_Java_thread() && prev_state == _thread_blocked),
+               "should be ConcurrentGCThread or JavaThread at safepoint");
         real_thread->set_thread_state(_thread_in_native);
 
         jvmtiExtensionEvent callback = env->ext_callbacks()->ClassUnload;
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -500,6 +500,54 @@
   c = *p;
 WB_END
 
+WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
+  const char* cpu_features = VM_Version::cpu_features();
+  ThreadToNativeFromVM ttn(thread);
+  jstring features_string = env->NewStringUTF(cpu_features);
+
+  CHECK_JNI_EXCEPTION_(env, NULL);
+
+  return features_string;
+WB_END
+
+
+WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
+  ResourceMark rm(THREAD);
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
+  jobjectArray result = NULL;
+  if (code == NULL) {
+    return result;
+  }
+  int insts_size = code->insts_size();
+
+  ThreadToNativeFromVM ttn(thread);
+  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  result = env->NewObjectArray(2, clazz, NULL);
+  if (result == NULL) {
+    return result;
+  }
+
+  clazz = env->FindClass(vmSymbols::java_lang_Integer()->as_C_string());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  jmethodID constructor = env->GetMethodID(clazz, vmSymbols::object_initializer_name()->as_C_string(), vmSymbols::int_void_signature()->as_C_string());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  jobject obj = env->NewObject(clazz, constructor, code->comp_level());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  env->SetObjectArrayElement(result, 0, obj);
+
+  jbyteArray insts = env->NewByteArray(insts_size);
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
+  env->SetObjectArrayElement(result, 1, insts);
+
+  return result;
+WB_END
+
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -611,6 +659,9 @@
   {CC"isInStringTable",   CC"(Ljava/lang/String;)Z",  (void*)&WB_IsInStringTable  },
   {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
   {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
+  {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
+  {CC"getNMethod",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
+                                                      (void*)&WB_GetNMethod         },
 };
 
 #undef CC
--- a/hotspot/src/share/vm/prims/whitebox.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -40,7 +40,6 @@
   do {                                                                 \
     JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
     if (HAS_PENDING_EXCEPTION) {                                       \
-      CLEAR_PENDING_EXCEPTION;                                         \
       return(value);                                                   \
     }                                                                  \
   } while (0)
@@ -49,7 +48,6 @@
   do {                                                                 \
     JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
     if (HAS_PENDING_EXCEPTION) {                                       \
-      CLEAR_PENDING_EXCEPTION;                                         \
       return;                                                          \
     }                                                                  \
   } while (0)
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -301,10 +301,12 @@
   { "UseMPSS",                       JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseStringCache",                JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseOldInlining",                JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "SafepointPollOffset",           JDK_Version::jdk(9), JDK_Version::jdk(10) },
 #ifdef PRODUCT
   { "DesiredMethodLimit",
                            JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
 #endif // PRODUCT
+  { "UseVMInterruptibleIO",          JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { NULL, JDK_Version(0), JDK_Version(0) }
 };
 
@@ -1185,11 +1187,6 @@
     FLAG_SET_DEFAULT(OldPLABSize, (intx)1024);
   }
 
-  // AlwaysTenure flag should make ParNew promote all at first collection.
-  // See CR 6362902.
-  if (AlwaysTenure) {
-    FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
-  }
   // When using compressed oops, we use local overflow stacks,
   // rather than using a global overflow list chained through
   // the klass word of the object's pre-image.
@@ -1906,24 +1903,22 @@
 // check if do gclog rotation
 // +UseGCLogFileRotation is a must,
 // no gc log rotation when log file not supplied or
-// NumberOfGCLogFiles is 0, or GCLogFileSize is 0
+// NumberOfGCLogFiles is 0
 void check_gclog_consistency() {
   if (UseGCLogFileRotation) {
-    if ((Arguments::gc_log_filename() == NULL) ||
-        (NumberOfGCLogFiles == 0)  ||
-        (GCLogFileSize == 0)) {
+    if ((Arguments::gc_log_filename() == NULL) || (NumberOfGCLogFiles == 0)) {
       jio_fprintf(defaultStream::output_stream(),
-                  "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files> -XX:GCLogFileSize=<num_of_size>[k|K|m|M|g|G]\n"
-                  "where num_of_file > 0 and num_of_size > 0\n"
+                  "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files>\n"
+                  "where num_of_file > 0\n"
                   "GC log rotation is turned off\n");
       UseGCLogFileRotation = false;
     }
   }
 
-  if (UseGCLogFileRotation && GCLogFileSize < 8*K) {
-        FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
-        jio_fprintf(defaultStream::output_stream(),
-                    "GCLogFileSize changed to minimum 8K\n");
+  if (UseGCLogFileRotation && (GCLogFileSize != 0) && (GCLogFileSize < 8*K)) {
+    FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
+    jio_fprintf(defaultStream::output_stream(),
+                "GCLogFileSize changed to minimum 8K\n");
   }
 }
 
@@ -2246,6 +2241,8 @@
                                        "G1ConcRSHotCardLimit");
     status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31,
                                        "G1ConcRSLogCacheSize");
+    status = status && verify_interval(StringDeduplicationAgeThreshold, 1, markOopDesc::max_age,
+                                       "StringDeduplicationAgeThreshold");
   }
   if (UseConcMarkSweepGC) {
     status = status && verify_min_value(CMSOldPLABNumRefills, 1, "CMSOldPLABNumRefills");
@@ -2340,10 +2337,8 @@
   status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement");
   status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement");
 
-  // the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp
-  // just for that, so hardcode here.
-  status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold");
-  status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold");
+  status = status && verify_interval(MaxTenuringThreshold, 0, markOopDesc::max_age + 1, "MaxTenuringThreshold");
+  status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "InitialTenuringThreshold");
   status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio");
   status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio");
 
@@ -3069,14 +3064,31 @@
       // but disallow DR and offlining (5008695).
       FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
 
+    // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
+    // and the last option wins.
     } else if (match_option(option, "-XX:+NeverTenure", &tail)) {
-      // The last option must always win.
+      FLAG_SET_CMDLINE(bool, NeverTenure, true);
       FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
-      FLAG_SET_CMDLINE(bool, NeverTenure, true);
+      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1);
     } else if (match_option(option, "-XX:+AlwaysTenure", &tail)) {
-      // The last option must always win.
       FLAG_SET_CMDLINE(bool, NeverTenure, false);
       FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
+      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
+    } else if (match_option(option, "-XX:MaxTenuringThreshold=", &tail)) {
+      uintx max_tenuring_thresh = 0;
+      if(!parse_uintx(tail, &max_tenuring_thresh, 0)) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "Invalid MaxTenuringThreshold: %s\n", option->optionString);
+      }
+      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, max_tenuring_thresh);
+
+      if (MaxTenuringThreshold == 0) {
+        FLAG_SET_CMDLINE(bool, NeverTenure, false);
+        FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
+      } else {
+        FLAG_SET_CMDLINE(bool, NeverTenure, false);
+        FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
+      }
     } else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) ||
                match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) {
       jio_fprintf(defaultStream::error_stream(),
@@ -3226,11 +3238,6 @@
         return JNI_EINVAL;
       }
       FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size);
-    } else if (match_option(option, "-XX:+UseVMInterruptibleIO", &tail)) {
-      // NOTE! In JDK 9, the UseVMInterruptibleIO flag will completely go
-      //       away and will cause VM initialization failures!
-      warning("-XX:+UseVMInterruptibleIO is obsolete and will be removed in a future release.");
-      FLAG_SET_CMDLINE(bool, UseVMInterruptibleIO, true);
 #if !INCLUDE_MANAGEMENT
     } else if (match_option(option, "-XX:+ManagementServer", &tail)) {
         jio_fprintf(defaultStream::error_stream(),
@@ -3781,9 +3788,6 @@
 #endif // CC_INTERP
 
 #ifdef COMPILER2
-  if (!UseBiasedLocking || EmitSync != 0) {
-    UseOptoBiasInlining = false;
-  }
   if (!EliminateLocks) {
     EliminateNestedLocks = false;
   }
@@ -3795,10 +3799,6 @@
     AlwaysIncrementalInline = false;
   }
 #endif
-  if (IncrementalInline && FLAG_IS_DEFAULT(MaxNodeLimit)) {
-    // incremental inlining: bump MaxNodeLimit
-    FLAG_SET_DEFAULT(MaxNodeLimit, (intx)75000);
-  }
   if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) {
     // nothing to use the profiling, turn if off
     FLAG_SET_DEFAULT(TypeProfileLevel, 0);
@@ -3844,6 +3844,11 @@
       UseBiasedLocking = false;
     }
   }
+#ifdef COMPILER2
+  if (!UseBiasedLocking || EmitSync != 0) {
+    UseOptoBiasInlining = false;
+  }
+#endif
 
   return JNI_OK;
 }
--- a/hotspot/src/share/vm/runtime/atomic.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/atomic.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -57,6 +57,7 @@
 
   // Atomically add to a location, return updated value
   inline static jint     add    (jint     add_value, volatile jint*     dest);
+  inline static size_t   add    (size_t   add_value, volatile size_t*   dest);
   inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
   inline static void*    add_ptr(intptr_t add_value, volatile void*     dest);
   // See comment above about using jlong atomics on 32-bit platforms
@@ -65,12 +66,14 @@
   // Atomically increment location
   inline static void inc    (volatile jint*     dest);
          static void inc    (volatile jshort*   dest);
+  inline static void inc    (volatile size_t*   dest);
   inline static void inc_ptr(volatile intptr_t* dest);
   inline static void inc_ptr(volatile void*     dest);
 
   // Atomically decrement a location
   inline static void dec    (volatile jint*     dest);
          static void dec    (volatile jshort*    dest);
+  inline static void dec    (volatile size_t*   dest);
   inline static void dec_ptr(volatile intptr_t* dest);
   inline static void dec_ptr(volatile void*     dest);
 
--- a/hotspot/src/share/vm/runtime/atomic.inline.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/atomic.inline.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -70,4 +70,21 @@
 # include "atomic_bsd_zero.inline.hpp"
 #endif
 
+// size_t casts...
+#if (SIZE_MAX != UINTPTR_MAX)
+#error size_t is not WORD_SIZE, interesting platform, but missing implementation here
+#endif
+
+inline size_t Atomic::add(size_t add_value, volatile size_t* dest) {
+  return (size_t) add_ptr((intptr_t) add_value, (volatile intptr_t*) dest);
+}
+
+inline void Atomic::inc(volatile size_t* dest) {
+  inc_ptr((volatile intptr_t*) dest);
+}
+
+inline void Atomic::dec(volatile size_t* dest) {
+  dec_ptr((volatile intptr_t*) dest);
+}
+
 #endif // SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1288,7 +1288,8 @@
     gather_statistics(reason, action, trap_bc);
 
     // Ensure that we can record deopt. history:
-    bool create_if_missing = ProfileTraps;
+    // Need MDO to record RTM code generation state.
+    bool create_if_missing = ProfileTraps RTM_OPT_ONLY( || UseRTMLocking );
 
     MethodData* trap_mdo =
       get_method_data(thread, trap_method, create_if_missing);
@@ -1569,6 +1570,17 @@
         if (tstate1 != tstate0)
           pdata->set_trap_state(tstate1);
       }
+
+#if INCLUDE_RTM_OPT
+      // Restart collecting RTM locking abort statistic if the method
+      // is recompiled for a reason other than RTM state change.
+      // Assume that in new recompiled code the statistic could be different,
+      // for example, due to different inlining.
+      if ((reason != Reason_rtm_state_change) && (trap_mdo != NULL) &&
+          UseRTMDeopt && (nm->rtm_state() != ProfileRTM)) {
+        trap_mdo->atomic_set_rtm_state(ProfileRTM);
+      }
+#endif
     }
 
     if (inc_recompile_count) {
@@ -1826,7 +1838,9 @@
   "age",
   "predicate",
   "loop_limit_check",
-  "speculate_class_check"
+  "speculate_class_check",
+  "speculate_null_check",
+  "rtm_state_change"
 };
 const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
   // Note:  Keep this in sync. with enum DeoptAction.
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -60,6 +60,8 @@
     Reason_predicate,             // compiler generated predicate failed
     Reason_loop_limit_check,      // compiler generated loop limits check failed
     Reason_speculate_class_check, // saw unexpected object class from type speculation
+    Reason_speculate_null_check,  // saw unexpected null from type speculation
+    Reason_rtm_state_change,      // rtm state change detected
     Reason_LIMIT,
     // Note:  Keep this enum in sync. with _trap_reason_name.
     Reason_RECORDED_LIMIT = Reason_bimorphic  // some are not recorded per bc
@@ -314,17 +316,27 @@
       return Reason_null_check;           // recorded per BCI as a null check
     else if (reason == Reason_speculate_class_check)
       return Reason_class_check;
+    else if (reason == Reason_speculate_null_check)
+      return Reason_null_check;
     else
       return Reason_none;
   }
 
   static bool reason_is_speculate(int reason) {
-    if (reason == Reason_speculate_class_check) {
+    if (reason == Reason_speculate_class_check || reason == Reason_speculate_null_check) {
       return true;
     }
     return false;
   }
 
+  static DeoptReason reason_null_check(bool speculative) {
+    return speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check;
+  }
+
+  static DeoptReason reason_class_check(bool speculative) {
+    return speculative ? Deoptimization::Reason_speculate_class_check : Deoptimization::Reason_class_check;
+  }
+
   static uint per_method_trap_limit(int reason) {
     return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit;
   }
--- a/hotspot/src/share/vm/runtime/frame.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -531,13 +531,16 @@
   // Number of elements on the interpreter expression stack
   // Callers should span by stackElementWords
   int element_size = Interpreter::stackElementWords;
+  size_t stack_size = 0;
   if (frame::interpreter_frame_expression_stack_direction() < 0) {
-    return (interpreter_frame_expression_stack() -
-            interpreter_frame_tos_address() + 1)/element_size;
+    stack_size = (interpreter_frame_expression_stack() -
+                  interpreter_frame_tos_address() + 1)/element_size;
   } else {
-    return (interpreter_frame_tos_address() -
-            interpreter_frame_expression_stack() + 1)/element_size;
+    stack_size = (interpreter_frame_tos_address() -
+                  interpreter_frame_expression_stack() + 1)/element_size;
   }
+  assert( stack_size <= (size_t)max_jint, "stack size too big");
+  return ((jint)stack_size);
 }
 
 
--- a/hotspot/src/share/vm/runtime/globals.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -2423,9 +2423,9 @@
           "Number of gclog files in rotation "                              \
           "(default: 0, no rotation)")                                      \
                                                                             \
-  product(uintx, GCLogFileSize, 0,                                          \
-          "GC log file size (default: 0 bytes, no rotation). "              \
-          "It requires UseGCLogFileRotation")                               \
+  product(uintx, GCLogFileSize, 8*K,                                        \
+          "GC log file size, requires UseGCLogFileRotation. "               \
+          "Set to 0 to only trigger rotation via jcmd")                     \
                                                                             \
   /* JVMTI heap profiling */                                                \
                                                                             \
@@ -2832,7 +2832,7 @@
           "number of method invocations/branches (expressed as % of "       \
           "CompileThreshold) before using the method's profile")            \
                                                                             \
-  develop(bool, PrintMethodData, false,                                     \
+  diagnostic(bool, PrintMethodData, false,                                  \
           "Print the results of +ProfileInterpreter at end of run")         \
                                                                             \
   develop(bool, VerifyDataPointer, trueInDebug,                             \
@@ -3840,17 +3840,28 @@
   experimental(uintx, SymbolTableSize, defaultSymbolTableSize,              \
           "Number of buckets in the JVM internal Symbol table")             \
                                                                             \
+  product(bool, UseStringDeduplication, false,                              \
+          "Use string deduplication")                                       \
+                                                                            \
+  product(bool, PrintStringDeduplicationStatistics, false,                  \
+          "Print string deduplication statistics")                          \
+                                                                            \
+  product(uintx, StringDeduplicationAgeThreshold, 3,                        \
+          "A string must reach this age (or be promoted to an old region) " \
+          "to be considered for deduplication")                             \
+                                                                            \
+  diagnostic(bool, StringDeduplicationResizeALot, false,                    \
+          "Force table resize every time the table is scanned")             \
+                                                                            \
+  diagnostic(bool, StringDeduplicationRehashALot, false,                    \
+          "Force table rehash every time the table is scanned")             \
+                                                                            \
   develop(bool, TraceDefaultMethods, false,                                 \
           "Trace the default method processing steps")                      \
                                                                             \
   develop(bool, VerifyGenericSignatures, false,                             \
           "Abort VM on erroneous or inconsistent generic signatures")       \
                                                                             \
-  product(bool, UseVMInterruptibleIO, false,                                \
-          "(Unstable, Solaris-specific) Thread interrupt before or with "   \
-          "EINTR for I/O operations results in OS_INTRPT. The default "     \
-          "value of this flag is true for JDK 6 and earlier")               \
-                                                                            \
   diagnostic(bool, WhiteBoxAPI, false,                                      \
           "Enable internal testing APIs")                                   \
                                                                             \
--- a/hotspot/src/share/vm/runtime/java.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -98,6 +98,59 @@
 #endif
 
 
+GrowableArray<Method*>* collected_profiled_methods;
+
+int compare_methods(Method** a, Method** b) {
+  // %%% there can be 32-bit overflow here
+  return ((*b)->invocation_count() + (*b)->compiled_invocation_count())
+       - ((*a)->invocation_count() + (*a)->compiled_invocation_count());
+}
+
+void collect_profiled_methods(Method* m) {
+  Thread* thread = Thread::current();
+  // This HandleMark prevents a huge amount of handles from being added
+  // to the metadata_handles() array on the thread.
+  HandleMark hm(thread);
+  methodHandle mh(thread, m);
+  if ((m->method_data() != NULL) &&
+      (PrintMethodData || CompilerOracle::should_print(mh))) {
+    collected_profiled_methods->push(m);
+  }
+}
+
+void print_method_profiling_data() {
+  if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) {
+    ResourceMark rm;
+    HandleMark hm;
+    collected_profiled_methods = new GrowableArray<Method*>(1024);
+    ClassLoaderDataGraph::methods_do(collect_profiled_methods);
+    collected_profiled_methods->sort(&compare_methods);
+
+    int count = collected_profiled_methods->length();
+    int total_size = 0;
+    if (count > 0) {
+      for (int index = 0; index < count; index++) {
+        Method* m = collected_profiled_methods->at(index);
+        ttyLocker ttyl;
+        tty->print_cr("------------------------------------------------------------------------");
+        m->print_invocation_count();
+        tty->print_cr("  mdo size: %d bytes", m->method_data()->size_in_bytes());
+        tty->cr();
+        // Dump data on parameters if any
+        if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
+          tty->fill_to(2);
+          m->method_data()->parameters_type_data()->print_data_on(tty);
+        }
+        m->print_codes();
+        total_size += m->method_data()->size_in_bytes();
+      }
+      tty->print_cr("------------------------------------------------------------------------");
+      tty->print_cr("Total MDO size: %d bytes", total_size);
+    }
+  }
+}
+
+
 #ifndef PRODUCT
 
 // Statistics printing (method invocation histogram)
@@ -111,26 +164,6 @@
 }
 
 
-GrowableArray<Method*>* collected_profiled_methods;
-
-void collect_profiled_methods(Method* m) {
-  Thread* thread = Thread::current();
-  // This HandleMark prevents a huge amount of handles from being added
-  // to the metadata_handles() array on the thread.
-  HandleMark hm(thread);
-  methodHandle mh(thread, m);
-  if ((m->method_data() != NULL) &&
-      (PrintMethodData || CompilerOracle::should_print(mh))) {
-    collected_profiled_methods->push(m);
-  }
-}
-
-
-int compare_methods(Method** a, Method** b) {
-  // %%% there can be 32-bit overflow here
-  return ((*b)->invocation_count() + (*b)->compiled_invocation_count())
-       - ((*a)->invocation_count() + (*a)->compiled_invocation_count());
-}
 
 
 void print_method_invocation_histogram() {
@@ -173,37 +206,6 @@
   SharedRuntime::print_call_statistics(comp_total);
 }
 
-void print_method_profiling_data() {
-  ResourceMark rm;
-  HandleMark hm;
-  collected_profiled_methods = new GrowableArray<Method*>(1024);
-  SystemDictionary::methods_do(collect_profiled_methods);
-  collected_profiled_methods->sort(&compare_methods);
-
-  int count = collected_profiled_methods->length();
-  int total_size = 0;
-  if (count > 0) {
-    for (int index = 0; index < count; index++) {
-      Method* m = collected_profiled_methods->at(index);
-      ttyLocker ttyl;
-      tty->print_cr("------------------------------------------------------------------------");
-      //m->print_name(tty);
-      m->print_invocation_count();
-      tty->print_cr("  mdo size: %d bytes", m->method_data()->size_in_bytes());
-      tty->cr();
-      // Dump data on parameters if any
-      if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
-        tty->fill_to(2);
-        m->method_data()->parameters_type_data()->print_data_on(tty);
-      }
-      m->print_codes();
-      total_size += m->method_data()->size_in_bytes();
-    }
-    tty->print_cr("------------------------------------------------------------------------");
-    tty->print_cr("Total MDO size: %d bytes", total_size);
-  }
-}
-
 void print_bytecode_count() {
   if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
     tty->print_cr("[BytecodeCounter::counter_value = %d]", BytecodeCounter::counter_value());
@@ -265,7 +267,7 @@
     os::print_statistics();
   }
 
-  if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics) {
+  if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) {
     OptoRuntime::print_named_counters();
   }
 
@@ -281,9 +283,9 @@
   if (CountCompiledCalls) {
     print_method_invocation_histogram();
   }
-  if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) {
-    print_method_profiling_data();
-  }
+
+  print_method_profiling_data();
+
   if (TimeCompiler) {
     COMPILER2_PRESENT(Compile::print_timers();)
   }
@@ -373,6 +375,10 @@
 
 void print_statistics() {
 
+  if (PrintMethodData) {
+    print_method_profiling_data();
+  }
+
   if (CITime) {
     CompileBroker::print_times();
   }
@@ -387,7 +393,7 @@
   }
 
 #ifdef COMPILER2
-  if (PrintPreciseBiasedLockingStatistics) {
+  if (PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) {
     OptoRuntime::print_named_counters();
   }
 #endif
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -58,6 +58,8 @@
 Mutex*   VtableStubs_lock             = NULL;
 Mutex*   SymbolTable_lock             = NULL;
 Mutex*   StringTable_lock             = NULL;
+Monitor* StringDedupQueue_lock        = NULL;
+Mutex*   StringDedupTable_lock        = NULL;
 Mutex*   CodeCache_lock               = NULL;
 Mutex*   MethodData_lock              = NULL;
 Mutex*   RetData_lock                 = NULL;
@@ -196,6 +198,9 @@
     def(MMUTracker_lock            , Mutex  , leaf     ,   true );
     def(HotCardCache_lock          , Mutex  , special  ,   true );
     def(EvacFailureStack_lock      , Mutex  , nonleaf  ,   true );
+
+    def(StringDedupQueue_lock      , Monitor, leaf,        true );
+    def(StringDedupTable_lock      , Mutex  , leaf,        true );
   }
   def(ParGCRareEvent_lock          , Mutex  , leaf     ,   true );
   def(DerivedPointerTableGC_lock   , Mutex,   leaf,        true );
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -66,6 +66,8 @@
 extern Mutex*   VtableStubs_lock;                // a lock on the VtableStubs
 extern Mutex*   SymbolTable_lock;                // a lock on the symbol table
 extern Mutex*   StringTable_lock;                // a lock on the interned string table
+extern Monitor* StringDedupQueue_lock;           // a lock on the string deduplication queue
+extern Mutex*   StringDedupTable_lock;           // a lock on the string deduplication table
 extern Mutex*   CodeCache_lock;                  // a lock on the CodeCache, rank is special, use MutexLockerEx
 extern Mutex*   MethodData_lock;                 // a lock on installation of method data
 extern Mutex*   RetData_lock;                    // a lock on installation of RetData inside method data
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/rtmLocking.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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_RUNTIME_RTMLOCKING_HPP
+#define SHARE_VM_RUNTIME_RTMLOCKING_HPP
+
+// Generate RTM (Restricted Transactional Memory) locking code for all inflated
+// locks when "UseRTMLocking" option is on with normal locking mechanism as fall back
+// handler.
+//
+// On abort/lock busy the lock will be retried a fixed number of times under RTM
+// as specified by "RTMRetryCount" option. The locks which abort too often
+// can be auto tuned or manually tuned.
+//
+// Auto-tuning can be done on an option like UseRTMDeopt and it will need abort
+// ratio calculation for each lock. The abort ratio will be calculated after
+// "RTMAbortThreshold" number of aborts is reached. The formulas are:
+//
+//     Aborted transactions = abort_count * 100
+//     All transactions = total_count *  RTMTotalCountIncrRate
+//
+//     Aborted transactions >= All transactions * RTMAbortRatio
+//
+// If "UseRTMDeopt" is on and the aborts ratio reaches "RTMAbortRatio"
+// the method containing the lock will be deoptimized and recompiled with
+// all locks as normal locks. If the abort ratio continues to remain low after
+// "RTMLockingThreshold" locks are attempted, then the method will be deoptimized
+// and recompiled with all locks as RTM locks without abort ratio calculation code.
+// The abort ratio calculation can be delayed by specifying flag
+// -XX:RTMLockingCalculationDelay in millisecond.
+//
+// For manual tuning the abort statistics for each lock needs to be provided
+// to the user on some JVM option like "PrintPreciseRTMLockingStatistics".
+// Based on the abort statistics users can create a .hotspot_compiler file
+// or use -XX:CompileCommand=option,class::method,NoRTMLockEliding
+// to specify for which methods to disable RTM locking.
+//
+// When UseRTMForStackLocks option is enabled along with UseRTMLocking option,
+// the RTM locking code is generated for stack locks too.
+// The retries, auto-tuning support and rtm locking statistics are all
+// supported for stack locks just like inflated locks.
+
+// RTM locking counters
+class RTMLockingCounters VALUE_OBJ_CLASS_SPEC {
+ private:
+  uintx _total_count; // Total RTM locks count
+  uintx _abort_count; // Total aborts count
+
+ public:
+  enum { ABORT_STATUS_LIMIT = 6 };
+  // Counters per RTM Abort Status. Incremented with +PrintPreciseRTMLockingStatistics
+  // RTM uses the EAX register to communicate abort status to software.
+  // Following an RTM abort the EAX register has the following definition.
+  //
+  //   EAX register bit position   Meaning
+  //     0     Set if abort caused by XABORT instruction.
+  //     1     If set, the transaction may succeed on a retry. This bit is always clear if bit 0 is set.
+  //     2     Set if another logical processor conflicted with a memory address that was part of the transaction that aborted.
+  //     3     Set if an internal buffer overflowed.
+  //     4     Set if a debug breakpoint was hit.
+  //     5     Set if an abort occurred during execution of a nested transaction.
+ private:
+  uintx _abortX_count[ABORT_STATUS_LIMIT];
+
+ public:
+  static uintx _calculation_flag;
+  static uintx* rtm_calculation_flag_addr() { return &_calculation_flag; }
+
+  static void init();
+
+  RTMLockingCounters() : _total_count(0), _abort_count(0) {
+    for (int i = 0; i < ABORT_STATUS_LIMIT; i++) {
+      _abortX_count[i] = 0;
+    }
+  }
+
+  uintx* total_count_addr()               { return &_total_count; }
+  uintx* abort_count_addr()               { return &_abort_count; }
+  uintx* abortX_count_addr()              { return &_abortX_count[0]; }
+
+  static int total_count_offset()         { return (int)offset_of(RTMLockingCounters, _total_count); }
+  static int abort_count_offset()         { return (int)offset_of(RTMLockingCounters, _abort_count); }
+  static int abortX_count_offset()        { return (int)offset_of(RTMLockingCounters, _abortX_count[0]); }
+
+
+  bool nonzero() {  return (_abort_count + _total_count) > 0; }
+
+  void print_on(outputStream* st);
+  void print() { print_on(tty); }
+};
+
+#endif // SHARE_VM_RUNTIME_RTMLOCKING_HPP
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -535,7 +535,7 @@
 
   // rotate log files?
   if (UseGCLogFileRotation) {
-    gclog_or_tty->rotate_log();
+    gclog_or_tty->rotate_log(false);
   }
 
   if (MemTracker::is_on()) {
--- a/hotspot/src/share/vm/runtime/task.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/task.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -105,7 +105,6 @@
   _counter(0), _interval((int) interval_time) {
   // Sanity check the interval time
   assert(_interval >= PeriodicTask::min_interval &&
-         _interval <= PeriodicTask::max_interval &&
          _interval %  PeriodicTask::interval_gran == 0,
               "improper PeriodicTask interval time");
 }
--- a/hotspot/src/share/vm/runtime/thread.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -107,6 +107,9 @@
 #include "opto/c2compiler.hpp"
 #include "opto/idealGraphPrinter.hpp"
 #endif
+#if INCLUDE_RTM_OPT
+#include "runtime/rtmLocking.hpp"
+#endif
 
 #ifdef DTRACE_ENABLED
 
@@ -211,7 +214,6 @@
   debug_only(_allow_allocation_count = 0;)
   NOT_PRODUCT(_allow_safepoint_count = 0;)
   NOT_PRODUCT(_skip_gcalot = false;)
-  CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
   _jvmti_env_iteration_count = 0;
   set_allocated_bytes(0);
   _vm_operation_started_count = 0;
@@ -3622,6 +3624,10 @@
 
   BiasedLocking::init();
 
+#if INCLUDE_RTM_OPT
+  RTMLockingCounters::init();
+#endif
+
   if (JDK_Version::current().post_vm_init_hook_enabled()) {
     call_postVMInitHook(THREAD);
     // The Java side of PostVMInitHook.run must deal with all
--- a/hotspot/src/share/vm/runtime/thread.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -249,9 +249,6 @@
   // Used by SkipGCALot class.
   NOT_PRODUCT(bool _skip_gcalot;)               // Should we elide gc-a-lot?
 
-  // Record when GC is locked out via the GC_locker mechanism
-  CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;)
-
   friend class No_Alloc_Verifier;
   friend class No_Safepoint_Verifier;
   friend class Pause_No_Safepoint_Verifier;
@@ -397,7 +394,6 @@
   void clear_unhandled_oops() {
     if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops();
   }
-  bool is_gc_locked_out() { return _gc_locked_out_count > 0; }
 #endif // CHECK_UNHANDLED_OOPS
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/runtime/unhandledOops.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/unhandledOops.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -113,9 +113,7 @@
 
 void UnhandledOops::clear_unhandled_oops() {
   assert (CheckUnhandledOops, "should only be called with checking option");
-  if (_thread->is_gc_locked_out()) {
-    return;
-  }
+
   for (int k = 0; k < _oop_list->length(); k++) {
     UnhandledOopEntry entry = _oop_list->at(k);
     // If an entry is on the unhandled oop list but isn't on the stack
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -171,15 +171,21 @@
 #include "opto/addnode.hpp"
 #include "opto/block.hpp"
 #include "opto/callnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/chaitin.hpp"
+#include "opto/convertnode.hpp"
 #include "opto/divnode.hpp"
+#include "opto/intrinsicnode.hpp"
 #include "opto/locknode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/mathexactnode.hpp"
 #include "opto/mulnode.hpp"
+#include "opto/movenode.hpp"
+#include "opto/narrowptrnode.hpp"
+#include "opto/opaquenode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/parse.hpp"
 #include "opto/regalloc.hpp"
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -96,6 +96,7 @@
   template(JFRCheckpoint)                         \
   template(Exit)                                  \
   template(LinuxDllLoad)                          \
+  template(RotateGCLog)                           \
 
 class VM_Operation: public CHeapObj<mtInternal> {
  public:
@@ -399,4 +400,15 @@
   void doit();
 };
 
+
+class VM_RotateGCLog: public VM_Operation {
+ private:
+  outputStream* _out;
+
+ public:
+  VM_RotateGCLog(outputStream* st) : _out(st) {}
+  VMOp_Type type() const { return VMOp_RotateGCLog; }
+  void doit() { gclog_or_tty->rotate_log(true, _out); }
+};
+
 #endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -55,6 +55,7 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
 #endif // INCLUDE_SERVICES
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
 
   // Enhanced JMX Agent Support
   // These commands won't be exported via the DiagnosticCommandMBean until an
@@ -659,3 +660,13 @@
   os::print_dll_info(output());
   output()->cr();
 }
+
+void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) {
+  if (UseGCLogFileRotation) {
+    VM_RotateGCLog rotateop(output());
+    VMThread::execute(&rotateop);
+  } else {
+    output()->print_cr("Target VM does not support GC log file rotation.");
+  }
+}
+
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -383,4 +383,21 @@
   virtual void execute(DCmdSource source, TRAPS);
 };
 
+class RotateGCLogDCmd : public DCmd {
+public:
+  RotateGCLogDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() { return "GC.rotate_log"; }
+  static const char* description() {
+    return "Force the GC log file to be rotated.";
+  }
+  static const char* impact() { return "Low"; }
+  virtual void execute(DCmdSource source, TRAPS);
+  static int num_arguments() { return 0; }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "control", NULL};
+    return p;
+  }
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/services/management.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/services/management.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -152,11 +152,14 @@
     // Load and initialize the sun.management.Agent class
     // invoke startAgent method to start the management server
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
-    Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(),
+    Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_management_Agent(),
                                                    loader,
                                                    Handle(),
-                                                   true,
-                                                   CHECK);
+                                                   THREAD);
+    if (k == NULL) {
+      vm_exit_during_initialization("Management agent initialization failure: "
+          "class sun.management.Agent not found.");
+    }
     instanceKlassHandle ik (THREAD, k);
 
     JavaValue result(T_VOID);
--- a/hotspot/src/share/vm/services/runtimeService.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/services/runtimeService.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -38,9 +38,6 @@
 PerfCounter*  RuntimeService::_total_safepoints = NULL;
 PerfCounter*  RuntimeService::_safepoint_time_ticks = NULL;
 PerfCounter*  RuntimeService::_application_time_ticks = NULL;
-PerfCounter*  RuntimeService::_thread_interrupt_signaled_count = NULL;
-PerfCounter*  RuntimeService::_interrupted_before_count = NULL;
-PerfCounter*  RuntimeService::_interrupted_during_count = NULL;
 
 void RuntimeService::init() {
   // Make sure the VM version is initialized
@@ -70,26 +67,6 @@
     PerfDataManager::create_constant(SUN_RT, "jvmVersion", PerfData::U_None,
                                      (jlong) Abstract_VM_Version::jvm_version(), CHECK);
 
-    // I/O interruption related counters
-
-    // thread signaling via os::interrupt()
-
-    _thread_interrupt_signaled_count =
-                PerfDataManager::create_counter(SUN_RT,
-                 "threadInterruptSignaled", PerfData::U_Events, CHECK);
-
-    // OS_INTRPT via "check before" in _INTERRUPTIBLE
-
-    _interrupted_before_count =
-                PerfDataManager::create_counter(SUN_RT, "interruptedBeforeIO",
-                                                PerfData::U_Events, CHECK);
-
-    // OS_INTRPT via "check during" in _INTERRUPTIBLE
-
-    _interrupted_during_count =
-                PerfDataManager::create_counter(SUN_RT, "interruptedDuringIO",
-                                                PerfData::U_Events, CHECK);
-
     // The capabilities counter is a binary representation of the VM capabilities in string.
     // This string respresentation simplifies the implementation of the client side
     // to parse the value.
@@ -181,22 +158,4 @@
     Management::ticks_to_ms(_application_time_ticks->get_value()) : -1;
 }
 
-void RuntimeService::record_interrupted_before_count() {
-  if (UsePerfData) {
-    _interrupted_before_count->inc();
-  }
-}
-
-void RuntimeService::record_interrupted_during_count() {
-  if (UsePerfData) {
-    _interrupted_during_count->inc();
-  }
-}
-
-void RuntimeService::record_thread_interrupt_signaled_count() {
-  if (UsePerfData) {
-    _thread_interrupt_signaled_count->inc();
-  }
-}
-
 #endif // INCLUDE_MANAGEMENT
--- a/hotspot/src/share/vm/services/runtimeService.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/services/runtimeService.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -34,9 +34,6 @@
   static PerfCounter* _total_safepoints;
   static PerfCounter* _safepoint_time_ticks;   // Accumulated time at safepoints
   static PerfCounter* _application_time_ticks; // Accumulated time not at safepoints
-  static PerfCounter* _thread_interrupt_signaled_count;// os:interrupt thr_kill
-  static PerfCounter* _interrupted_before_count;  // _INTERRUPTIBLE OS_INTRPT
-  static PerfCounter* _interrupted_during_count;  // _INTERRUPTIBLE OS_INTRPT
 
   static TimeStamp _safepoint_timer;
   static TimeStamp _app_timer;
@@ -58,10 +55,6 @@
   static void record_safepoint_end() NOT_MANAGEMENT_RETURN;
   static void record_application_start() NOT_MANAGEMENT_RETURN;
 
-  // interruption events
-  static void record_interrupted_before_count() NOT_MANAGEMENT_RETURN;
-  static void record_interrupted_during_count() NOT_MANAGEMENT_RETURN;
-  static void record_thread_interrupt_signaled_count() NOT_MANAGEMENT_RETURN;
 };
 
 #endif // SHARE_VM_SERVICES_RUNTIMESERVICE_HPP
--- a/hotspot/src/share/vm/trace/trace.xml	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/trace/trace.xml	Wed Jul 05 19:35:40 2017 +0200
@@ -193,11 +193,48 @@
     <event id="MetaspaceSummary" path="vm/gc/heap/metaspace_summary" label="Metaspace Summary" is_instant="true">
       <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
       <value type="GCWHEN" field="when" label="When" />
+      <value type="BYTES64" field="gcThreshold" label="GC Threshold" />
       <structvalue type="MetaspaceSizes" field="metaspace" label="Total"/>
       <structvalue type="MetaspaceSizes" field="dataSpace" label="Data"/>
       <structvalue type="MetaspaceSizes" field="classSpace" label="Class"/>
     </event>
 
+    <event id="MetaspaceGCThreshold" path="vm/gc/metaspace/gc_threshold" label="Metaspace GC Threshold" is_instant="true">
+      <value type="BYTES64" field="oldValue" label="Old Value" />
+      <value type="BYTES64" field="newValue" label="New Value" />
+      <value type="GCTHRESHOLDUPDATER" field="updater" label="Updater" />
+    </event>
+
+    <event id="MetaspaceAllocationFailure" path="vm/gc/metaspace/allocation_failure" label="Metaspace Allocation Failure" is_instant="true" has_stacktrace="true">
+      <value type="CLASS" field="classLoader" label="Class Loader" />
+      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+      <value type="BYTES64" field="size" label="Size" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+    </event>
+
+    <event id="MetaspaceOOM" path="vm/gc/metaspace/out_of_memory" label="Metaspace Out of Memory" is_instant="true" has_stacktrace="true">
+      <value type="CLASS" field="classLoader" label="Class Loader" />
+      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+      <value type="BYTES64" field="size" label="Size" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+    </event>
+
+    <event id="MetaspaceChunkFreeListSummary" path="vm/gc/metaspace/chunk_free_list_summary" label="Metaspace Chunk Free List Summary" is_instant="true">
+      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+      <value type="GCWHEN" field="when" label="When" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="ULONG" field="specializedChunks" label="Specialized Chunks" />
+      <value type="BYTES64" field="specializedChunksTotalSize" label="Specialized Chunks Total Size" />
+      <value type="ULONG" field="smallChunks" label="Small Chunks" />
+      <value type="BYTES64" field="smallChunksTotalSize" label="Small Chunks Total Size" />
+      <value type="ULONG" field="mediumChunks" label="Medium Chunks" />
+      <value type="BYTES64" field="mediumChunksTotalSize" label="Medium Chunks Total Size" />
+      <value type="ULONG" field="humongousChunks" label="Humongous Chunks" />
+      <value type="BYTES64" field="humongousChunksTotalSize" label="Humongous Chunks Total Size" />
+    </event>
+
     <event id="PSHeapSummary" path="vm/gc/heap/ps_summary" label="Parallel Scavenge Heap Summary" is_instant="true">
       <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
       <value type="GCWHEN" field="when" label="When" />
--- a/hotspot/src/share/vm/trace/tracetypes.xml	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/trace/tracetypes.xml	Wed Jul 05 19:35:40 2017 +0200
@@ -130,11 +130,26 @@
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="GCThresholdUpdater" hr_name="GC Treshold Updater"
+                  type="U1" jvm_type="GCTHRESHOLDUPDATER">
+      <value type="UTF8" field="updater" label="updater" />
+    </content_type>
+
     <content_type id="ReferenceType" hr_name="Reference Type"
                   type="U1" jvm_type="REFERENCETYPE">
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="MetadataType" hr_name="Metadata Type"
+                  type="U1" jvm_type="METADATATYPE">
+      <value type="UTF8" field="type" label="type" />
+    </content_type>
+
+    <content_type id="MetaspaceObjectType" hr_name="Metaspace Object Type"
+                  type="U1" jvm_type="METASPACEOBJTYPE">
+      <value type="UTF8" field="type" label="type" />
+    </content_type>
+
     <content_type id="NARROW_OOP_MODE" hr_name="Narrow Oop Mode"
                   type="U1" jvm_type="NARROWOOPMODE">
       <value type="UTF8" field="mode" label="mode" />
@@ -324,10 +339,22 @@
     <primary_type symbol="G1YCTYPE" datatype="U1" contenttype="G1YCTYPE"
                   type="u1" sizeop="sizeof(u1)" />
 
+    <!-- GCTHRESHOLDUPDATER -->
+    <primary_type symbol="GCTHRESHOLDUPDATER" datatype="U1" contenttype="GCTHRESHOLDUPDATER"
+                  type="u1" sizeop="sizeof(u1)" />
+
     <!-- REFERENCETYPE -->
     <primary_type symbol="REFERENCETYPE" datatype="U1"
                   contenttype="REFERENCETYPE" type="u1" sizeop="sizeof(u1)" />
 
+    <!-- METADATATYPE -->
+    <primary_type symbol="METADATATYPE" datatype="U1"
+                  contenttype="METADATATYPE" type="u1" sizeop="sizeof(u1)" />
+
+    <!-- METADATAOBJTYPE -->
+    <primary_type symbol="METASPACEOBJTYPE" datatype="U1"
+                  contenttype="METASPACEOBJTYPE" type="u1" sizeop="sizeof(u1)" />
+
     <!-- NARROWOOPMODE -->
     <primary_type symbol="NARROWOOPMODE" datatype="U1"
                   contenttype="NARROWOOPMODE" type="u1" sizeop="sizeof(u1)" />
--- a/hotspot/src/share/vm/utilities/bitMap.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
 #include "utilities/bitMap.inline.hpp"
 #include "utilities/copy.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -67,16 +68,14 @@
   idx_t new_size_in_words = size_in_words();
   if (in_resource_area) {
     _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
+    Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
+                         MIN2(old_size_in_words, new_size_in_words));
   } else {
-    if (old_map != NULL) {
-      _map_allocator.free();
-    }
-    _map = _map_allocator.allocate(new_size_in_words);
+    _map = _map_allocator.reallocate(new_size_in_words);
   }
-  Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
-                       MIN2(old_size_in_words, new_size_in_words));
+
   if (new_size_in_words > old_size_in_words) {
-    clear_range_of_words(old_size_in_words, size_in_words());
+    clear_range_of_words(old_size_in_words, new_size_in_words);
   }
 }
 
@@ -536,6 +535,83 @@
   tty->cr();
 }
 
+class TestBitMap : public AllStatic {
+  const static BitMap::idx_t BITMAP_SIZE = 1024;
+  static void fillBitMap(BitMap& map) {
+    map.set_bit(1);
+    map.set_bit(3);
+    map.set_bit(17);
+    map.set_bit(512);
+  }
+
+  static void testResize(bool in_resource_area) {
+    {
+      BitMap map(0, in_resource_area);
+      map.resize(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map);
+
+      BitMap map2(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map2);
+      assert(map.is_same(map2), "could be");
+    }
+
+    {
+      BitMap map(128, in_resource_area);
+      map.resize(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map);
+
+      BitMap map2(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map2);
+      assert(map.is_same(map2), "could be");
+    }
+
+    {
+      BitMap map(BITMAP_SIZE, in_resource_area);
+      map.resize(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map);
+
+      BitMap map2(BITMAP_SIZE, in_resource_area);
+      fillBitMap(map2);
+      assert(map.is_same(map2), "could be");
+    }
+  }
+
+  static void testResizeResource() {
+    ResourceMark rm;
+    testResize(true);
+  }
+
+  static void testResizeNonResource() {
+    const uintx bitmap_bytes = BITMAP_SIZE / BitsPerByte;
+
+    // Test the default behavior
+    testResize(false);
+
+    {
+      // Make sure that AllocatorMallocLimit is larger than our allocation request
+      // forcing it to call standard malloc()
+      UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
+      testResize(false);
+    }
+    {
+      // Make sure that AllocatorMallocLimit is smaller than our allocation request
+      // forcing it to call mmap() (or equivalent)
+      UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
+      testResize(false);
+    }
+  }
+
+ public:
+  static void test() {
+    testResizeResource();
+    testResizeNonResource();
+  }
+
+};
+
+void TestBitMap_test() {
+  TestBitMap::test();
+}
 #endif
 
 
--- a/hotspot/src/share/vm/utilities/debug.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -243,7 +243,6 @@
 
 // out of shared space reporting
 enum SharedSpaceType {
-  SharedPermGen,
   SharedReadOnly,
   SharedReadWrite,
   SharedMiscData
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -373,6 +373,21 @@
 
 // Machine dependent stuff
 
+#if defined(X86) && defined(COMPILER2) && !defined(JAVASE_EMBEDDED)
+// Include Restricted Transactional Memory lock eliding optimization
+#define INCLUDE_RTM_OPT 1
+#define RTM_OPT_ONLY(code) code
+#else
+#define INCLUDE_RTM_OPT 0
+#define RTM_OPT_ONLY(code)
+#endif
+// States of Restricted Transactional Memory usage.
+enum RTMState {
+  NoRTM      = 0x2, // Don't use RTM
+  UseRTM     = 0x1, // Use RTM
+  ProfileRTM = 0x0  // Use RTM with abort ratio calculation
+};
+
 #ifdef TARGET_ARCH_x86
 # include "globalDefinitions_x86.hpp"
 #endif
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Wed Jul 05 19:35:40 2017 +0200
@@ -662,13 +662,13 @@
 // write to gc log file at safepoint. If in future, changes made for mutator threads or
 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
 // must be synchronized.
-void gcLogFileStream::rotate_log() {
+void gcLogFileStream::rotate_log(bool force, outputStream* out) {
   char time_msg[FILENAMEBUFLEN];
   char time_str[EXTRACHARLEN];
   char current_file_name[FILENAMEBUFLEN];
   char renamed_file_name[FILENAMEBUFLEN];
 
-  if (_bytes_written < (jlong)GCLogFileSize) {
+  if (!should_rotate(force)) {
     return;
   }
 
@@ -685,6 +685,11 @@
     jio_snprintf(time_msg, sizeof(time_msg), "File  %s rotated at %s\n",
                  _file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
     write(time_msg, strlen(time_msg));
+
+    if (out != NULL) {
+      out->print(time_msg);
+    }
+
     dump_loggc_header();
     return;
   }
@@ -706,12 +711,18 @@
                  _file_name, _cur_file_num);
     jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
                  _file_name, _cur_file_num);
-    jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the"
-                           " maximum size. Saved as %s\n",
-                           os::local_time_string((char *)time_str, sizeof(time_str)),
-                           renamed_file_name);
+
+    const char* msg = force ? "GC log rotation request has been received."
+                            : "GC log file has reached the maximum size.";
+    jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
+                     os::local_time_string((char *)time_str, sizeof(time_str)),
+                                                         msg, renamed_file_name);
     write(time_msg, strlen(time_msg));
 
+    if (out != NULL) {
+      out->print(time_msg);
+    }
+
     fclose(_file);
     _file = NULL;
 
@@ -752,6 +763,11 @@
                            os::local_time_string((char *)time_str, sizeof(time_str)),
                            current_file_name);
     write(time_msg, strlen(time_msg));
+
+    if (out != NULL) {
+      out->print(time_msg);
+    }
+
     dump_loggc_header();
     // remove the existing file
     if (access(current_file_name, F_OK) == 0) {
--- a/hotspot/src/share/vm/utilities/ostream.hpp	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.hpp	Wed Jul 05 19:35:40 2017 +0200
@@ -115,7 +115,7 @@
    // flushing
    virtual void flush() {}
    virtual void write(const char* str, size_t len) = 0;
-   virtual void rotate_log() {} // GC log rotation
+   virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation
    virtual ~outputStream() {}   // close properly on deletion
 
    void dec_cr() { dec(); cr(); }
@@ -240,8 +240,14 @@
   gcLogFileStream(const char* file_name);
   ~gcLogFileStream();
   virtual void write(const char* c, size_t len);
-  virtual void rotate_log();
+  virtual void rotate_log(bool force, outputStream* out = NULL);
   void dump_loggc_header();
+
+  /* If "force" sets true, force log file rotation from outside JVM */
+  bool should_rotate(bool force) {
+    return force ||
+             ((GCLogFileSize != 0) && ((uintx)_bytes_written >= GCLogFileSize));
+  }
 };
 
 #ifndef PRODUCT
--- a/hotspot/test/TEST.groups	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/TEST.groups	Wed Jul 05 19:35:40 2017 +0200
@@ -129,6 +129,8 @@
   gc/g1/TestHumongousAllocInitialMark.java \
   gc/arguments/TestG1HeapRegionSize.java \
   gc/metaspace/TestMetaspaceMemoryPool.java \
+  gc/arguments/TestDynMinHeapFreeRatio.java \
+  gc/arguments/TestDynMaxHeapFreeRatio.java \
   runtime/InternalApi/ThreadCpuTimesDeadlock.java \
   serviceability/threads/TestFalseDeadLock.java \
   compiler/tiered/NonTieredLevelsTest.java \
--- a/hotspot/test/compiler/6792161/Test6792161.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/compiler/6792161/Test6792161.java	Wed Jul 05 19:35:40 2017 +0200
@@ -27,7 +27,7 @@
  * @bug 6792161
  * @summary assert("No dead instructions after post-alloc")
  *
- * @run main/othervm/timeout=300 -Xcomp -XX:MaxInlineSize=120 Test6792161
+ * @run main/othervm/timeout=600 -Xcomp -XX:MaxInlineSize=120 Test6792161
  */
 
 import java.lang.reflect.Constructor;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import com.oracle.java.testlibrary.cli.*;
+
+/**
+ * Base class for all X86 bit manipulation related command line options.
+ */
+public abstract class BMICommandLineOptionTestBase
+              extends CPUSpecificCommandLineOptionTest {
+
+    public static final String LZCNT_WARNING =
+        "lzcnt instruction is not available on this CPU";
+    public static final String TZCNT_WARNING =
+        "tzcnt instruction is not available on this CPU";
+    public static final String BMI1_WARNING =
+        "BMI1 instructions are not available on this CPU";
+
+    protected final String optionName;
+    protected final String warningMessage;
+    protected final String errorMessage;
+
+    /**
+     * Construct new test on {@code optionName} option.
+     *
+     * @param optionName Name of the option to be tested
+     *                   without -XX:[+-] prefix.
+     * @param warningMessage Message that can occur in VM output
+     *                       if CPU on test box does not support
+     *                       features required by the option.
+     * @param supportedCPUFeatures CPU features requires by the option,
+     *                             that should be supported on test box.
+     * @param unsupportedCPUFeatures CPU features requires by the option,
+     *                               that should not be supported on test box.
+     */
+    public BMICommandLineOptionTestBase(String optionName,
+                                        String warningMessage,
+                                        String supportedCPUFeatures[],
+                                        String unsupportedCPUFeatures[]) {
+        super(".*", supportedCPUFeatures, unsupportedCPUFeatures);
+            this.optionName = optionName;
+            this.warningMessage = warningMessage;
+            this.errorMessage = CommandLineOptionTest.
+                UNRECOGNIZED_OPTION_ERROR_FORMAT.format(optionName);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.*;
+
+/**
+ * Test on bit manipulation related command line options,
+ * that should be executed on CPU that supports all required
+ * features.
+ */
+public class BMISupportedCPUTest extends BMICommandLineOptionTestBase {
+
+    /**
+     * Construct new test on {@code optionName} option.
+     *
+     * @param optionName Name of the option to be tested
+     *                   without -XX:[+-] prefix.
+     * @param warningMessage Message that can occur in VM output
+     *                       if CPU on test box does not support
+     *                       features required by the option.
+     * @param cpuFeatures CPU features requires by the option.
+     */
+    public BMISupportedCPUTest(String optionName,
+                               String warningMessage,
+                               String... cpuFeatures) {
+        super(optionName, warningMessage, cpuFeatures, null);
+    }
+
+    @Override
+    public void runTestCases() throws Throwable {
+        // verify that VM will succesfully start up whithout warnings
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:+" + optionName,
+                             null, new String[] { warningMessage },
+                             ExitCode.OK);
+
+        // verify that VM will succesfully start up whithout warnings
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:-" + optionName,
+                             null, new String[] { warningMessage },
+                             ExitCode.OK);
+
+        // verify that on appropriate CPU option in on by default
+        CommandLineOptionTest.verifyOptionValue(optionName, "true");
+
+        // verify that option could be explicitly turned off
+        CommandLineOptionTest.verifyOptionValue(optionName, "false",
+                                                "-XX:-" + optionName);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.*;
+
+/**
+ * Test on bit manipulation related command line options,
+ * that should be executed on CPU that does not support
+ * required features.
+ */
+public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase {
+
+    /**
+     * Construct new test on {@code optionName} option.
+     *
+     * @param optionName Name of the option to be tested
+     *                   without -XX:[+-] prefix.
+     * @param warningMessage Message that can occur in VM output
+     *                       if CPU on test box does not support
+     *                       features required by the option.
+     * @param cpuFeatures CPU features requires by the option.
+     */
+    public BMIUnsupportedCPUTest(String optionName,
+                                 String warningMessage,
+                                 String... cpuFeatures) {
+        super(optionName, warningMessage, null, cpuFeatures);
+    }
+
+    @Override
+    public void runTestCases() throws Throwable {
+        if (Platform.isX86() || Platform.isX64()) {
+            unsupportedX86CPUTestCases();
+        } else {
+            unsupportedNonX86CPUTestCases();
+        }
+    }
+
+    /**
+     * Run test cases common for all bit manipulation related VM options
+     * targeted to X86 CPU that does not support required features.
+     *
+     * @throws Throwable if test failed.
+     */
+    public void unsupportedX86CPUTestCases() throws Throwable {
+
+        // verify that VM will succesfully start up, but output will
+        // contain a warning
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:+" + optionName,
+                             new String[] { warningMessage },
+                             new String[] { errorMessage },
+                             ExitCode.OK);
+
+        // verify that VM will succesfully startup without any warnings
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:-" + optionName,
+                             null,
+                             new String[] { warningMessage, errorMessage },
+                             ExitCode.OK);
+
+        // verify that on unsupported CPUs option is off by default
+        CommandLineOptionTest.verifyOptionValue(optionName, "false");
+
+        // verify that on unsupported CPUs option will be off even if
+        // it was explicitly turned on by uset
+        CommandLineOptionTest.verifyOptionValue(optionName, "false",
+                                                     "-XX:+" + optionName);
+
+    }
+
+    /**
+     * Run test cases common for all bit manipulation related VM options
+     * targeted to non-X86 CPU that does not support required features.
+     *
+     * @throws Throwable if test failed.
+     */
+    public void unsupportedNonX86CPUTestCases() throws Throwable {
+
+        // verify that VM known nothing about tested option
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:+" + optionName,
+                             new String[] { errorMessage },
+                             null,
+                             ExitCode.FAIL);
+
+        CommandLineOptionTest.
+            verifyJVMStartup("-XX:-" + optionName,
+                             new String[] { errorMessage },
+                             null,
+                             ExitCode.FAIL);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseBMI1Instructions option on CPU with
+ *          BMI1 feature support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseBMI1InstructionsOnSupportedCPU
+ *        BMISupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnSupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+
+public class TestUseBMI1InstructionsOnSupportedCPU
+     extends BMISupportedCPUTest {
+
+    public TestUseBMI1InstructionsOnSupportedCPU() {
+        super("UseBMI1Instructions", BMI1_WARNING, "bmi1");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseBMI1InstructionsOnSupportedCPU().test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseBMI1Instructions option on CPU without
+ *          BMI1 feature support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseBMI1InstructionsOnUnsupportedCPU
+ *        BMIUnsupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnUnsupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.*;
+
+public class TestUseBMI1InstructionsOnUnsupportedCPU
+      extends BMIUnsupportedCPUTest {
+
+    public TestUseBMI1InstructionsOnUnsupportedCPU() {
+        super("UseBMI1Instructions", BMI1_WARNING, "bmi1");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseBMI1InstructionsOnUnsupportedCPU().test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseCountLeadingZerosInstruction option
+ *          on CPU with LZCNT support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseCountLeadingZerosInstructionOnSupportedCPU
+ *        BMISupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseCountLeadingZerosInstructionOnSupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+
+public class TestUseCountLeadingZerosInstructionOnSupportedCPU
+     extends BMISupportedCPUTest {
+
+    public TestUseCountLeadingZerosInstructionOnSupportedCPU() {
+        super("UseCountLeadingZerosInstruction", LZCNT_WARNING, "lzcnt");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseCountLeadingZerosInstructionOnSupportedCPU().test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseCountLeadingZerosInstruction option
+ *          on CPU without LZCNT support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU
+ *        BMIUnsupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseCountLeadingZerosInstructionOnUnsupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+
+public class TestUseCountLeadingZerosInstructionOnUnsupportedCPU
+     extends BMIUnsupportedCPUTest {
+
+    public TestUseCountLeadingZerosInstructionOnUnsupportedCPU() {
+        super("UseCountLeadingZerosInstruction", LZCNT_WARNING, "lzcnt");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseCountLeadingZerosInstructionOnUnsupportedCPU().test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseCountTrailingZerosInstruction option
+ *          on CPU with TZCNT (BMI1 feature) support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseCountTrailingZerosInstructionOnSupportedCPU
+ *        BMISupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseCountTrailingZerosInstructionOnSupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.*;
+
+public class TestUseCountTrailingZerosInstructionOnSupportedCPU
+     extends BMISupportedCPUTest {
+
+    public TestUseCountTrailingZerosInstructionOnSupportedCPU() {
+        super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1");
+    }
+
+    @Override
+    public void runTestCases() throws Throwable {
+
+        super.runTestCases();
+
+        // verify that option will be disabled if all BMI1 instuctions
+        // are explicitly disabled
+        CommandLineOptionTest.
+            verifyOptionValue("UseCountTrailingZerosInstruction", "false",
+                              "-XX:-UseBMI1Instructions");
+
+        // verify that option could be turned on even if other BMI1
+        // instructions were turned off
+        CommandLineOptionTest.
+            verifyOptionValue("UseCountTrailingZerosInstruction", "true",
+                              "-XX:-UseBMI1Instructions",
+                              "-XX:+UseCountTrailingZerosInstruction");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseCountTrailingZerosInstructionOnSupportedCPU().test();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify processing of UseCountTrailingZerosInstruction option
+ *          on CPU without TZCNT instuction (BMI1 feature) support.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU
+ *        BMIUnsupportedCPUTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   TestUseCountTrailingZerosInstructionOnUnsupportedCPU
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.*;
+
+public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU
+     extends BMIUnsupportedCPUTest {
+
+    public TestUseCountTrailingZerosInstructionOnUnsupportedCPU() {
+        super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1");
+    }
+
+    @Override
+    public void unsupportedX86CPUTestCases() throws Throwable {
+
+        super.unsupportedX86CPUTestCases();
+
+        // verify that option will not be turned on during
+        // UseBMI1Instuctions processing
+        CommandLineOptionTest.
+            verifyOptionValue("UseCountTrailingZerosInstruction", "false",
+                              "-XX:+UseBMI1Instructions");
+
+        CommandLineOptionTest.
+            verifyOptionValue("UseCountTrailingZerosInstruction", "false",
+                              "-XX:+UseCountTrailingZerosInstruction",
+                              "-XX:+UseBMI1Instructions");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        new TestUseCountTrailingZerosInstructionOnUnsupportedCPU().test();
+    }
+}
+
--- a/hotspot/test/compiler/ciReplay/common.sh	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/compiler/ciReplay/common.sh	Wed Jul 05 19:35:40 2017 +0200
@@ -218,7 +218,7 @@
             -XX:VMThreadStackSize=512 \
             -XX:CompilerThreadStackSize=512 \
             -XX:ParallelGCThreads=1 \
-            -XX:CICompilerCount=1 \
+            -XX:CICompilerCount=2 \
             -Xcomp \
             -XX:CICrashAt=1 \
             -XX:+CreateMinidumpOnCrash \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codegen/C1NullCheckOfNullStore.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8039043
+ * @summary Null check is placed in a wrong place when storing a null to an object field on x64 with compressed oops off
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CompileCommand=compileonly,C1NullCheckOfNullStore::test -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-UseCompressedOops C1NullCheckOfNullStore
+ *
+ */
+
+public class C1NullCheckOfNullStore {
+  private static class Foo {
+    Object bar;
+  }
+  static private void test(Foo x) {
+    x.bar = null;
+  }
+  static public void main(String args[]) {
+    Foo x = new Foo();
+    for (int i = 0; i < 10000; i++) {
+      test(x);
+    }
+    boolean gotNPE = false;
+    try {
+      for (int i = 0; i < 10000; i++) {
+        test(null);
+      }
+    }
+    catch(NullPointerException e) {
+      gotNPE = true;
+    }
+    if (!gotNPE) {
+      throw new Error("Expecting a NullPointerException");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/BMITestRunner.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+import java.util.*;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.charset.StandardCharsets;
+
+import com.oracle.java.testlibrary.*;
+
+/**
+ * Test runner that invokes all methods implemented by particular Expr
+ * with random arguments in two different JVM processes and compares output.
+ * JVMs being started in different modes - one in int and other in comp
+ * with C2 and disabled tiered compilation.
+ */
+public class BMITestRunner {
+
+    enum VMMode {
+        COMP, INT;
+    };
+
+    public static int DEFAULT_ITERATIONS_COUNT = 4000;
+
+    /**
+     * Execute all methods implemented by <b>expr</b> in int and comp modes
+     * and compare output.
+     * Test pass only of output obtained with different VM modes is equal.
+     * To control behaviour of test following options could be passed:
+     * <ul>
+     *   <li>-iterations=&lt;N&gt; each operation implemented by
+     *       <b>expr</b> will be executed <i>N</i> times. Default value
+     *       is 4000.</li>
+     *   <li>-seed=&lt;SEED&gt; arguments for <b>expr</b>'s methods
+     *       obtained via RNG initiated with seed <i>SEED</i>. By default
+     *       some random seed will be used.</li>
+     * </ul>
+     *
+     * @param expr operation that should be tested
+     * @param testOpts options to control test behaviour
+     * @param additionalVMOpts additional options for VM
+     *
+     * @throws Throwable if test failed.
+     */
+    public static void runTests(Class<? extends Expr> expr,
+                                String testOpts[],
+                                String... additionalVMOpts)
+                         throws Throwable {
+
+        int seed = new Random().nextInt();
+        int iterations = DEFAULT_ITERATIONS_COUNT;
+
+        for (String testOption : testOpts) {
+            if (testOption.startsWith("-iterations=")) {
+                iterations = Integer.valueOf(testOption.
+                                             replace("-iterations=", ""));
+            } else if (testOption.startsWith("-seed=")) {
+                seed = Integer.valueOf(testOption.replace("-seed=", ""));
+            }
+        }
+
+        System.out.println("Running test with seed: " + seed);
+
+        OutputAnalyzer intOutput = runTest(expr, VMMode.INT,
+                                           additionalVMOpts,
+                                           seed, iterations);
+        OutputAnalyzer compOutput = runTest(expr, VMMode.COMP,
+                                            additionalVMOpts,
+                                            seed, iterations);
+
+        dumpOutput(intOutput, "int");
+        dumpOutput(compOutput, "comp");
+
+        Asserts.assertStringsEqual(intOutput.getStdout(),
+                                   compOutput.getStdout(),
+                                   "Results obtained in -Xint and " +
+                                   "-Xcomp should be the same.");
+    }
+
+    /**
+     * Execute tests on methods implemented by <b>expr</b> in new VM
+     * started in <b>testVMMode</b> mode.
+     *
+     * @param expr operation that should be tested
+     * @param testVMMode VM mode for test
+     * @param additionalVMOpts additional options for VM
+     * @param seed for RNG used it tests
+     * @param iterations that will be used to invoke <b>expr</b>'s methods.
+     *
+     * @return OutputAnalyzer for executed test.
+     * @throws Throwable when something goes wrong.
+     */
+    public static OutputAnalyzer runTest(Class<? extends Expr> expr,
+                                         VMMode testVMMode,
+                                         String additionalVMOpts[],
+                                         int seed, int iterations)
+                                  throws Throwable {
+
+        List<String> vmOpts = new LinkedList<String>();
+
+        Collections.addAll(vmOpts, additionalVMOpts);
+
+        //setup mode-specific options
+        switch (testVMMode) {
+        case INT:
+            Collections.addAll(vmOpts, new String[] { "-Xint" });
+            break;
+        case COMP:
+            Collections.addAll(vmOpts, new String[] {
+                    "-Xcomp",
+                    "-XX:-TieredCompilation",
+                    String.format("-XX:CompileCommand=compileonly,%s::*",
+                                  expr.getName())
+                });
+            break;
+        }
+
+        Collections.addAll(vmOpts, new String[] {
+                "-XX:+DisplayVMOutputToStderr",
+                Executor.class.getName(),
+                expr.getName(),
+                new Integer(seed).toString(),
+                new Integer(iterations).toString()
+            });
+
+        OutputAnalyzer outputAnalyzer = ProcessTools.
+            executeTestJvm(vmOpts.toArray(new String[vmOpts.size()]));
+
+        outputAnalyzer.shouldHaveExitValue(0);
+
+        return outputAnalyzer;
+    }
+
+    /**
+     * Dump stdout and stderr of test process to <i>prefix</i>.test.out
+     * and <i>prefix</i>.test.err respectively.
+     *
+     * @param outputAnalyzer OutputAnalyzer whom output should be dumped
+     * @param prefix Prefix that will be used in file names.
+     * @throws IOException if unable to dump output to file.
+     */
+    protected static void dumpOutput(OutputAnalyzer outputAnalyzer,
+                                     String prefix)
+                              throws IOException {
+        Files.write(Paths.get(prefix + ".test.out"),
+                    outputAnalyzer.getStdout().getBytes());
+
+        Files.write(Paths.get(prefix + ".test.err"),
+                    outputAnalyzer.getStderr().getBytes());
+    }
+
+
+    /**
+     * Executor that invoke all methods implemented by particular
+     * Expr instance.
+     */
+    public static class Executor {
+
+        /**
+         * Usage: BMITestRunner$Executor <ExprClassName> <seed> <iterations>
+         */
+        public static void main(String args[]) throws Exception {
+            @SuppressWarnings("unchecked")
+            Class<? extends Expr> exprClass =
+                (Class<? extends Expr>)Class.forName(args[0]);
+            Expr expr = exprClass.getConstructor().newInstance();
+            Random rng = new Random(Integer.valueOf(args[1]));
+            int iterations = Integer.valueOf(args[2]);
+            runTests(expr, iterations, rng);
+        }
+
+
+        public static int[] getIntBitShifts() {
+            //SIZE+1 shift is for zero.
+            int data[] = new int[Integer.SIZE+1];
+            for (int s = 0; s < data.length; s++) {
+                data[s] = 1<<s;
+            }
+            return data;
+        }
+
+        public static long[] getLongBitShifts() {
+            //SIZE+1 shift is for zero.
+            long data[] = new long[Long.SIZE+1];
+            for (int s = 0; s < data.length; s++) {
+                data[s] = 1L<<s;
+            }
+            return data;
+        }
+
+        public static void log(String format, Object... args) {
+            System.out.println(String.format(format, args));
+        }
+
+        public static void runTests(Expr expr, int iterations, Random rng) {
+            runUnaryIntRegTest(expr, iterations, rng);
+            runUnaryIntMemTest(expr, iterations, rng);
+            runUnaryLongRegTest(expr, iterations, rng);
+            runUnaryLongMemTest(expr, iterations, rng);
+            runBinaryRegRegIntTest(expr, iterations, rng);
+            runBinaryRegMemIntTest(expr, iterations, rng);
+            runBinaryMemRegIntTest(expr, iterations, rng);
+            runBinaryMemMemIntTest(expr, iterations, rng);
+            runBinaryRegRegLongTest(expr, iterations, rng);
+            runBinaryRegMemLongTest(expr, iterations, rng);
+            runBinaryMemRegLongTest(expr, iterations, rng);
+            runBinaryMemMemLongTest(expr, iterations, rng);
+        }
+
+        public static void runUnaryIntRegTest(Expr expr, int iterations,
+                                              Random rng) {
+            if (!(expr.isUnaryArgumentSupported()
+                  && expr.isIntExprSupported())) {
+                return;
+            }
+
+            for (int value : getIntBitShifts()) {
+                log("UnaryIntReg(0X%x) -> 0X%x",
+                    value, expr.intExpr(value));
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int value = rng.nextInt();
+                log("UnaryIntReg(0X%x) -> 0X%x",
+                    value, expr.intExpr(value));
+            }
+        }
+
+        public static void runUnaryIntMemTest(Expr expr, int iterations,
+                                              Random rng) {
+            if (!(expr.isUnaryArgumentSupported()
+                  && expr.isIntExprSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int value : getIntBitShifts()) {
+                log("UnaryIntMem(0X%x) -> 0X%x",
+                    value, expr.intExpr(new Expr.MemI(value)));
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int value = rng.nextInt();
+                log("UnaryIntMem(0X%x) -> 0X%x",
+                    value, expr.intExpr(new Expr.MemI(value)));
+            }
+        }
+
+        public static void runUnaryLongRegTest(Expr expr, int iterations,
+                                               Random rng) {
+            if (!(expr.isUnaryArgumentSupported()
+                  && expr.isLongExprSupported())) {
+                return;
+            }
+
+            for (long value : getLongBitShifts()) {
+                log("UnaryLongReg(0X%x) -> 0X%x",
+                    value, expr.longExpr(value));
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long value = rng.nextLong();
+                log("UnaryLongReg(0X%x) -> 0X%x",
+                    value, expr.longExpr(value));
+            }
+        }
+
+        public static void runUnaryLongMemTest(Expr expr, int iterations,
+                                               Random rng) {
+            if (!(expr.isUnaryArgumentSupported()
+                  && expr.isLongExprSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (long value : getLongBitShifts()) {
+                log("UnaryLongMem(0X%x) -> 0X%x",
+                    value, expr.longExpr(new Expr.MemL(value)));
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long value = rng.nextLong();
+                log("UnaryLongMem(0X%x) -> 0X%x",
+                    value, expr.longExpr(new Expr.MemL(value)));
+            }
+        }
+
+        public static void runBinaryRegRegIntTest(Expr expr, int iterations,
+                                                  Random rng) {
+            if (!(expr.isIntExprSupported()
+                  && expr.isBinaryArgumentSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int aValue = rng.nextInt();
+                int bValue = rng.nextInt();
+                log("BinaryIntRegReg(0X%x, 0X%x) -> 0X%x",
+                    aValue, bValue, expr.intExpr(aValue, bValue));
+            }
+        }
+
+        public static void runBinaryRegMemIntTest(Expr expr, int iterations,
+                                                  Random rng) {
+            if (!(expr.isIntExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int aValue = rng.nextInt();
+                int bValue = rng.nextInt();
+                log("BinaryIntRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.intExpr(aValue, new Expr.MemI(bValue)));
+            }
+        }
+
+        public static void runBinaryMemRegIntTest(Expr expr, int iterations,
+                                                  Random rng) {
+            if (!(expr.isIntExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int aValue = rng.nextInt();
+                int bValue = rng.nextInt();
+                log("BinaryIntMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.intExpr(new Expr.MemI(aValue), bValue));
+            }
+        }
+
+        public static void runBinaryMemMemIntTest(Expr expr, int iterations,
+                                                  Random rng) {
+            if (!(expr.isIntExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                int aValue = rng.nextInt();
+                int bValue = rng.nextInt();
+                log("BinaryIntMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.intExpr(new Expr.MemI(aValue),
+                                 new Expr.MemI(bValue)));
+            }
+        }
+
+        public static void runBinaryRegRegLongTest(Expr expr,
+                                                   int iterations,
+                                                   Random rng) {
+            if (!(expr.isLongExprSupported()
+                  && expr.isBinaryArgumentSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long aValue = rng.nextLong();
+                long bValue = rng.nextLong();
+                log("BinaryLongRegReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.longExpr(aValue, bValue));
+            }
+        }
+
+        public static void runBinaryRegMemLongTest(Expr expr,
+                                                   int iterations,
+                                                   Random rng) {
+            if (!(expr.isLongExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long aValue = rng.nextLong();
+                long bValue = rng.nextLong();
+                log("BinaryLongRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.longExpr(aValue, new Expr.MemL(bValue)));
+            }
+        }
+
+        public static void runBinaryMemRegLongTest(Expr expr,
+                                                   int iterations,
+                                                   Random rng) {
+            if (!(expr.isLongExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long aValue = rng.nextLong();
+                long bValue = rng.nextLong();
+                log("BinaryLongMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.longExpr(new Expr.MemL(aValue), bValue));
+            }
+        }
+
+        public static void runBinaryMemMemLongTest(Expr expr,
+                                                   int iterations,
+                                                   Random rng) {
+            if (!(expr.isLongExprSupported()
+                  && expr.isBinaryArgumentSupported()
+                  && expr.isMemExprSupported())) {
+                return;
+            }
+
+            for (int i = 0; i < iterations; i++) {
+                long aValue = rng.nextLong();
+                long bValue = rng.nextLong();
+                log("BinaryLongMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
+                    expr.longExpr(new Expr.MemL(aValue),
+                                  new Expr.MemL(bValue)));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/Expr.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * Expression that should be replaced by particular instrinsic
+ * or intruction during compilation.
+ */
+
+public abstract class Expr {
+
+    public static class MemI {
+        public MemI(int i) {
+            this.value = i;
+        }
+
+        public int value;
+    }
+
+    public static class MemL {
+        public MemL(long l) {
+            this.value = l;
+        }
+
+        public long value;
+    }
+
+    public boolean isUnaryArgumentSupported() {
+        return false;
+    }
+
+    public boolean isIntExprSupported() {
+        return false;
+    }
+
+    public boolean isBinaryArgumentSupported() {
+        return false;
+    }
+
+    public boolean isLongExprSupported() {
+        return false;
+    }
+
+    public boolean isMemExprSupported() {
+        return false;
+    }
+
+    public int intExpr(int reg) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int intExpr(MemI mem) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int intExpr(int a, int b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int intExpr(int a, MemI b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int intExpr(MemI a, int b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int intExpr(MemI a, MemI b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(long reg) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(MemL mem) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(long a, long b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(long a, MemL b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(MemL a, long b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public long longExpr(MemL a, MemL b) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static class BMIExpr extends Expr {
+
+        public boolean isMemExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BMIBinaryExpr extends BMIExpr {
+
+        public boolean isBinaryArgumentSupported() {
+            return true;
+        }
+
+    }
+
+    public static class BMIUnaryExpr extends BMIExpr {
+        public boolean isUnaryArgumentSupported() {
+            return true;
+        }
+    }
+
+    public static class BMIBinaryIntExpr extends BMIBinaryExpr {
+        public boolean isIntExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BMIBinaryLongExpr extends BMIBinaryExpr {
+        public boolean isLongExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BMIUnaryIntExpr extends BMIUnaryExpr {
+        public boolean isIntExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BMIUnaryLongExpr extends BMIUnaryExpr {
+        public boolean isLongExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BitCountingExpr extends Expr {
+        public boolean isUnaryArgumentSupported() {
+            return true;
+        }
+    }
+
+    public static class BitCountingIntExpr extends BitCountingExpr {
+        public boolean isIntExprSupported() {
+            return true;
+        }
+    }
+
+    public static class BitCountingLongExpr extends BitCountingExpr {
+        public boolean isLongExprSupported() {
+            return true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of ANDN instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestAndnI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestAndnI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestAndnI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. "+
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(AndnIExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(AndnICommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class AndnIExpr extends Expr.BMIBinaryIntExpr {
+
+        public int intExpr(int src1, int src2) {
+            return ~src1 & src2;
+        }
+
+        public int intExpr(int src1, Expr.MemI src2) {
+            return ~src1 & src2.value;
+        }
+
+        public int intExpr(Expr.MemI src1, int src2) {
+            return ~src1.value & src2;
+        }
+
+        public int intExpr(Expr.MemI src1, Expr.MemI src2) {
+            return ~src1.value & src2.value;
+        }
+    }
+
+    public static class AndnICommutativeExpr extends Expr.BMIBinaryIntExpr {
+
+        public int intExpr(int src1, int src2) {
+            return src1 & ~src2;
+        }
+
+        public int intExpr(int src1, Expr.MemI src2) {
+            return src1 & ~src2.value;
+        }
+
+        public int intExpr(Expr.MemI src1, int src2) {
+            return src1.value & ~src2;
+        }
+
+        public int intExpr(Expr.MemI src1, Expr.MemI src2) {
+            return src1.value & ~src2.value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of ANDN instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestAndnL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestAndnL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestAndnL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(AndnLExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(AndnLCommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class AndnLExpr extends Expr.BMIBinaryLongExpr {
+
+        public long longExpr(long src1, long src2) {
+            return ~src1 & src2;
+        }
+
+        public long longExpr(long src1, Expr.MemL src2) {
+            return ~src1 & src2.value;
+        }
+
+        public long longExpr(Expr.MemL src1, long src2) {
+            return ~src1.value & src2;
+        }
+
+        public long longExpr(Expr.MemL src1, Expr.MemL src2) {
+            return ~src1.value & src2.value;
+        }
+
+
+    }
+
+    public static class AndnLCommutativeExpr extends Expr.BMIBinaryLongExpr {
+
+        public long longExpr(long src1, long src2) {
+            return src1 & ~src2;
+        }
+
+        public long longExpr(long src1, Expr.MemL src2) {
+            return src1 & ~src2.value;
+        }
+
+        public long longExpr(Expr.MemL src1, long src2) {
+            return src1.value & ~src2;
+        }
+
+        public long longExpr(Expr.MemL src1, Expr.MemL src2) {
+            return src1.value & ~src2.value;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSI instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsiI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsiI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsiI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsiIExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsiICommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsiIExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return -src & src;
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return -src.value & src.value;
+        }
+
+    }
+
+    public static class BlsiICommutativeExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return src & -src;
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return src.value & -src.value;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSI instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsiL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsiL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsiL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsiLExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsiLCommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsiLExpr extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return -src & src;
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return -src.value & src.value;
+        }
+
+    }
+
+    public static class BlsiLCommutativeExpr extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return src & -src;
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return src.value & -src.value;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSMSK instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsmskI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsmskI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsmskI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsmskIExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsmskICommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsmskIExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return (src - 1) ^ src;
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return (src.value - 1) ^ src.value;
+        }
+
+    }
+
+    public static class BlsmskICommutativeExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return src ^ (src - 1);
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return src.value ^ (src.value - 1);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSMSK instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsmskL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsmskL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsmskL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsmskLExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsmskLCommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsmskLExpr
+        extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return (src - 1) ^ src;
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return (src.value - 1) ^ src.value;
+        }
+
+    }
+
+    public static class BlsmskLCommutativeExpr
+        extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return src ^ (src - 1);
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return src.value ^ (src.value - 1);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSR instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsrI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsrI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsrI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsrIExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsrICommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsrIExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return (src - 1) & src;
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return (src.value - 1) & src.value;
+        }
+
+    }
+
+    public static class BlsrICommutativeExpr extends Expr.BMIUnaryIntExpr {
+
+        public int intExpr(int src) {
+            return src & (src - 1);
+        }
+
+        public int intExpr(Expr.MemI src) {
+            return src.value & (src.value - 1);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of BLSR instruction
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestBlsrL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestBlsrL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestBlsrL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(BlsrLExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+        BMITestRunner.runTests(BlsrLCommutativeExpr.class, args,
+                               "-XX:+UseBMI1Instructions");
+    }
+
+    public static class BlsrLExpr extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return (src - 1) & src;
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return (src.value - 1) & src.value;
+        }
+
+    }
+
+    public static class BlsrLCommutativeExpr extends Expr.BMIUnaryLongExpr {
+
+        public long longExpr(long src) {
+            return src & (src - 1);
+        }
+
+        public long longExpr(Expr.MemL src) {
+            return src.value & (src.value - 1);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of intrinsic
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestLzcntI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestLzcntI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestLzcntI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("lzcnt")) {
+            System.out.println("CPU does not support lzcnt feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(LzcntIExpr.class, args,
+                               "-XX:+UseCountLeadingZerosInstruction");
+    }
+
+    public static class LzcntIExpr extends Expr.BitCountingIntExpr {
+
+        public int intExpr(int src) {
+            return Integer.numberOfLeadingZeros(src);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of intrinsic
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestLzcntL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestLzcntL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestLzcntL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("lzcnt")) {
+            System.out.println("CPU does not support lzcnt feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(LzcntLExpr.class, args,
+                               "-XX:+UseCountLeadingZerosInstruction");
+    }
+
+    public static class LzcntLExpr extends Expr.BitCountingLongExpr {
+
+        public long longExpr(long src) {
+            return Long.numberOfLeadingZeros(src);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of intrinsic
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestTzcntI BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestTzcntI
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestTzcntI {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(TzcntIExpr.class, args,
+                               "-XX:+UseCountTrailingZerosInstruction");
+    }
+
+    public static class TzcntIExpr extends Expr.BitCountingIntExpr {
+
+        public int intExpr(int src) {
+            return Integer.numberOfTrailingZeros(src);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8031321
+ * @summary Verify that results of computations are the same w/
+ *          and w/o usage of intrinsic
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestTzcntL BMITestRunner Expr
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI TestTzcntL
+ */
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+public class TestTzcntL {
+
+    public static void main(String args[]) throws Throwable {
+        if (!CPUInfo.hasFeature("bmi1")) {
+            System.out.println("CPU does not support bmi1 feature. " +
+                               "Test skipped.");
+            return;
+        }
+
+        BMITestRunner.runTests(TzcntLExpr.class, args,
+                               "-XX:+UseCountTrailingZerosInstruction");
+    }
+
+    public static class TzcntLExpr extends Expr.BitCountingLongExpr {
+
+        public long longExpr(long src) {
+            return Long.numberOfTrailingZeros(src);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 6653795
+ * @summary C2 intrinsic for Unsafe.getAddress performs pointer sign extension on 32-bit systems
+ * @run main UnsafeGetAddressTest
+ *
+ */
+
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+public class UnsafeGetAddressTest {
+    private static Unsafe unsafe;
+
+    public static void main(String[] args) throws Exception {
+        Class c = UnsafeGetAddressTest.class.getClassLoader().loadClass("sun.misc.Unsafe");
+        Field f = c.getDeclaredField("theUnsafe");
+        f.setAccessible(true);
+        unsafe = (Unsafe)f.get(c);
+
+        long address = unsafe.allocateMemory(unsafe.addressSize());
+        unsafe.putAddress(address, 0x0000000080000000L);
+        // from sun.misc.Unsafe.getAddress' documentation:
+        // "If the native pointer is less than 64 bits wide, it is
+        // extended as an unsigned number to a Java long."
+        result = unsafe.getAddress(address);
+        System.out.printf("1: was 0x%x, expected 0x%x\n", result,
+                0x0000000080000000L);
+        for (int i = 0; i < 1000000; i++) {
+            result = unsafe.getAddress(address);
+        }
+
+        // The code has got compiled, check the result now
+        System.out.printf("2: was 0x%x, expected 0x%x\n", result,
+                0x0000000080000000L);
+        if (result != 0x0000000080000000L) {
+            System.out.println("Test Failed");
+            System.exit(97);
+        } else {
+            System.out.println("Test Passed");
+        }
+    }
+    static volatile long result;
+}
+
--- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -24,6 +24,7 @@
 import com.sun.management.HotSpotDiagnosticMXBean;
 import com.sun.management.VMOption;
 import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
 import sun.management.ManagementFactoryHelper;
 
 import java.lang.reflect.Constructor;
@@ -278,7 +279,8 @@
     }
 
     protected final int getCompLevel() {
-        return WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr());
+        NMethod nm = NMethod.get(method, testCase.isOsr());
+        return nm == null ? COMP_LEVEL_NONE : nm.comp_level;
     }
 
     protected final boolean isCompilable() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/whitebox/GetNMethodTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+import sun.hotspot.code.NMethod;
+
+/*
+ * @test GetNMethodTest
+ * @bug 8038240
+ * @library /testlibrary /testlibrary/whitebox
+ * @build GetNMethodTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* GetNMethodTest
+ * @summary testing of WB::getNMethod()
+ * @author igor.ignatyev@oracle.com
+ */
+public class GetNMethodTest extends CompilerWhiteBoxTest {
+    public static void main(String[] args) throws Exception {
+        CompilerWhiteBoxTest.main(GetNMethodTest::new, args);
+    }
+
+    private GetNMethodTest(TestCase testCase) {
+        super(testCase);
+        // to prevent inlining of #method
+        WHITE_BOX.testSetDontInlineMethod(method, true);
+    }
+
+    @Override
+    protected void test() throws Exception {
+        checkNotCompiled();
+
+        compile();
+        checkCompiled();
+        NMethod nmethod = NMethod.get(method, testCase.isOsr());
+        if (IS_VERBOSE) {
+            System.out.println("nmethod = " + nmethod);
+        }
+        if (nmethod == null) {
+            throw new RuntimeException("nmethod of compiled method is null");
+        }
+        if (nmethod.insts.length == 0) {
+            throw new RuntimeException("compiled method's instructions is empty");
+        }
+        deoptimize();
+        checkNotCompiled();
+        nmethod = NMethod.get(method, testCase.isOsr());
+        if (nmethod != null) {
+            throw new RuntimeException("nmethod of non-compiled method isn't null");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/TestGCLogRotationViaJcmd.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestGCLogRotationViaJcmd.java
+ * @bug 7090324
+ * @summary test for gc log rotation via jcmd
+ * @library /testlibrary
+ * @run main/othervm -Xloggc:test.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 TestGCLogRotationViaJcmd
+ *
+ */
+import com.oracle.java.testlibrary.*;
+import java.io.File;
+import java.io.FilenameFilter;
+
+public class TestGCLogRotationViaJcmd {
+
+    static final File currentDirectory = new File(".");
+    static final String LOG_FILE_NAME = "test.log";
+    static final int NUM_LOGS = 3;
+
+    static FilenameFilter logFilter = new FilenameFilter() {
+        @Override
+        public boolean accept(File dir, String name) {
+            return name.startsWith(LOG_FILE_NAME);
+        }
+    };
+
+    public static void main(String[] args) throws Exception {
+        // Grab the pid from the current java process
+        String pid = Integer.toString(ProcessTools.getProcessId());
+
+        // Create a JDKToolLauncher
+        JDKToolLauncher jcmd = JDKToolLauncher.create("jcmd")
+                                              .addToolArg(pid)
+                                              .addToolArg("GC.rotate_log");
+
+        for (int times = 1; times < NUM_LOGS; times++) {
+            // Run jcmd <pid> GC.rotate_log
+            ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand());
+
+            // Make sure we didn't crash
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldHaveExitValue(0);
+        }
+
+        // GC log check
+        File[] logs = currentDirectory.listFiles(logFilter);
+        if (logs.length != NUM_LOGS) {
+            throw new Error("There are only " + logs.length
+                                              + " logs instead " + NUM_LOGS);
+        }
+
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/FlagsValue.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 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.
+*/
+
+import java.util.regex.*;
+
+public class FlagsValue {
+  public static boolean getFlagBoolValue(String flag, String where) {
+    Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
+    if (!m.find()) {
+      throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+    }
+    return m.group(1).equals("true");
+  }
+
+  public static long getFlagLongValue(String flag, String where) {
+    Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+    if (!m.find()) {
+      throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+    }
+    String match = m.group();
+    return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length()));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test TestDynMaxHeapFreeRatio
+ * @bug 8028391
+ * @summary Verify that MaxHeapFreeRatio flag is manageable
+ * @library /testlibrary
+ * @run main TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:-UseAdaptiveSizePolicy TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
+ */
+import com.oracle.java.testlibrary.TestDynamicVMOption;
+import com.oracle.java.testlibrary.DynamicVMOptionChecker;
+
+public class TestDynMaxHeapFreeRatio extends TestDynamicVMOption {
+
+    public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
+    public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
+
+    public TestDynMaxHeapFreeRatio() {
+        super(MaxFreeRatioFlagName);
+    }
+
+    public void test() {
+
+        int minHeapFreeValue = DynamicVMOptionChecker.getIntValue(MinFreeRatioFlagName);
+        System.out.println(MinFreeRatioFlagName + " = " + minHeapFreeValue);
+
+        testPercentageValues();
+
+        checkInvalidValue(Integer.toString(minHeapFreeValue - 1));
+        checkValidValue(Integer.toString(minHeapFreeValue));
+        checkValidValue("100");
+    }
+
+    public static void main(String args[]) throws Exception {
+        new TestDynMaxHeapFreeRatio().test();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test TestDynMinHeapFreeRatio
+ * @bug 8028391
+ * @summary Verify that MinHeapFreeRatio flag is manageable
+ * @library /testlibrary
+ * @run main TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:-UseAdaptiveSizePolicy TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
+ */
+import com.oracle.java.testlibrary.TestDynamicVMOption;
+import com.oracle.java.testlibrary.DynamicVMOptionChecker;
+
+public class TestDynMinHeapFreeRatio extends TestDynamicVMOption {
+
+    public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
+    public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
+
+    public TestDynMinHeapFreeRatio() {
+        super(MinFreeRatioFlagName);
+    }
+
+    public void test() {
+        int maxHeapFreeValue = DynamicVMOptionChecker.getIntValue(MaxFreeRatioFlagName);
+        System.out.println(MaxFreeRatioFlagName + " = " + maxHeapFreeValue);
+
+        testPercentageValues();
+
+        checkInvalidValue(Integer.toString(maxHeapFreeValue + 1));
+        checkValidValue(Integer.toString(maxHeapFreeValue));
+        checkValidValue("0");
+    }
+
+    public static void main(String args[]) throws Exception {
+        new TestDynMinHeapFreeRatio().test();
+    }
+}
--- a/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2013, 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
@@ -63,13 +63,13 @@
     // successful tests
     runWithThresholds(0, 10, false);
     runWithThresholds(5, 5, false);
+    runWithThresholds(8, 16, false);
     // failing tests
     runWithThresholds(10, 0, true);
     runWithThresholds(9, 8, true);
     runWithThresholds(-1, 8, true);
     runWithThresholds(8, -1, true);
-    runWithThresholds(8, 16, true);
     runWithThresholds(16, 8, true);
+    runWithThresholds(8, 17, true);
   }
-}
-
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestObjectTenuringFlags.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,215 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestObjectTenuringFlags
+ * @key gc
+ * @bug 6521376
+ * @summary Tests argument processing for NeverTenure, AlwaysTenure,
+ * and MaxTenuringThreshold
+ * @library /testlibrary
+ * @build TestObjectTenuringFlags FlagsValue
+ * @run main/othervm TestObjectTenuringFlags
+ */
+
+import com.oracle.java.testlibrary.*;
+
+import java.util.*;
+
+public class TestObjectTenuringFlags {
+  public static void main(String args[]) throws Exception {
+    // default case
+    runTenuringFlagsConsistencyTest(
+        new String[]{},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 15));
+
+    // valid cases
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+NeverTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+AlwaysTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=0"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=5"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 5, 5));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=10"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 10));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=15"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 15));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=16"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 16));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=0"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 0, 15));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=5"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 5, 15));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=10"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 10, 15));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=15"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 15, 15));
+
+    // "Last option wins" cases
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+AlwaysTenure", "-XX:+NeverTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+NeverTenure", "-XX:+AlwaysTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=16", "-XX:+AlwaysTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+AlwaysTenure", "-XX:MaxTenuringThreshold=16"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 16));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=0", "-XX:+NeverTenure"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16));
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:+NeverTenure", "-XX:MaxTenuringThreshold=0"},
+        false /* shouldFail */,
+        new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0));
+
+    // Illegal cases
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:MaxTenuringThreshold=17"},
+        true /* shouldFail */,
+        new ExpectedTenuringFlags());
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=16"},
+        true /* shouldFail */,
+        new ExpectedTenuringFlags());
+
+    runTenuringFlagsConsistencyTest(
+        new String[]{"-XX:InitialTenuringThreshold=17"},
+        true /* shouldFail */,
+        new ExpectedTenuringFlags());
+  }
+
+  private static void runTenuringFlagsConsistencyTest(String[] tenuringFlags,
+          boolean shouldFail,
+          ExpectedTenuringFlags expectedFlags) throws Exception {
+    List<String> vmOpts = new ArrayList<>();
+    if (tenuringFlags.length > 0) {
+      Collections.addAll(vmOpts, tenuringFlags);
+    }
+    Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version");
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    if (shouldFail) {
+      output.shouldHaveExitValue(1);
+    } else {
+      output.shouldHaveExitValue(0);
+      String stdout = output.getStdout();
+      checkTenuringFlagsConsistency(stdout, expectedFlags);
+    }
+  }
+
+  private static void checkTenuringFlagsConsistency(String output, ExpectedTenuringFlags expectedFlags) {
+    if (expectedFlags.alwaysTenure != FlagsValue.getFlagBoolValue("AlwaysTenure", output)) {
+      throw new RuntimeException(
+            "Actual flag AlwaysTenure " + FlagsValue.getFlagBoolValue("AlwaysTenure", output) +
+            " is not equal to expected flag AlwaysTenure " + expectedFlags.alwaysTenure);
+    }
+
+    if (expectedFlags.neverTenure != FlagsValue.getFlagBoolValue("NeverTenure", output)) {
+      throw new RuntimeException(
+            "Actual flag NeverTenure " + FlagsValue.getFlagBoolValue("NeverTenure", output) +
+            " is not equal to expected flag NeverTenure " + expectedFlags.neverTenure);
+    }
+
+    if (expectedFlags.initialTenuringThreshold != FlagsValue.getFlagLongValue("InitialTenuringThreshold", output)) {
+      throw new RuntimeException(
+            "Actual flag InitialTenuringThreshold " + FlagsValue.getFlagLongValue("InitialTenuringThreshold", output) +
+            " is not equal to expected flag InitialTenuringThreshold " + expectedFlags.initialTenuringThreshold);
+    }
+
+    if (expectedFlags.maxTenuringThreshold != FlagsValue.getFlagLongValue("MaxTenuringThreshold", output)) {
+      throw new RuntimeException(
+            "Actual flag MaxTenuringThreshold " + FlagsValue.getFlagLongValue("MaxTenuringThreshold", output) +
+            " is not equal to expected flag MaxTenuringThreshold " + expectedFlags.maxTenuringThreshold);
+    }
+  }
+}
+
+class ExpectedTenuringFlags {
+    public boolean alwaysTenure;
+    public boolean neverTenure;
+    public long initialTenuringThreshold;
+    public long maxTenuringThreshold;
+
+    public ExpectedTenuringFlags(boolean alwaysTenure,
+            boolean neverTenure,
+            long initialTenuringThreshold,
+            long maxTenuringThreshold) {
+      this.alwaysTenure = alwaysTenure;
+      this.neverTenure = neverTenure;
+      this.initialTenuringThreshold = initialTenuringThreshold;
+      this.maxTenuringThreshold = maxTenuringThreshold;
+    }
+    public ExpectedTenuringFlags() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestPrintGCDetails
+ * @bug 8035406 8027295 8035398
+ * @summary Ensure that the PrintGCDetails output for a minor GC with G1
+ * includes the expected necessary messages.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestGCLogMessages {
+  public static void main(String[] args) throws Exception {
+    testNormalLogs();
+    testWithToSpaceExhaustionLogs();
+  }
+
+  private static void testNormalLogs() throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                              "-Xmx10M",
+                                                              GCTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    output.shouldNotContain("[Redirty Cards");
+    output.shouldNotContain("[Code Root Purge");
+    output.shouldNotContain("[String Dedup Fixup");
+    output.shouldNotContain("[Young Free CSet");
+    output.shouldNotContain("[Non-Young Free CSet");
+    output.shouldHaveExitValue(0);
+
+    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-XX:+UseStringDeduplication",
+                                               "-Xmx10M",
+                                               "-XX:+PrintGCDetails",
+                                               GCTest.class.getName());
+
+    output = new OutputAnalyzer(pb.start());
+
+    output.shouldContain("[Redirty Cards");
+    output.shouldContain("[Code Root Purge");
+    output.shouldContain("[String Dedup Fixup");
+    output.shouldNotContain("[Young Free CSet");
+    output.shouldNotContain("[Non-Young Free CSet");
+    output.shouldHaveExitValue(0);
+
+    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-XX:+UseStringDeduplication",
+                                               "-Xmx10M",
+                                               "-XX:+PrintGCDetails",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               GCTest.class.getName());
+
+    output = new OutputAnalyzer(pb.start());
+
+    output.shouldContain("[Redirty Cards");
+    output.shouldContain("[Code Root Purge");
+    output.shouldContain("[String Dedup Fixup");
+    output.shouldContain("[Young Free CSet");
+    output.shouldContain("[Non-Young Free CSet");
+
+    // also check evacuation failure messages once
+    output.shouldNotContain("[Evacuation Failure");
+    output.shouldNotContain("[Recalculate Used");
+    output.shouldNotContain("[Remove Self Forwards");
+    output.shouldNotContain("[Restore RemSet");
+    output.shouldHaveExitValue(0);
+  }
+
+  private static void testWithToSpaceExhaustionLogs() throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xmx10M",
+                                               "-Xmn5M",
+                                               "-XX:+PrintGCDetails",
+                                               GCTestWithToSpaceExhaustion.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("[Evacuation Failure");
+    output.shouldNotContain("[Recalculate Used");
+    output.shouldNotContain("[Remove Self Forwards");
+    output.shouldNotContain("[Restore RemSet");
+    output.shouldHaveExitValue(0);
+
+    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xmx10M",
+                                               "-Xmn5M",
+                                               "-XX:+PrintGCDetails",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               GCTestWithToSpaceExhaustion.class.getName());
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("[Evacuation Failure");
+    output.shouldContain("[Recalculate Used");
+    output.shouldContain("[Remove Self Forwards");
+    output.shouldContain("[Restore RemSet");
+    output.shouldHaveExitValue(0);
+  }
+
+  static class GCTest {
+    private static byte[] garbage;
+    public static void main(String [] args) {
+      System.out.println("Creating garbage");
+      // create 128MB of garbage. This should result in at least one GC
+      for (int i = 0; i < 1024; i++) {
+        garbage = new byte[128 * 1024];
+      }
+      System.out.println("Done");
+    }
+  }
+
+  static class GCTestWithToSpaceExhaustion {
+    private static byte[] garbage;
+    private static byte[] largeObject;
+    public static void main(String [] args) {
+      largeObject = new byte[5*1024*1024];
+      System.out.println("Creating garbage");
+      // create 128MB of garbage. This should result in at least one GC,
+      // some of them with to-space exhaustion.
+      for (int i = 0; i < 1024; i++) {
+        garbage = new byte[128 * 1024];
+      }
+      System.out.println("Done");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationAgeThreshold
+ * @summary Test string deduplication age threshold
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationAgeThreshold {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testAgeThreshold();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationFullGC
+ * @summary Test string deduplication during full GC
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationFullGC {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testFullGC();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationInterned.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationInterned
+ * @summary Test string deduplication of interned strings
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationInterned {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testInterned();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationMemoryUsage.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationMemoryUsage
+ * @summary Test string deduplication memory usage
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationMemoryUsage {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testMemoryUsage();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationPrintOptions
+ * @summary Test string deduplication print options
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationPrintOptions {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testPrintOptions();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationTableRehash
+ * @summary Test string deduplication table rehash
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationTableRehash {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testTableRehash();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationTableResize
+ * @summary Test string deduplication table resize
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationTableResize {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testTableResize();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * Common code for string deduplication tests
+ */
+
+import java.lang.management.*;
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.*;
+import com.oracle.java.testlibrary.*;
+import sun.misc.*;
+
+class TestStringDeduplicationTools {
+    private static final String YoungGC = "YoungGC";
+    private static final String FullGC  = "FullGC";
+
+    private static final int Xmn = 50;  // MB
+    private static final int Xms = 100; // MB
+    private static final int Xmx = 100; // MB
+    private static final int MB = 1024 * 1024;
+    private static final int StringLength = 50;
+
+    private static Field valueField;
+    private static Unsafe unsafe;
+    private static byte[] dummy;
+
+    static {
+        try {
+            Field field = Unsafe.class.getDeclaredField("theUnsafe");
+            field.setAccessible(true);
+            unsafe = (Unsafe)field.get(null);
+
+            valueField = String.class.getDeclaredField("value");
+            valueField.setAccessible(true);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Object getValue(String string) {
+        try {
+            return valueField.get(string);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static void doFullGc(int numberOfTimes) {
+        for (int i = 0; i < numberOfTimes; i++) {
+            System.out.println("Begin: Full GC " + (i + 1) + "/" + numberOfTimes);
+            System.gc();
+            System.out.println("End: Full GC " + (i + 1) + "/" + numberOfTimes);
+        }
+    }
+
+    private static void doYoungGc(int numberOfTimes) {
+        // Provoke at least numberOfTimes young GCs
+        final int objectSize = 128;
+        final int maxObjectInYoung = (Xmn * MB) / objectSize;
+        for (int i = 0; i < numberOfTimes; i++) {
+            System.out.println("Begin: Young GC " + (i + 1) + "/" + numberOfTimes);
+            for (int j = 0; j < maxObjectInYoung + 1; j++) {
+                dummy = new byte[objectSize];
+            }
+            System.out.println("End: Young GC " + (i + 1) + "/" + numberOfTimes);
+        }
+    }
+
+    private static void forceDeduplication(int ageThreshold, String gcType) {
+        // Force deduplication to happen by either causing a FullGC or a YoungGC.
+        // We do several collections to also provoke a situation where the the
+        // deduplication thread needs to yield while processing the queue. This
+        // also tests that the references in the deduplication queue are adjusted
+        // accordingly.
+        if (gcType.equals(FullGC)) {
+            doFullGc(3);
+        } else {
+            doYoungGc(ageThreshold + 3);
+        }
+    }
+
+    private static String generateString(int id) {
+        StringBuilder builder = new StringBuilder(StringLength);
+
+        builder.append("DeduplicationTestString:" + id + ":");
+
+        while (builder.length() < StringLength) {
+            builder.append('X');
+        }
+
+        return builder.toString();
+    }
+
+    private static ArrayList<String> createStrings(int total, int unique) {
+        System.out.println("Creating strings: total=" + total + ", unique=" + unique);
+        if (total % unique != 0) {
+            throw new RuntimeException("Total must be divisible by unique");
+        }
+
+        ArrayList<String> list = new ArrayList<String>(total);
+        for (int j = 0; j < total / unique; j++) {
+            for (int i = 0; i < unique; i++) {
+                list.add(generateString(i));
+            }
+        }
+
+        return list;
+    }
+
+    private static void verifyStrings(ArrayList<String> list, int uniqueExpected) {
+        for (;;) {
+            // Check number of deduplicated strings
+            ArrayList<Object> unique = new ArrayList<Object>(uniqueExpected);
+            for (String string: list) {
+                Object value = getValue(string);
+                boolean uniqueValue = true;
+                for (Object obj: unique) {
+                    if (obj == value) {
+                        uniqueValue = false;
+                        break;
+                    }
+                }
+
+                if (uniqueValue) {
+                    unique.add(value);
+                }
+            }
+
+            System.out.println("Verifying strings: total=" + list.size() +
+                               ", uniqueFound=" + unique.size() +
+                               ", uniqueExpected=" + uniqueExpected);
+
+            if (unique.size() == uniqueExpected) {
+                System.out.println("Deduplication completed");
+                break;
+            } else {
+                System.out.println("Deduplication not completed, waiting...");
+
+                // Give the deduplication thread time to complete
+                try {
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
+    private static OutputAnalyzer runTest(String... extraArgs) throws Exception {
+        String[] defaultArgs = new String[] {
+            "-Xmn" + Xmn + "m",
+            "-Xms" + Xms + "m",
+            "-Xmx" + Xmx + "m",
+            "-XX:+UseG1GC",
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:+VerifyAfterGC" // Always verify after GC
+        };
+
+        ArrayList<String> args = new ArrayList<String>();
+        args.addAll(Arrays.asList(defaultArgs));
+        args.addAll(Arrays.asList(extraArgs));
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        System.err.println(output.getStderr());
+        System.out.println(output.getStdout());
+        return output;
+    }
+
+    private static class DeduplicationTest {
+        public static void main(String[] args) {
+            System.out.println("Begin: DeduplicationTest");
+
+            final int numberOfStrings = Integer.parseUnsignedInt(args[0]);
+            final int numberOfUniqueStrings = Integer.parseUnsignedInt(args[1]);
+            final int ageThreshold = Integer.parseUnsignedInt(args[2]);
+            final String gcType = args[3];
+
+            ArrayList<String> list = createStrings(numberOfStrings, numberOfUniqueStrings);
+            forceDeduplication(ageThreshold, gcType);
+            verifyStrings(list, numberOfUniqueStrings);
+
+            System.out.println("End: DeduplicationTest");
+        }
+
+        public static OutputAnalyzer run(int numberOfStrings, int ageThreshold, String gcType, String... extraArgs) throws Exception {
+            String[] defaultArgs = new String[] {
+                "-XX:+UseStringDeduplication",
+                "-XX:StringDeduplicationAgeThreshold=" + ageThreshold,
+                DeduplicationTest.class.getName(),
+                "" + numberOfStrings,
+                "" + numberOfStrings / 2,
+                "" + ageThreshold,
+                gcType
+            };
+
+            ArrayList<String> args = new ArrayList<String>();
+            args.addAll(Arrays.asList(extraArgs));
+            args.addAll(Arrays.asList(defaultArgs));
+
+            return runTest(args.toArray(new String[args.size()]));
+        }
+    }
+
+    private static class InternedTest {
+        public static void main(String[] args) {
+            // This test verifies that interned strings are always
+            // deduplicated when being interned, and never after
+            // being interned.
+
+            System.out.println("Begin: InternedTest");
+
+            final int ageThreshold = Integer.parseUnsignedInt(args[0]);
+            final String baseString = "DeduplicationTestString:" + InternedTest.class.getName();
+
+            // Create duplicate of baseString
+            StringBuilder sb1 = new StringBuilder(baseString);
+            String dupString1 = sb1.toString();
+            if (getValue(dupString1) == getValue(baseString)) {
+                throw new RuntimeException("Values should not match");
+            }
+
+            // Force baseString to be inspected for deduplication
+            // and be inserted into the deduplication hashtable.
+            forceDeduplication(ageThreshold, FullGC);
+
+            // Wait for deduplication to occur
+            while (getValue(dupString1) != getValue(baseString)) {
+                System.out.println("Waiting...");
+                try {
+                    Thread.sleep(100);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            // Create a new duplicate of baseString
+            StringBuilder sb2 = new StringBuilder(baseString);
+            String dupString2 = sb2.toString();
+            if (getValue(dupString2) == getValue(baseString)) {
+                throw new RuntimeException("Values should not match");
+            }
+
+            // Intern the new duplicate
+            Object beforeInternedValue = getValue(dupString2);
+            String internedString = dupString2.intern();
+            if (internedString != dupString2) {
+                throw new RuntimeException("String should match");
+            }
+            if (getValue(internedString) != getValue(baseString)) {
+                throw new RuntimeException("Values should match");
+            }
+
+            // Check original value of interned string, to make sure
+            // deduplication happened on the interned string and not
+            // on the base string
+            if (beforeInternedValue == getValue(baseString)) {
+                throw new RuntimeException("Values should not match");
+            }
+
+            System.out.println("End: InternedTest");
+        }
+
+        public static OutputAnalyzer run() throws Exception {
+            return runTest("-XX:+PrintGC",
+                           "-XX:+PrintGCDetails",
+                           "-XX:+UseStringDeduplication",
+                           "-XX:+PrintStringDeduplicationStatistics",
+                           "-XX:StringDeduplicationAgeThreshold=" + DefaultAgeThreshold,
+                           InternedTest.class.getName(),
+                           "" + DefaultAgeThreshold);
+        }
+    }
+
+    private static class MemoryUsageTest {
+        public static void main(String[] args) {
+            System.out.println("Begin: MemoryUsageTest");
+
+            final boolean useStringDeduplication = Boolean.parseBoolean(args[0]);
+            final int numberOfStrings = LargeNumberOfStrings;
+            final int numberOfUniqueStrings = 1;
+
+            ArrayList<String> list = createStrings(numberOfStrings, numberOfUniqueStrings);
+            forceDeduplication(DefaultAgeThreshold, FullGC);
+
+            if (useStringDeduplication) {
+                verifyStrings(list, numberOfUniqueStrings);
+            }
+
+            System.gc();
+            System.out.println("Heap Memory Usage: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed());
+
+            System.out.println("End: MemoryUsageTest");
+        }
+
+        public static OutputAnalyzer run(boolean useStringDeduplication) throws Exception {
+            String[] extraArgs = new String[0];
+
+            if (useStringDeduplication) {
+                extraArgs = new String[] {
+                    "-XX:+UseStringDeduplication",
+                    "-XX:+PrintStringDeduplicationStatistics",
+                    "-XX:StringDeduplicationAgeThreshold=" + DefaultAgeThreshold
+                };
+            }
+
+            String[] defaultArgs = new String[] {
+                "-XX:+PrintGC",
+                "-XX:+PrintGCDetails",
+                MemoryUsageTest.class.getName(),
+                "" + useStringDeduplication
+            };
+
+            ArrayList<String> args = new ArrayList<String>();
+            args.addAll(Arrays.asList(extraArgs));
+            args.addAll(Arrays.asList(defaultArgs));
+
+            return runTest(args.toArray(new String[args.size()]));
+        }
+    }
+
+    /*
+     * Tests
+     */
+
+    private static final int LargeNumberOfStrings = 10000;
+    private static final int SmallNumberOfStrings = 10;
+
+    private static final int MaxAgeThreshold      = 15;
+    private static final int DefaultAgeThreshold  = 3;
+    private static final int MinAgeThreshold      = 1;
+
+    private static final int TooLowAgeThreshold   = MinAgeThreshold - 1;
+    private static final int TooHighAgeThreshold  = MaxAgeThreshold + 1;
+
+    public static void testYoungGC() throws Exception {
+        // Do young GC to age strings to provoke deduplication
+        OutputAnalyzer output = DeduplicationTest.run(LargeNumberOfStrings,
+                                                      DefaultAgeThreshold,
+                                                      YoungGC,
+                                                      "-XX:+PrintGC",
+                                                      "-XX:+PrintStringDeduplicationStatistics");
+        output.shouldNotContain("Full GC");
+        output.shouldContain("GC pause (G1 Evacuation Pause) (young)");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testFullGC() throws Exception {
+        // Do full GC to age strings to provoke deduplication
+        OutputAnalyzer output = DeduplicationTest.run(LargeNumberOfStrings,
+                                                      DefaultAgeThreshold,
+                                                      FullGC,
+                                                      "-XX:+PrintGC",
+                                                      "-XX:+PrintStringDeduplicationStatistics");
+        output.shouldNotContain("GC pause (G1 Evacuation Pause) (young)");
+        output.shouldContain("Full GC");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testTableResize() throws Exception {
+        // Test with StringDeduplicationResizeALot
+        OutputAnalyzer output = DeduplicationTest.run(LargeNumberOfStrings,
+                                                      DefaultAgeThreshold,
+                                                      YoungGC,
+                                                      "-XX:+PrintGC",
+                                                      "-XX:+PrintStringDeduplicationStatistics",
+                                                      "-XX:+StringDeduplicationResizeALot");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldNotContain("Resize Count: 0");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testTableRehash() throws Exception {
+        // Test with StringDeduplicationRehashALot
+        OutputAnalyzer output = DeduplicationTest.run(LargeNumberOfStrings,
+                                                      DefaultAgeThreshold,
+                                                      YoungGC,
+                                                      "-XX:+PrintGC",
+                                                      "-XX:+PrintStringDeduplicationStatistics",
+                                                      "-XX:+StringDeduplicationRehashALot");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldNotContain("Rehash Count: 0");
+        output.shouldNotContain("Hash Seed: 0x0");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testAgeThreshold() throws Exception {
+        OutputAnalyzer output;
+
+        // Test with max age theshold
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       MaxAgeThreshold,
+                                       YoungGC,
+                                       "-XX:+PrintGC",
+                                       "-XX:+PrintStringDeduplicationStatistics");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+
+        // Test with min age theshold
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       MinAgeThreshold,
+                                       YoungGC,
+                                       "-XX:+PrintGC",
+                                       "-XX:+PrintStringDeduplicationStatistics");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+
+        // Test with too low age threshold
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       TooLowAgeThreshold,
+                                       YoungGC);
+        output.shouldContain("StringDeduplicationAgeThreshold of " + TooLowAgeThreshold +
+                             " is invalid; must be between " + MinAgeThreshold + " and " + MaxAgeThreshold);
+        output.shouldHaveExitValue(1);
+
+        // Test with too high age threshold
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       TooHighAgeThreshold,
+                                       YoungGC);
+        output.shouldContain("StringDeduplicationAgeThreshold of " + TooHighAgeThreshold +
+                             " is invalid; must be between " + MinAgeThreshold + " and " + MaxAgeThreshold);
+        output.shouldHaveExitValue(1);
+    }
+
+    public static void testPrintOptions() throws Exception {
+        OutputAnalyzer output;
+
+        // Test without PrintGC and without PrintStringDeduplicationStatistics
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       DefaultAgeThreshold,
+                                       YoungGC);
+        output.shouldNotContain("GC concurrent-string-deduplication");
+        output.shouldNotContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+
+        // Test with PrintGC but without PrintStringDeduplicationStatistics
+        output = DeduplicationTest.run(SmallNumberOfStrings,
+                                       DefaultAgeThreshold,
+                                       YoungGC,
+                                       "-XX:+PrintGC");
+        output.shouldContain("GC concurrent-string-deduplication");
+        output.shouldNotContain("Deduplicated:");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testInterned() throws Exception {
+        // Test that interned strings are deduplicated before being interned
+        OutputAnalyzer output = InternedTest.run();
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void testMemoryUsage() throws Exception {
+        // Test that memory usage is reduced after deduplication
+        OutputAnalyzer output;
+        final String usagePattern = "Heap Memory Usage: (\\d+)";
+
+        // Run without deduplication
+        output = MemoryUsageTest.run(false);
+        output.shouldHaveExitValue(0);
+        final long memoryUsageWithoutDedup = Long.parseLong(output.firstMatch(usagePattern, 1));
+
+        // Run with deduplication
+        output = MemoryUsageTest.run(true);
+        output.shouldHaveExitValue(0);
+        final long memoryUsageWithDedup = Long.parseLong(output.firstMatch(usagePattern, 1));
+
+        // Calculate expected memory usage with deduplication enabled. This calculation does
+        // not take alignment and padding into account, so it's a conservative estimate.
+        final long sizeOfChar = 2; // bytes
+        final long bytesSaved = (LargeNumberOfStrings - 1) * (StringLength * sizeOfChar + unsafe.ARRAY_CHAR_BASE_OFFSET);
+        final long memoryUsageWithDedupExpected = memoryUsageWithoutDedup - bytesSaved;
+
+        System.out.println("Memory usage summary:");
+        System.out.println("   memoryUsageWithoutDedup:      " + memoryUsageWithoutDedup);
+        System.out.println("   memoryUsageWithDedup:         " + memoryUsageWithDedup);
+        System.out.println("   memoryUsageWithDedupExpected: " + memoryUsageWithDedupExpected);
+
+        if (memoryUsageWithDedup > memoryUsageWithDedupExpected) {
+            throw new Exception("Unexpected memory usage, memoryUsageWithDedup should less or equal to memoryUsageWithDedupExpected");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestStringDeduplicationYoungGC
+ * @summary Test string deduplication during young GC
+ * @bug 8029075
+ * @key gc
+ * @library /testlibrary
+ */
+
+public class TestStringDeduplicationYoungGC {
+    public static void main(String[] args) throws Exception {
+        TestStringDeduplicationTools.testYoungGC();
+    }
+}
--- a/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java	Wed Jul 05 19:35:40 2017 +0200
@@ -26,7 +26,7 @@
  * @bug 8004924
  * @summary Checks that jmap -heap contains the flag CompressedClassSpaceSize
  * @library /testlibrary
- * @run main/othervm -XX:CompressedClassSpaceSize=50m CompressedClassSpaceSizeInJmapHeap
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:CompressedClassSpaceSize=50m CompressedClassSpaceSizeInJmapHeap
  */
 
 import com.oracle.java.testlibrary.*;
@@ -37,6 +37,11 @@
 
 public class CompressedClassSpaceSizeInJmapHeap {
     public static void main(String[] args) throws Exception {
+        if (!Platform.is64bit()) {
+            // Compressed Class Space is only available on 64-bit JVMs
+            return;
+        }
+
         String pid = Integer.toString(ProcessTools.getProcessId());
 
         JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
--- a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,7 +22,6 @@
  */
 
 /*
- * @ignore 8026154
  * @test
  * @bug 8005933
  * @summary Test that -Xshare:auto uses CDS when explicitly specified with -server.
@@ -50,21 +49,15 @@
 
         pb = ProcessTools.createJavaProcessBuilder(
             "-server", "-Xshare:auto", "-XX:+UnlockDiagnosticVMOptions",
-            "-XX:SharedArchiveFile=./sample.jsa", "-version");
+            "-XX:SharedArchiveFile=./sample.jsa", "-XX:+PrintSharedSpaces", "-version");
         output = new OutputAnalyzer(pb.start());
         try {
             output.shouldContain("sharing");
-            output.shouldHaveExitValue(0);
         } catch (RuntimeException e) {
-            // If this failed then check that it would also be unable
-            // to share even if -Xshare:on is specified.  If so, then
-            // return a success status.
-            pb = ProcessTools.createJavaProcessBuilder(
-                "-server", "-Xshare:on", "-XX:+UnlockDiagnosticVMOptions",
-                "-XX:SharedArchiveFile=./sample.jsa", "-version");
-            output = new OutputAnalyzer(pb.start());
-            output.shouldContain("Unable to use shared archive");
-            output.shouldHaveExitValue(1);
+            // if sharing failed due to ASLR or similar reasons,
+            // check whether sharing was attempted at all (UseSharedSpaces)
+            output.shouldContain("UseSharedSpaces:");
         }
+        output.shouldHaveExitValue(0);
     }
 }
--- a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java	Wed Jul 05 19:35:40 2017 +0200
@@ -26,10 +26,7 @@
  * @key nmt jcmd
  * @summary Verify that jcmd correctly reports that NMT is not enabled
  * @library /testlibrary
- * First run without enabling NMT
- * @run main/othervm JcmdWithNMTDisabled
- * Then run with explicitly disabling NMT, should not be any difference
- * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled
+ * @run main JcmdWithNMTDisabled 1
  */
 
 import com.oracle.java.testlibrary.*;
@@ -39,6 +36,27 @@
   static String pid;
 
   public static void main(String args[]) throws Exception {
+
+    // This test explicitly needs to be run with the exact command lines below, not passing on
+    // arguments from the parent VM is a conscious choice to avoid NMT being turned on.
+    if (args.length > 0) {
+      ProcessBuilder pb;
+      OutputAnalyzer output;
+      String testjdkPath = System.getProperty("test.jdk");
+
+      // First run without enabling NMT
+      pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "JcmdWithNMTDisabled");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldHaveExitValue(0);
+
+      // Then run with explicitly disabling NMT, should not be any difference
+      pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "-XX:NativeMemoryTracking=off", "JcmdWithNMTDisabled");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldHaveExitValue(0);
+
+      return;
+    }
+
     // Grab my own PID
     pid = Integer.toString(ProcessTools.getProcessId());
 
--- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,7 +22,6 @@
  */
 
 /*
- * @ignore 8025642
  * @test CdsDifferentObjectAlignment
  * @summary Testing CDS (class data sharing) using varying object alignment.
  *          Using different object alignment for each dump/load pair.
@@ -84,7 +83,11 @@
             createAlignment,
             loadAlignment);
 
-        output.shouldContain(expectedErrorMsg);
+        try {
+            output.shouldContain(expectedErrorMsg);
+        } catch (RuntimeException e) {
+            output.shouldContain("Unable to use shared archive");
+        }
         output.shouldHaveExitValue(1);
     }
 }
--- a/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java	Wed Jul 05 19:35:40 2017 +0200
@@ -22,7 +22,6 @@
  */
 
 /*
- * @ignore 8032222
  * @test CdsWriteError
  * @summary Test how VM handles situation when it is impossible to write the
  *          CDS archive. VM is expected to exit gracefully and display the
@@ -46,6 +45,12 @@
             return;
         }
 
+        // This test has been unstable for Mac OSx (see JDK-8032222)
+        if (Platform.isOSX()) {
+            System.out.println("This test is skipped on Mac");
+            return;
+        }
+
         String folderName = "tmp";
         String fileName = folderName + File.separator + "empty.jsa";
 
--- a/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java	Wed Jul 05 19:35:40 2017 +0200
@@ -22,7 +22,6 @@
  */
 
 /*
- * @ignore 8032224
  * @test DefaultUseWithClient
  * @summary Test default behavior of sharing with -client
  * @library /testlibrary
@@ -57,10 +56,17 @@
            "-XX:+UnlockDiagnosticVMOptions",
            "-XX:SharedArchiveFile=./" + fileName,
            "-client",
+           "-XX:+PrintSharedSpaces",
            "-version");
 
         output = new OutputAnalyzer(pb.start());
-        output.shouldContain("sharing");
+        try {
+            output.shouldContain("sharing");
+        } catch (RuntimeException e) {
+            // if sharing failed due to ASLR or similar reasons,
+            // check whether sharing was attempted at all (UseSharedSpaces)
+            output.shouldContain("UseSharedSpaces:");
+        }
         output.shouldHaveExitValue(0);
    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/8036666/GetObjectLockCount.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2014 SAP AG.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.jdi.AbsentInformationException;
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.Location;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.Connector.Argument;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.VMStartException;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.ClassPrepareEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.EventQueue;
+import com.sun.jdi.event.EventSet;
+import com.sun.jdi.event.VMDeathEvent;
+import com.sun.jdi.event.VMDisconnectEvent;
+import com.sun.jdi.event.VMStartEvent;
+import com.sun.jdi.request.BreakpointRequest;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.EventRequestManager;
+
+
+/*
+ * @test GetObjectLockCount.java
+ * @bug 8036666
+ * @key regression
+ * @summary verify jvm returns correct lock recursion count
+ * @run compile -g RecursiveObjectLock.java
+ * @run main/othervm GetObjectLockCount
+ * @author axel.siebenborn@sap.com
+ */
+
+public class GetObjectLockCount {
+
+    public static final String CLASS_NAME  = "RecursiveObjectLock";
+    public static final String METHOD_NAME = "breakpoint1";
+    public static final String ARGUMENTS = "";
+
+
+    /**
+     * Find a com.sun.jdi.CommandLineLaunch connector
+     */
+    static LaunchingConnector findLaunchingConnector() {
+        List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
+        Iterator <Connector> iter = connectors.iterator();
+        while (iter.hasNext()) {
+            Connector connector = iter.next();
+            if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) {
+                return (LaunchingConnector)connector;
+            }
+        }
+        throw new Error("No launching connector");
+    }
+
+    static VirtualMachine launchTarget(String mainArgs) {
+        LaunchingConnector connector = findLaunchingConnector();
+        Map<String, Argument>  arguments = connectorArguments(connector, mainArgs);
+        try {
+            return (VirtualMachine) connector.launch(arguments);
+        } catch (IOException exc) {
+            throw new Error("Unable to launch target VM: " + exc);
+        } catch (IllegalConnectorArgumentsException exc) {
+            throw new Error("Internal error: " + exc);
+        } catch (VMStartException exc) {
+            throw new Error("Target VM failed to initialize: " +
+                    exc.getMessage());
+        }
+    }
+    /**
+     * Return the launching connector's arguments.
+     */
+    static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
+        Map<String,Connector.Argument> arguments = connector.defaultArguments();
+
+        Connector.Argument mainArg = (Connector.Argument)arguments.get("main");
+        if (mainArg == null) {
+            throw new Error("Bad launching connector");
+        }
+        mainArg.setValue(mainArgs);
+
+        Connector.Argument optionsArg = (Connector.Argument)arguments.get("options");
+        if (optionsArg == null) {
+            throw new Error("Bad launching connector");
+        }
+        optionsArg.setValue(ARGUMENTS);
+        return arguments;
+    }
+
+    private static void addClassWatch(VirtualMachine vm) {
+        EventRequestManager erm = vm.eventRequestManager();
+        ClassPrepareRequest classPrepareRequest = erm
+                .createClassPrepareRequest();
+        classPrepareRequest.addClassFilter(CLASS_NAME);
+        classPrepareRequest.setEnabled(true);
+    }
+
+    private static void addBreakpoint(VirtualMachine vm, ReferenceType refType) {
+        Location breakpointLocation = null;
+        List<Location> locs;
+        try {
+            locs = refType.allLineLocations();
+            for (Location loc: locs) {
+                if (loc.method().name().equals(METHOD_NAME)) {
+                    breakpointLocation = loc;
+                    break;
+                }
+            }
+        } catch (AbsentInformationException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        if (breakpointLocation != null) {
+            EventRequestManager evtReqMgr = vm.eventRequestManager();
+            BreakpointRequest bReq = evtReqMgr.createBreakpointRequest(breakpointLocation);
+            bReq.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);
+            bReq.enable();
+        }
+    }
+
+    /**
+     * @param args
+     * @throws InterruptedException
+     */
+    public static void main(String[] args) throws InterruptedException  {
+
+        VirtualMachine vm = launchTarget(CLASS_NAME);
+
+        // process events
+        EventQueue eventQueue = vm.eventQueue();
+        // resume the vm
+        boolean launched = false;
+
+        while (!launched) {
+            EventSet eventSet = eventQueue.remove();
+            for (Event event : eventSet) {
+                if (event instanceof VMStartEvent) {
+                    System.out.println("Vm launched");
+                    // set watch field on already loaded classes
+                    List<ReferenceType> referenceTypes = vm.classesByName(CLASS_NAME);
+                    for (ReferenceType refType : referenceTypes) {
+                        System.out.println("Found Class");
+                        addBreakpoint(vm, refType);
+                    }
+
+                    // watch for loaded classes
+                    addClassWatch(vm);
+                    vm.resume();
+                    launched = true;
+                }
+            }
+        }
+
+        Process process = vm.process();
+
+        // Copy target's output and error to our output and error.
+        Thread outThread = new StreamRedirectThread("out reader", process.getInputStream());
+        Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream());
+
+        int recursionCount = -1;
+
+        errThread.start();
+        outThread.start();
+        boolean connected = true;
+        while (connected) {
+            EventSet eventSet = eventQueue.remove();
+            for (Event event : eventSet) {
+                if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) {
+                    // exit
+                    connected = false;
+                }
+                else if (event instanceof ClassPrepareEvent) {
+                    // watch field on loaded class
+                    System.out.println("ClassPrepareEvent");
+                    ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event;
+                    ReferenceType refType = classPrepEvent.referenceType();
+                    addBreakpoint(vm, refType);
+                } else if (event instanceof BreakpointEvent) {
+                    recursionCount = getLockRecursions(vm);
+                    System.out.println("resume...");
+                }
+            }
+            eventSet.resume();
+        }
+        // Shutdown begins when event thread terminates
+        try {
+            errThread.join(); // Make sure output is forwarded
+            outThread.join();
+        } catch (InterruptedException e) {
+            // we don't interrupt
+            e.printStackTrace();
+        }
+        if (recursionCount != 3) {
+            throw new AssertionError("recursions: expected 3, but was " + recursionCount);
+        }
+    }
+
+    public static int getLockRecursions(VirtualMachine vm) {
+        List <ThreadReference> threads = vm.allThreads();
+        for (ThreadReference thread : threads) {
+            if (thread.name().equals("main")) {
+
+                System.out.println("Found main thread.");
+                try{
+                    StackFrame frame = thread.frame(3);
+                    return frame.thisObject().entryCount();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            System.out.println("Main thread not found!");
+        }
+        return -1;
+    }
+}
+
+class StreamRedirectThread extends Thread {
+
+    private final BufferedReader in;
+
+    private static final int BUFFER_SIZE = 2048;
+
+    /**
+     * Set up for copy.
+     * @param name  Name of the thread
+     * @param in    Stream to copy from
+     */
+    StreamRedirectThread(String name, InputStream in) {
+        super(name);
+        this.in = new BufferedReader(new InputStreamReader(in));
+    }
+
+    /**
+     * Copy.
+     */
+    public void run() {
+        try {
+            String line;
+            while ((line = in.readLine ()) != null) {
+                System.out.println("testvm: " + line);
+            }
+            System.out.flush();
+        } catch(IOException exc) {
+            System.err.println("Child I/O Transfer - " + exc);
+            exc.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/8036666/RecursiveObjectLock.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 SAP AG.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class RecursiveObjectLock {
+
+    public void testMethod() {
+        synchronized (this) {
+            nestedLock1();
+        }
+    }
+
+    public void nestedLock1() {
+        synchronized (this) {
+            nestedLock2();
+        }
+    }
+
+    public void nestedLock2() {
+        synchronized (this) {
+            callWait();
+        }
+    }
+
+    public void callWait(){
+        try {
+            this.wait(1);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        breakpoint1();
+    }
+
+    public static void breakpoint1() {
+        // purpose: hold a breakpoint
+    }
+
+    public static void main(String[] args) {
+        RecursiveObjectLock ro = new RecursiveObjectLock();
+        ro.testMethod();
+        System.out.println("ready");
+    }
+
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java	Wed Jul 05 19:35:40 2017 +0200
@@ -378,6 +378,64 @@
         }
     }
 
+    /**
+     * Asserts that two strings are equal.
+     *
+     * If strings are not equals, then exception message
+     * will contain {@code msg} followed by list of mismatched lines.
+     *
+     * @param str1 First string to compare.
+     * @param str2 Second string to compare.
+     * @param msg A description of the assumption.
+     * @throws RuntimeException if strings are not equal.
+     */
+    public static void assertStringsEqual(String str1, String str2,
+                                          String msg) {
+        String lineSeparator = System.getProperty("line.separator");
+        String str1Lines[] = str1.split(lineSeparator);
+        String str2Lines[] = str2.split(lineSeparator);
+
+        int minLength = Math.min(str1Lines.length, str2Lines.length);
+        String longestStringLines[] = ((str1Lines.length == minLength) ?
+                                       str2Lines : str1Lines);
+
+        boolean stringsAreDifferent = false;
+
+        StringBuilder messageBuilder = new StringBuilder(msg);
+
+        messageBuilder.append("\n");
+
+        for (int line = 0; line < minLength; line++) {
+            if (!str1Lines[line].equals(str2Lines[line])) {
+                messageBuilder.append(String.
+                                      format("[line %d] '%s' differs " +
+                                             "from '%s'\n",
+                                             line,
+                                             str1Lines[line],
+                                             str2Lines[line]));
+                stringsAreDifferent = true;
+            }
+        }
+
+        if (minLength < longestStringLines.length) {
+            String stringName = ((longestStringLines == str1Lines) ?
+                                 "first" : "second");
+            messageBuilder.append(String.format("Only %s string contains " +
+                                                "following lines:\n",
+                                                stringName));
+            stringsAreDifferent = true;
+            for(int line = minLength; line < longestStringLines.length; line++) {
+                messageBuilder.append(String.
+                                      format("[line %d] '%s'", line,
+                                             longestStringLines[line]));
+            }
+        }
+
+        if (stringsAreDifferent) {
+            error(messageBuilder.toString());
+        }
+    }
+
     private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) {
         assertNotNull(lhs, msg);
         assertNotNull(rhs, msg);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 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.
+ */
+package com.oracle.java.testlibrary;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import java.lang.management.ManagementFactory;
+
+/**
+ * Simple class to check writeability, invalid and valid values for VMOption
+ */
+public class DynamicVMOptionChecker {
+
+    /**
+     * Reads VM option from PlatformMXBean and parse it to integer value
+     *
+     * @param name of option
+     * @return parsed value
+     */
+    public static int getIntValue(String name) {
+
+        VMOption option = ManagementFactory.
+                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+                getVMOption(name);
+
+        return Integer.parseInt(option.getValue());
+    }
+
+    /**
+     * Sets VM option value
+     *
+     * @param name of option
+     * @param value to set
+     */
+    public static void setIntValue(String name, int value) {
+        ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class).setVMOption(name, Integer.toString(value));
+    }
+
+    /**
+     * Checks that VM option is dynamically writable
+     *
+     * @param name
+     * @throws RuntimeException if option if not writable
+     * @return always true
+     */
+    public static boolean checkIsWritable(String name) {
+        VMOption option = ManagementFactory.
+                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+                getVMOption(name);
+
+        if (!option.isWriteable()) {
+            throw new RuntimeException(name + " is not writable");
+        }
+
+        return true;
+    }
+
+    /**
+     * Checks that value cannot be set
+     *
+     * @param name of flag
+     * @param value string representation of value to set
+     * @throws RuntimeException on error - when expected exception hasn't been thrown
+     */
+    public static void checkInvalidValue(String name, String value) {
+        // should throw
+        try {
+            ManagementFactory.
+                    getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+                    setVMOption(name, value);
+
+        } catch (IllegalArgumentException e) {
+            return;
+        }
+
+        throw new RuntimeException("Expected IllegalArgumentException was not thrown, " + name + "= " + value);
+    }
+
+    /**
+     * Checks that value can be set
+     *
+     * @param name of flag to set
+     * @param value string representation of value to set
+     * @throws RuntimeException on error - when value in VM is not equal to origin
+     */
+    public static void checkValidValue(String name, String value) {
+        ManagementFactory.
+                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+                setVMOption(name, value);
+
+        VMOption option = ManagementFactory.
+                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+                getVMOption(name);
+
+        if (!option.getValue().equals(value)) {
+            throw new RuntimeException("Actual value of " + name + " \"" + option.getValue()
+                    + "\" not equal origin \"" + value + "\"");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ExitCode.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+/**
+ * Exit code values that could be returned by the JVM.
+ */
+public enum ExitCode {
+    OK(0),
+    FAIL(1),
+    CRASH(134);
+
+    public final int value;
+
+    ExitCode(int value) {
+        this.value = value;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 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.
+ */
+package com.oracle.java.testlibrary;
+
+/**
+ * Simple class to check writeability, invalid and valid values for concrete VMOption
+ */
+public class TestDynamicVMOption {
+
+    private final String name;
+    private final int value;
+
+    /**
+     * Constructor
+     *
+     * @param name of VM option to test
+     */
+    public TestDynamicVMOption(String name) {
+        this.name = name;
+        this.value = DynamicVMOptionChecker.getIntValue(name);
+        System.out.println(this.name + " = " + this.value);
+    }
+
+    /**
+     * Checks that this value can accept valid percentage values and cannot accept invalid percentage values
+     *
+     * @throws RuntimeException
+     */
+    public void testPercentageValues() {
+        checkInvalidValue(Integer.toString(Integer.MIN_VALUE));
+        checkInvalidValue(Integer.toString(Integer.MAX_VALUE));
+        checkInvalidValue("-10");
+        checkInvalidValue("190");
+    }
+
+    /**
+     * Reads VM option from PlatformMXBean and parse it to integer value
+     *
+     * @return value
+     */
+    public int getIntValue() {
+        return DynamicVMOptionChecker.getIntValue(this.name);
+    }
+
+    /**
+     * Sets VM option value
+     *
+     * @param value to set
+     */
+    public void setIntValue(int value) {
+        DynamicVMOptionChecker.setIntValue(this.name, value);
+    }
+
+    /**
+     * Checks that this VM option is dynamically writable
+     *
+     * @throws RuntimeException if option if not writable
+     * @return true
+     */
+    public boolean checkIsWritable() throws RuntimeException {
+        return DynamicVMOptionChecker.checkIsWritable(this.name);
+    }
+
+    /**
+     * Checks that value for this VM option cannot be set
+     *
+     * @param value to check
+     * @throws RuntimeException on error - when expected exception hasn't been thrown
+     */
+    public void checkInvalidValue(String value) {
+        DynamicVMOptionChecker.checkInvalidValue(this.name, value);
+    }
+
+    /**
+     * Checks that value for this VM option can be set
+     *
+     * @param value to check
+     * @throws RuntimeException on error - when value in VM is not equal to origin
+     */
+    public void checkValidValue(String value) {
+        DynamicVMOptionChecker.checkValidValue(this.name, value);
+    }
+
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -108,6 +108,40 @@
     }
 
     /**
+     * Returns the default JTReg arguments for a jvm running a test without
+     * options that matches regular expresions in {@code filters}.
+     * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+     * @param filters Regular expressions used to filter out options.
+     * @return An array of options, or an empty array if no opptions.
+     */
+    public static String[] getFilteredTestJavaOpts(String... filters) {
+        String options[] = getTestJavaOpts();
+
+        if (filters.length == 0) {
+            return options;
+        }
+
+        List<String> filteredOptions = new ArrayList<String>(options.length);
+        Pattern patterns[] = new Pattern[filters.length];
+        for (int i = 0; i < filters.length; i++) {
+            patterns[i] = Pattern.compile(filters[i]);
+        }
+
+        for (String option : options) {
+            boolean matched = false;
+            for (int i = 0; i < patterns.length && !matched; i++) {
+                Matcher matcher = patterns[i].matcher(option);
+                matched = matcher.find();
+            }
+            if (!matched) {
+                filteredOptions.add(option);
+            }
+        }
+
+        return filteredOptions.toArray(new String[filteredOptions.size()]);
+    }
+
+    /**
      * Combines given arguments with default JTReg arguments for a jvm running a test.
      * This is the combination of JTReg arguments test.vm.opts and test.java.opts
      * @return The combination of JTReg test java options and user args.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package com.oracle.java.testlibrary.cli;
+
+import sun.hotspot.cpuinfo.CPUInfo;
+import com.oracle.java.testlibrary.*;
+
+/**
+ * Base class for command line options tests that
+ * requires specific CPU arch or specific CPU features.
+ */
+public abstract class CPUSpecificCommandLineOptionTest
+              extends CommandLineOptionTest {
+
+    private String cpuArchPattern;
+    private String supportedCPUFeatures[];
+    private String unsupportedCPUFeatures[];
+
+    /**
+     * Create new CPU specific test instance that does not
+     * require any CPU features.
+     *
+     * @param cpuArchPattern Regular expression that should
+     *                       match os.arch.
+     */
+    public CPUSpecificCommandLineOptionTest(String cpuArchPattern) {
+        this(cpuArchPattern, null, null);
+    }
+
+    /**
+     * Create new CPU specific test instance that does not
+     * require from CPU support of {@code supportedCPUFeatures} features
+     * and no support of {@code unsupportedCPUFeatures}.
+     *
+     * @param cpuArchPattern Regular expression that should
+     *                       match os.arch.
+     * @param supportedCPUFeatures Array with names of features that
+     *                             should be supported by CPU. If <b>null</b>,
+     *                             then no features have to be supported.
+     * @param unsupportedCPUFeatures Array with names of features that
+     *                               should not be supported by CPU.
+     *                               If <b>null</b>, then CPU may support any
+     *                               features.
+     */
+    public CPUSpecificCommandLineOptionTest(String cpuArchPattern,
+                                            String supportedCPUFeatures[],
+                                            String unsupportedCPUFeatures[]) {
+        this.cpuArchPattern = cpuArchPattern;
+        this.supportedCPUFeatures = supportedCPUFeatures;
+        this.unsupportedCPUFeatures = unsupportedCPUFeatures;
+    }
+
+    /**
+     * Check that CPU on test box has appropriate architecture, support all
+     * required features and does not support all features that should not be
+     * supported.
+     *
+     * @return <b>true</b> if CPU on test box fulfill all requirements.
+     */
+    @Override
+    public boolean checkPreconditions() {
+        if (!Platform.getOsArch().matches(cpuArchPattern)) {
+            System.out.println("CPU arch does not match " + cpuArchPattern);
+            return false;
+        }
+
+        if (supportedCPUFeatures != null) {
+            for (String feature : supportedCPUFeatures) {
+                if (!CPUInfo.hasFeature(feature)) {
+                    System.out.println("CPU does not support " + feature +
+                                       " feature");
+                    return false;
+                }
+            }
+        }
+
+        if (unsupportedCPUFeatures != null) {
+            for (String feature : unsupportedCPUFeatures) {
+                if (CPUInfo.hasFeature(feature)) {
+                    System.out.println("CPU support " + feature + " feature");
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package com.oracle.java.testlibrary.cli;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import com.oracle.java.testlibrary.*;
+
+/**
+ * Base class for command line option tests.
+ */
+public abstract class CommandLineOptionTest {
+
+    public static final String UNRECOGNIZED_OPTION_ERROR_FORMAT =
+        "Unrecognized VM option '[+-]?%s'";
+
+    public static final String printFlagsFinalFormat = "%s\\s*:?=\\s*%s";
+
+    /**
+     * Verify that JVM startup behaviour matches our expectations.
+     *
+     * @param option The option that should be passed to JVM
+     * @param excpectedMessages Array of patterns that should occur
+     *                          in JVM output. If <b>null</b> then
+     *                          JVM output could be empty.
+     * @param unexpectedMessages Array of patterns that should not
+     *                           occur in JVM output. If <b>null</b> then
+     *                          JVM output could be empty.
+     * @param exitCode expected exit code.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifyJVMStartup(String option,
+                                        String expectedMessages[],
+                                        String unexpectedMessages[],
+                                        ExitCode exitCode)
+                                 throws Throwable {
+
+        OutputAnalyzer outputAnalyzer =
+            ProcessTools.executeTestJvm(option, "-version");
+
+        outputAnalyzer.shouldHaveExitValue(exitCode.value);
+
+        if (expectedMessages != null) {
+            for (String expectedMessage : expectedMessages) {
+                outputAnalyzer.shouldMatch(expectedMessage);
+            }
+        }
+
+        if (unexpectedMessages != null) {
+            for (String unexpectedMessage : unexpectedMessages) {
+                outputAnalyzer.shouldNotMatch(unexpectedMessage);
+            }
+        }
+    }
+
+    /**
+     * Verify that value of specified JVM option is the same as
+     * expected value.
+     * This method filter out option with {@code optionName}
+     * name from test java options.
+     *
+     * @param optionName Name of tested option.
+     * @param expectedValue Expected value of tested option.
+     * @param additionalVMOpts Additonal options that should be
+     *                         passed to JVM.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifyOptionValue(String optionName,
+                                         String expectedValue,
+                                         String... additionalVMOpts)
+                                  throws Throwable {
+        verifyOptionValue(optionName, expectedValue, true, additionalVMOpts);
+    }
+
+    /**
+     * Verify that value of specified JVM option is the same as
+     * expected value.
+     * This method filter out option with {@code optionName}
+     * name from test java options.
+     *
+     * @param optionName Name of tested option.
+     * @param expectedValue Expected value of tested option.
+     * @param addTestVmOptions If <b>true</b>, then test VM options
+     *                         will be used.
+     * @param additionalVMOpts Additonal options that should be
+     *                         passed to JVM.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifyOptionValue(String optionName,
+                                         String expectedValue,
+                                         boolean addTestVmOptions,
+                                         String... additionalVMOpts)
+                                  throws Throwable {
+
+        List<String> vmOpts = new ArrayList<String>();
+
+        if (addTestVmOptions) {
+            Collections.addAll(vmOpts,
+                               Utils.getFilteredTestJavaOpts(optionName));
+        }
+        Collections.addAll(vmOpts, additionalVMOpts);
+        Collections.addAll(vmOpts, new String[] {
+                "-XX:+PrintFlagsFinal",
+                "-version"
+            });
+
+        ProcessBuilder processBuilder =
+            ProcessTools.
+            createJavaProcessBuilder(vmOpts.
+                                     toArray(new String[vmOpts.size()]));
+
+        OutputAnalyzer outputAnalyzer =
+            new OutputAnalyzer(processBuilder.start());
+
+        outputAnalyzer.shouldHaveExitValue(0);
+        outputAnalyzer.shouldMatch(String.
+                                   format(printFlagsFinalFormat,
+                                          optionName,
+                                          expectedValue));
+    }
+
+
+    /**
+     * Run command line option test.
+     *
+     * @throws Throwable if test failed.
+     */
+    public final void test() throws Throwable {
+        if (checkPreconditions()) {
+            runTestCases();
+        }
+    }
+
+    /**
+     * Check that all preconditions for test execution are met.
+     *
+     * @return <b>true</b> if test could be executed.
+     */
+    public boolean checkPreconditions() {
+        return true;
+    }
+
+    /**
+     * Run test cases.
+     *
+     * @throws Throwable if test failed.
+     */
+    public abstract void runTestCases() throws Throwable;
+}
+
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Fri Apr 11 14:07:25 2014 -0700
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Wed Jul 05 19:35:40 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -135,6 +135,7 @@
   public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
   public native void    clearMethodState(Executable method);
   public native int     getMethodEntryBci(Executable method);
+  public native Object[] getNMethod(Executable method, boolean isOsr);
 
   // Intered strings
   public native boolean isInStringTable(String str);
@@ -150,4 +151,7 @@
   public native void runMemoryUnitTests();
   public native void readFromNoaccessArea();
 
+  // CPU features
+  public native String getCPUFeatures();
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+package sun.hotspot.code;
+
+import java.lang.reflect.Executable;
+import sun.hotspot.WhiteBox;
+
+public class NMethod {
+  private static final WhiteBox wb = WhiteBox.getWhiteBox();
+  public static NMethod get(Executable method, boolean isOsr) {
+    Object[] obj = wb.getNMethod(method, isOsr);
+    return obj == null ? null : new NMethod(obj);
+  }
+  private NMethod(Object[] obj) {
+    assert obj.length == 2;
+    comp_level = (Integer) obj[0];
+    insts = (byte[]) obj[1];
+  }
+  public byte[] insts;
+  public int comp_level;
+
+  @Override
+  public String toString() {
+    return "NMethod{" +
+        "insts=" + insts +
+        ", comp_level=" + comp_level +
+        '}';
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java	Wed Jul 05 19:35:40 2017 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+package sun.hotspot.cpuinfo;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import sun.hotspot.WhiteBox;
+
+/**
+ * Information about CPU on test box.
+ *
+ * CPUInfo uses WhiteBox to gather information,
+ * so WhiteBox class should be added to bootclasspath
+ * and option -XX:+WhiteBoxAPI should expclicetly
+ * specified on command line.
+ */
+public class CPUInfo {
+
+    private static final List<String> features;
+    private static final String additionalCPUInfo;
+
+    static {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+
+        Pattern additionalCPUInfoRE =
+            Pattern.compile("([^(]*\\([^)]*\\)[^,]*),\\s*");
+
+        String cpuFeaturesString = wb.getCPUFeatures();
+        Matcher matcher = additionalCPUInfoRE.matcher(cpuFeaturesString);
+        if (matcher.find()) {
+            additionalCPUInfo = matcher.group(1);
+        } else {
+            additionalCPUInfo = "";
+        }
+        String splittedFeatures[] = matcher.replaceAll("").split("(, )| ");
+
+        features = Collections.unmodifiableList(Arrays.
+                                                asList(splittedFeatures));
+    }
+
+    /**
+     * Get additional information about CPU.
+     * For example, on X86 in will be family/model/stepping
+     * and number of cores.
+     *
+     * @return additional CPU info
+     */
+    public static String getAdditionalCPUInfo() {
+        return additionalCPUInfo;
+    }
+
+    /**
+     * Get all known features supported by CPU.
+     *
+     * @return unmodifiable list with names of all known features
+     *         supported by CPU.
+     */
+    public static List<String> getFeatures() {
+        return features;
+    }
+
+    /**
+     * Check if some feature is supported by CPU.
+     *
+     * @param feature Name of feature to be tested.
+     * @return <b>true</b> if tested feature is supported by CPU.
+     */
+    public static boolean hasFeature(String feature) {
+        return features.contains(feature.toLowerCase());
+    }
+}
--- a/make/common/NativeCompilation.gmk	Fri Apr 11 14:07:25 2014 -0700
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 19:35:40 2017 +0200
@@ -369,6 +369,10 @@
     $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION))
   endif
 
+  # Add sys root specific cflags last
+  $1_EXTRA_CFLAGS += $(SYSROOT_CFLAGS)
+  $1_EXTRA_CXXFLAGS += $(SYSROOT_CFLAGS)
+
   # Now call add_native_source for each source file we are going to compile.
   $$(foreach p,$$($1_SRCS), \
       $$(eval $$(call add_native_source,$1,$$p,$$($1_OBJECT_DIR), \
@@ -414,6 +418,8 @@
     $1_EXTRA_LDFLAGS += $(call SET_SHARED_LIBRARY_MAPFILE,$$($1_REAL_MAPFILE))
   endif
 
+  $1_EXTRA_LDFLAGS += $(SYSROOT_LDFLAGS)
+
   # Need to make sure TARGET is first on list
   $1 := $$($1_TARGET)
   ifeq ($$($1_STATIC_LIBRARY),)
@@ -476,7 +482,7 @@
             # to be rebuilt properly.
             $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
 		$(CD) $$($1_OBJECT_DIR) \
-		&& $(ZIP) -q $$@ $$($1_DEBUGINFO_FILES)
+		&& $(ZIP) -q $$@ $$(notdir $$($1_DEBUGINFO_FILES))
 
           else
             $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_FILES))
--- a/make/devkit/Makefile	Fri Apr 11 14:07:25 2014 -0700
+++ b/make/devkit/Makefile	Wed Jul 05 19:35:40 2017 +0200
@@ -75,7 +75,7 @@
   $(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me)))
 endif
 
-OUTPUT_ROOT = $(abspath ../../../build/devkit)
+OUTPUT_ROOT = $(abspath ../../build/devkit)
 RESULT = $(OUTPUT_ROOT)/result
 
 submakevars = HOST=$@ BUILD=$(me) \
--- a/make/devkit/Tools.gmk	Fri Apr 11 14:07:25 2014 -0700
+++ b/make/devkit/Tools.gmk	Wed Jul 05 19:35:40 2017 +0200
@@ -49,8 +49,8 @@
 # Define external dependencies
 
 # Latest that could be made to work.
-gcc_ver := gcc-4.7.3
-binutils_ver := binutils-2.22
+gcc_ver := gcc-4.8.2
+binutils_ver := binutils-2.24
 ccache_ver := ccache-3.1.9
 mpfr_ver := mpfr-3.0.1
 gmp_ver := gmp-4.3.2
@@ -64,6 +64,7 @@
 MPC := http://www.multiprecision.org/mpc/download/${mpc_ver}.tar.gz
 
 # RPMs in OEL5.5
+LINUX_VERSION := OEL5.5
 RPM_LIST := \
     kernel-headers \
     glibc-2 glibc-headers glibc-devel \
@@ -121,7 +122,7 @@
 BUILDDIR := $(OUTPUT_ROOT)/$(HOST)/$(TARGET)
 PREFIX := $(RESULT)/$(HOST)
 TARGETDIR := $(PREFIX)/$(TARGET)
-SYSROOT := $(TARGETDIR)/sys-root
+SYSROOT := $(TARGETDIR)/sysroot
 DOWNLOAD := $(OUTPUT_ROOT)/download
 SRCDIR := $(OUTPUT_ROOT)/src
 
@@ -184,7 +185,7 @@
 
 ##########################################################################################
 
-# Note: MUST create a <sys-root>/usr/lib even if not really needed.
+# Note: MUST create a <sysroot>/usr/lib even if not really needed.
 # gcc will use a path relative to it to resolve lib64. (x86_64).
 # we're creating multi-lib compiler with 32bit libc as well, so we should
 # have it anyway, but just to make sure...
@@ -459,15 +460,31 @@
 
 ##########################################################################################
 
+$(PREFIX)/devkit.info: FRC
+	@echo 'Creating devkit.info in the root of the kit'
+	rm -f $@
+	touch $@
+	echo '# This file describes to configure how to interpret the contents of this' >> $@
+	echo '# devkit' >> $@
+	echo '' >> $@
+	echo 'DEVKIT_NAME="$(gcc_ver) - $(LINUX_VERSION)"' >> $@
+	echo 'DEVKIT_TOOLCHAIN_PATH="$$DEVKIT_ROOT/bin"' >> $@
+	echo 'DEVKIT_SYSROOT="$$DEVKIT_ROOT/$$host/sysroot"' >> $@
+
+##########################################################################################
+
 bfdlib : $(bfdlib)
 binutils : $(binutils)
 rpms : $(rpms)
 libs : $(libs)
 sysroot : rpms libs
 gcc : sysroot $(gcc) $(gccpatch)
-all : binutils gcc bfdlib
+all : binutils gcc bfdlib $(PREFIX)/devkit.info
 
 # this is only built for host. so separate.
 ccache : $(ccache)
 
+# Force target
+FRC:
+
 .PHONY : gcc all binutils bfdlib link_libs rpms libs sysroot